Skip to content

Commit 7cd97e9

Browse files
committed
docs: rebuild the documentation around reader tasks
The docs were organised around the framework's own parts. Nine pages, each named after a thing — Configuration, Frontmatter, Components, Themes — so a reader who arrived with a job had to guess which noun held the answer. Twenty-four pages in six groups now, named after the jobs: start here, writing docs, guides, themes, reference, deploy and operate. `features.mdx` is gone. It was doing three jobs at once: a marketing bullet list, a feature index, and the only documentation in the whole site for five topics. Sorting and `meta.json` went to Navigation, redirects to Links and redirects, markdown URLs and `llms.txt` to Generated routes, the playground to API reference, health checks to Monitoring. What was left became an Introduction. Versioning, API references and deployment each had a config key and a bullet and no guide, despite being three of the strongest reasons to pick Chronicle. Deployment was the sharpest case: the last step of the job was three words in a config reference. They have guides now, along with search, multiple content sections, and moving an existing docs site over. `configuration.mdx` was 468 lines, nearly a third of the site, and was where people were forced to learn versioning and API specs because there was nowhere else. It is a reference again, with a link to the guide for each large key. The frontmatter page leads with a table, and its `draft` section is no longer pasted into the middle of `authors`, which had split that field's prose in half. Writing the guides meant reading the source, which turned up four things the docs had wrong. Only three deploy presets were listed where the code has eight, four of them static. Search was called "powered by Fumadocs" on one page and "SQLite FTS5" on another; it is SQLite full-text search on a server build and a downloaded index in the browser on a static one, which decides how large a static site can sensibly get. A static build is a single-page app rather than pre-rendered HTML, so a host has to rewrite unknown paths to `index.html` — undocumented, and the usual reason a deep link 404s. And it optimises images at build time, which the old page denied. Seven permanent redirects cover every URL that moved, so no existing link breaks. `url` is set, which the sitemap, canonical tags and social cards all needed and none of them had. Content elsewhere gets the same treatment as the pages: every file opened with an `# H1` repeating its own frontmatter title, so both examples and the `init` scaffold showed the same words twice. Removed, and the rule is written down under `title` in the frontmatter reference. The one exception is the basic example's heading-levels demo, which now starts at `##` and says why.
1 parent df3e048 commit 7cd97e9

50 files changed

Lines changed: 2177 additions & 367 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/chronicle.yaml‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ site:
22
title: Chronicle
33
description: Config-driven documentation framework
44

5+
url: https://chronicle.raystack.org
6+
57
content:
68
- dir: docs
79
label: Docs
@@ -18,6 +20,30 @@ search:
1820
enabled: true
1921
placeholder: Search docs...
2022

23+
# The docs were reorganised into groups. These keep every old link working.
24+
redirects:
25+
- from: /docs/features
26+
to: /docs
27+
permanent: true
28+
- from: /docs/cli
29+
to: /docs/reference/cli
30+
permanent: true
31+
- from: /docs/configuration
32+
to: /docs/reference/config
33+
permanent: true
34+
- from: /docs/frontmatter
35+
to: /docs/reference/frontmatter
36+
permanent: true
37+
- from: /docs/components
38+
to: /docs/writing/components
39+
permanent: true
40+
- from: /docs/image-optimization
41+
to: /docs/writing/images
42+
permanent: true
43+
- from: /docs/docker
44+
to: /docs/deploy/docker
45+
permanent: true
46+
2147
telemetry:
2248
enabled: true
2349

‎docs/content/docs/deploy/build.mdx‎

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
title: Build and serve
3+
description: What a production build produces, and how presets change it.
4+
order: 1
5+
---
6+
7+
```bash
8+
chronicle build
9+
chronicle start
10+
```
11+
12+
`build` writes the production site. `start` serves what `build` produced — it
13+
does not build for you, so the order matters. `chronicle serve` runs both, which
14+
is handy locally and wrong in a deployment, where you want the build to happen
15+
once and the server to start many times.
16+
17+
## Two kinds of output
18+
19+
The `preset` decides which you get, and it is the only decision that really
20+
matters here.
21+
22+
**A server build** produces a small server. Pages are rendered per request,
23+
which is what makes search, image resizing and the API request tester work.
24+
This is the default.
25+
26+
**A static build** produces a single-page app: one `index.html`, a JavaScript
27+
bundle, and a small JSON file per page that the app fetches as the reader
28+
navigates. There is no process to run and nothing to keep alive.
29+
30+
```yaml
31+
preset: static
32+
```
33+
34+
Or per build:
35+
36+
```bash
37+
chronicle build --preset static
38+
```
39+
40+
## What you give up going static
41+
42+
There is no server, so the parts that needed one change:
43+
44+
| | Server build | Static build |
45+
|---|---|---|
46+
| Page HTML | Rendered per request, works with JavaScript off | One shell; pages filled in by JavaScript |
47+
| Search | Queried per request | Whole index downloaded, searched in the browser |
48+
| Images | Resized on demand, then cached | Resized once, during the build |
49+
| API request tester | Proxies through your server | Not available |
50+
| Health and readiness | `/api/health`, `/api/ready` | Not available |
51+
| Redirects | Served by Chronicle | Your host has to do them |
52+
53+
Everything else is generated either way: navigation, versions, the API
54+
reference, markdown URLs, `llms.txt`, the sitemap and social cards.
55+
56+
The first row matters most. A server build sends finished HTML, so a crawler or
57+
a reader with JavaScript off gets the page. A static build sends a shell, so
58+
they get very little. If search ranking matters to you, that is the argument for
59+
a server build.
60+
61+
Pick static for a small or medium site you want on a CDN with nothing to
62+
operate. Pick a server build for a large site, when search needs to stay fast,
63+
or when the request tester matters.
64+
65+
## Where the output goes
66+
67+
| Preset | Output directory |
68+
|---|---|
69+
| unset, `node-server`, `cloudflare` | `.output/` |
70+
| `static`, `cloudflare-pages`, `github-pages` | `.output/public/` |
71+
| `vercel`, `vercel-static` | `.vercel/output/` |
72+
73+
A static host has to send unknown paths to `index.html`, because every page
74+
shares that one file. Getting this wrong is the usual reason a deep link 404s
75+
while the home page works — see [Deploy](/docs/deploy/hosting).
76+
77+
Gitignore whichever applies. `chronicle init` adds `.output` for you.
78+
79+
## Build failures
80+
81+
The build stops on a page it cannot parse, and names the file and the line. This
82+
is deliberate — a docs site that silently drops a broken page is worse than one
83+
that refuses to build.
84+
85+
The usual cause is MDX being stricter than markdown about `<` and `{`, which it
86+
reads as the start of a component or an expression. Wrap the character in
87+
backticks.
88+
89+
## In CI
90+
91+
```bash
92+
bun install
93+
bun run chronicle build --preset static
94+
```
95+
96+
Then publish the output directory. The build needs no network access beyond
97+
installing packages, and no services.
98+
99+
If your build machine is not the machine that serves the site, remember `start`
100+
needs the `.output/` directory that `build` wrote — copy it, or build on the
101+
host.
102+
103+
## Next
104+
105+
- [Deploy](/docs/deploy/hosting) — putting the output on a host
106+
- [Docker](/docs/deploy/docker) — running from the container image
107+
- [Monitoring](/docs/deploy/monitoring) — health checks and metrics
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
---
22
title: Docker
3-
description: Run Chronicle with Docker.
4-
order: 8
3+
description: Run Chronicle from the official container image.
4+
order: 3
55
---
66

7-
# Docker
8-
97
Chronicle is available as a Docker image on [Docker Hub](https://hub.docker.com/r/raystack/chronicle).
108

119
## Pull the Image
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
---
2+
title: Deploy
3+
description: Put a built site on Vercel, Cloudflare, a Node host, or any static host.
4+
order: 2
5+
---
6+
7+
Pick the preset that matches your host, build, and publish the output. The
8+
preset is the only Chronicle-specific part — everything after it is your host's
9+
normal workflow.
10+
11+
Set it in the config so every build agrees:
12+
13+
```yaml
14+
preset: vercel
15+
```
16+
17+
Or pass it per build, which is what you want if the same repository deploys to
18+
more than one place:
19+
20+
```bash
21+
chronicle build --preset static
22+
```
23+
24+
## Vercel
25+
26+
```yaml
27+
preset: vercel
28+
```
29+
30+
```bash
31+
chronicle build
32+
```
33+
34+
The build writes `.vercel/output`, which is the directory Vercel deploys
35+
directly. Set the build command to `chronicle build` and leave the output
36+
directory at its default.
37+
38+
For a site that does not need per-request search or the API request tester, use
39+
`vercel-static` instead. Same output location, built as a single-page app.
40+
41+
## Cloudflare
42+
43+
For Workers:
44+
45+
```yaml
46+
preset: cloudflare
47+
```
48+
49+
The build writes `.output/`. Deploy it with Wrangler.
50+
51+
For Pages, use the static preset built for it:
52+
53+
```yaml
54+
preset: cloudflare-pages
55+
```
56+
57+
That writes `.output/public/`. Point your Pages project at that directory.
58+
59+
## A Node host
60+
61+
Any host that runs a Node process — a VM, a container platform, a PaaS.
62+
63+
```yaml
64+
preset: node-server
65+
```
66+
67+
```bash
68+
chronicle build
69+
chronicle start --port 3000 --host 0.0.0.0
70+
```
71+
72+
`--host 0.0.0.0` matters. The default binds to localhost, which works on your
73+
machine and refuses connections from outside a container.
74+
75+
Point the platform's health check at `/api/health`, and its readiness check at
76+
`/api/ready` if it has a separate one. See
77+
[Monitoring](/docs/deploy/monitoring).
78+
79+
There is a container image if you would rather not build your own — see
80+
[Docker](/docs/deploy/docker).
81+
82+
## GitHub Pages
83+
84+
```yaml
85+
preset: github-pages
86+
```
87+
88+
The build writes `.output/public/`. A workflow that builds and publishes it:
89+
90+
```yaml
91+
name: docs
92+
on:
93+
push:
94+
branches: [main]
95+
96+
permissions:
97+
contents: read
98+
pages: write
99+
id-token: write
100+
101+
jobs:
102+
build:
103+
runs-on: ubuntu-latest
104+
steps:
105+
- uses: actions/checkout@v4
106+
- uses: oven-sh/setup-bun@v2
107+
- run: bun install
108+
- run: bun run chronicle build --preset github-pages
109+
# GitHub Pages cannot rewrite unknown paths, but it does serve 404.html
110+
# for them — so a copy of the app shell makes deep links work.
111+
- run: cp .output/public/index.html .output/public/404.html
112+
- uses: actions/upload-pages-artifact@v3
113+
with:
114+
path: .output/public
115+
deploy:
116+
needs: build
117+
runs-on: ubuntu-latest
118+
environment: github-pages
119+
steps:
120+
- uses: actions/deploy-pages@v4
121+
```
122+
123+
## Any other static host
124+
125+
```yaml
126+
preset: static
127+
```
128+
129+
`chronicle build` writes `.output/public/`. Upload it to S3, Netlify, a CDN, or
130+
an nginx document root. There is nothing to run.
131+
132+
### Send unknown paths to index.html
133+
134+
This one step catches most people. A static build is a single-page app, so every
135+
page is served by the same `index.html`. Without a rewrite rule the home page
136+
works and `/docs/quick-start` returns a 404.
137+
138+
On nginx:
139+
140+
```nginx
141+
location / {
142+
try_files $uri $uri/ /index.html;
143+
}
144+
```
145+
146+
On Netlify, a `_redirects` file in the published directory:
147+
148+
```
149+
/* /index.html 200
150+
```
151+
152+
Most CDNs call this a "SPA fallback" or "rewrite to index". Whatever the name,
153+
it is the same rule.
154+
155+
## Set `url` before you ship
156+
157+
```yaml
158+
url: https://docs.example.com
159+
```
160+
161+
Without it there are no absolute URLs for the sitemap, no canonical link tags,
162+
and no social cards — a social network needs an absolute address to fetch a card
163+
image from. It is the single easiest thing to forget and the one most visible
164+
once the site is public.
165+
166+
## Redirects survive the move
167+
168+
If your docs used to live somewhere else, or you moved pages during the
169+
migration, `redirects` in the config are served by Chronicle itself. They work
170+
the same on every server preset.
171+
172+
Static presets have no server to run them, so on a static host use the host's
173+
own redirect mechanism — the same place you configured the rewrite above. See
174+
[Links and redirects](/docs/writing/links).
175+
176+
## A checklist
177+
178+
Before you call it done:
179+
180+
- `url` is set
181+
- `/sitemap.xml` and `/robots.txt` return something sensible
182+
- Search finds a page you know exists
183+
- A shared link shows a social card
184+
- Old URLs still resolve, if any moved
185+
- Health check points at `/api/health`, on a server build
186+
- A deep link like `/docs/quick-start` loads directly, on a static build

‎docs/content/docs/deploy/meta.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "title": "Deploy and operate", "order": 8 }

0 commit comments

Comments
 (0)