Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
8822ecd
feat: add versioned multi-content config schema
rsbh Apr 21, 2026
223a75f
feat: rewrite config loader for multi-content + versions
rsbh Apr 21, 2026
65f3321
chore: add test script using bun's built-in runner
rsbh Apr 21, 2026
bfa17f3
test: cover config schema + loader helpers
rsbh Apr 21, 2026
6105ac6
refactor: use lodash/uniqBy for dir uniqueness check
rsbh Apr 21, 2026
f58dd83
refactor: thread projectRoot through CLI instead of contentDir
rsbh Apr 21, 2026
bbc6fa2
feat: build multi-content + versioned .content mirror
rsbh Apr 21, 2026
1a290c8
feat: add version-aware selectors to source
rsbh Apr 21, 2026
bcf18e6
test: cover content mirror scaffold
rsbh Apr 21, 2026
913e8d0
test: cover version-aware source filters
rsbh Apr 21, 2026
88255cd
feat: add pure route resolver for multi-content + versions
rsbh Apr 21, 2026
e8bb0c5
refactor: expose RouteType enum for route classifier
rsbh Apr 21, 2026
0e7c002
feat: apply version-aware routing in SSR + client
rsbh Apr 21, 2026
8f6cfed
fix: wire initialVersion into hydration + guard redirect narrowing
rsbh Apr 21, 2026
8a145ea
feat: multi-content landing page for docs-index route
rsbh Apr 21, 2026
4067ff8
feat: per-version API specs
rsbh Apr 21, 2026
ef102e8
feat: version-aware server routes (llms, sitemap, og)
rsbh Apr 21, 2026
ab59b24
fix: remaining config.title references + init template
rsbh Apr 21, 2026
9ad768d
feat!: move description under site
rsbh Apr 21, 2026
2e445b2
chore: migrate docs/ to new content layout
rsbh Apr 21, 2026
80eb120
feat: inject synthetic meta.json per content root
rsbh Apr 21, 2026
5530ca8
feat: nav helpers for version + content-dir selectors
rsbh Apr 21, 2026
f525964
feat: version switcher + content-dir buttons in default theme
rsbh Apr 21, 2026
6404355
feat: version switcher + content-dir dropdown in paper theme
rsbh Apr 21, 2026
5735642
feat: opt-in landing page via latest.landing / versions[].landing
rsbh Apr 21, 2026
6d1945c
feat: chromeless landing page (no sidebar)
rsbh Apr 21, 2026
0c44a6d
chore: versioned example opts into landing pages
rsbh Apr 21, 2026
8e0d069
fix: drop node:path from config.ts for browser compat
rsbh Apr 21, 2026
c61e302
fix: switchers use DropdownMenu (apsara 0.55 export)
rsbh Apr 21, 2026
30db12a
feat: filterPageTreeByContentDir for per-content sidebar scope
rsbh Apr 21, 2026
6b7a8d8
chore: add dev/build scripts for examples
rsbh Apr 21, 2026
9bcb75e
feat: per-version search index
rsbh Apr 21, 2026
b99f487
feat: canonical URL in Head
rsbh Apr 21, 2026
629856d
test: cover chronicle init scaffolding
rsbh Apr 21, 2026
0b5d138
chore: migrate examples/basic to new content layout
rsbh Apr 21, 2026
d03cc93
docs: rewrite configuration reference for new schema
rsbh Apr 21, 2026
8b95ee8
docs: add migration guide
rsbh Apr 21, 2026
5f4ca2e
revert: drop migration guide from published docs
rsbh Apr 21, 2026
70f1440
ci: add lint + test workflow for PRs
rsbh Apr 21, 2026
aa74f41
fix: mirror content with per-file symlinks so prod build finds pages
rsbh Apr 21, 2026
c09b0f9
fix: add --config flag to chronicle start
rsbh Apr 21, 2026
cde1931
feat: reject '.', '..', and path-shaped dir names
rsbh Apr 21, 2026
8fcd6c7
fix: update vercel output path
rsbh Apr 21, 2026
477e8f6
feat: validate content/version dir overlap + reserved route segments
rsbh Apr 21, 2026
df16866
fix: harden buildLlmsTxt against missing title + empty description
rsbh Apr 21, 2026
1abbf2b
refactor: address coderabbit review findings
rsbh Apr 21, 2026
aeaacbe
ci: pin bun to 1.3.9 to keep lockfile reproducible
rsbh Apr 21, 2026
c223ba8
chore: sync lockfile after rebase on main
rsbh Apr 21, 2026
5fdec37
refactor: address minor coderabbit review findings
rsbh Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: ci

on:
pull_request:
push:
branches: [main]

jobs:
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: ./packages/chronicle
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.9

- name: Install dependencies
run: bun install --frozen-lockfile
working-directory: .

- name: Lint
run: bun run lint

- name: Test
run: bun test
224 changes: 92 additions & 132 deletions bun.lock

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions docs/chronicle.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
title: Chronicle
description: Config-driven documentation framework
content: .
site:
title: Chronicle
description: Config-driven documentation framework

content:
- dir: docs
label: Docs

theme:
name: paper
Expand All @@ -20,6 +24,8 @@ llms:
telemetry:
enabled: true

preset: "vercel"

footer:
copyright: "© 2026 Raystack. All rights reserved."
links:
Expand Down
File renamed without changes.
File renamed without changes.
181 changes: 143 additions & 38 deletions docs/configuration.mdx → docs/content/docs/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,34 @@ order: 3

# Configuration

All site configuration lives in a single `chronicle.yaml` file in your project root. The config is validated using Zod — invalid fields will produce clear error messages at startup.
All site configuration lives in a single `chronicle.yaml` file in your project root. The config is validated using Zod — invalid fields produce clear errors at startup.

## Full Example
## Project layout

```
my-docs-site/
├── chronicle.yaml
├── content/ ← latest
│ ├── docs/
│ └── dev/
└── versions/ ← only if versions: is declared
├── v2/
│ └── docs/
└── v1/
├── docs/
└── dev/
```

Content dirs declared in `content:` are resolved under `content/` for the latest version; each `versions[].content[]` entry is resolved under `versions/<version-dir>/`.

## Full example

```yaml
title: My Project Docs
description: Documentation for My Project
site:
title: My Project Docs
description: Documentation for My Project

url: https://docs.example.com
content: docs
preset: vercel

logo:
Expand All @@ -24,12 +43,45 @@ logo:
theme:
name: default

content:
- dir: docs
label: Docs
- dir: dev
label: Dev Docs

latest:
label: "3.0"
landing: true

versions:
- dir: v2
label: "2.0"
content:
- dir: docs
label: Docs

- dir: v1
label: "1.0"
landing: true
badge:
label: deprecated
variant: warning
content:
- dir: dev
label: Developer Guide
- dir: docs
label: Docs
api:
- name: REST API (v1)
spec: ./v1-openapi.yaml
basePath: /apis
server:
url: https://api.example.com/v1

navigation:
links:
- label: GitHub
href: https://github.com/myorg/myproject
- label: Blog
href: https://blog.example.com

search:
enabled: true
Expand All @@ -40,8 +92,6 @@ footer:
links:
- label: GitHub
href: https://github.com/myorg/myproject
- label: License
href: /license

api:
- name: REST API
Expand Down Expand Up @@ -71,49 +121,108 @@ telemetry:

## Reference

### title
### site

**Required.** The site title displayed in the navbar and browser tab.
**Required.** Site-level metadata.

```yaml
title: My Documentation
site:
title: My Documentation
description: Documentation powered by Chronicle
```

| Field | Type | Description |
|-------|------|-------------|
| `title` | `string` | Site title (navbar, browser tab, canonical metadata). Required. |
| `description` | `string` | Meta description for SEO and OG. |

### url

Optional site URL. Used for SEO metadata, sitemap, and canonical URLs.
Optional site URL used for the sitemap and canonical URLs.

```yaml
url: https://docs.example.com
```

### content

Optional content directory path. Can be overridden by the `--content` CLI flag.
**Required.** Content dirs for the latest version. Each entry maps to `content/<dir>/` on disk and to `/<dir>/...` in URLs.

```yaml
content: docs
content:
- dir: docs
label: Docs
- dir: dev
label: Dev Docs
```

### preset
| Field | Type | Description |
|-------|------|-------------|
| `dir` | `string` | Folder name under `content/`. Must be unique. |
| `label` | `string` | Display label in navigation and landing pages. |

### latest

Optional deploy preset. Can be overridden by the `--preset` CLI flag.
Optional metadata for the latest version. Required when `versions:` is declared.

```yaml
preset: vercel # vercel, cloudflare, or node-server
latest:
label: "3.0"
landing: true
```

### description
| Field | Type | Description | Default |
|-------|------|-------------|---------|
| `label` | `string` | Version label (e.g. `3.0`). Shown in the version switcher. | — |
| `landing` | `boolean` | `true` → `/` renders a landing page listing content dirs. `false` (default) → `/` 302s to the first content dir. | `false` |

Optional meta description for SEO.
### versions

Optional list of older versions. Each entry lives under `versions/<dir>/` on disk and is reachable at `/<dir>/...` in URLs.

```yaml
description: Documentation powered by Chronicle
versions:
- dir: v1
label: "1.0"
landing: true
badge:
label: deprecated
variant: warning
content:
- dir: dev
label: Developer Guide
- dir: docs
label: Docs
api:
- name: REST API (v1)
spec: ./v1-openapi.yaml
basePath: /apis
server:
url: https://api.example.com/v1
```

| Field | Type | Description |
|-------|------|-------------|
| `dir` | `string` | Folder name under `versions/`. Doubles as URL prefix. Must be unique. |
| `label` | `string` | Version label. Shown in the switcher. |
| `landing` | `boolean` | `true` → `/<dir>` renders a landing page; otherwise 302s to the version's first content dir. Default `false`. |
| `badge` | `object` | Optional Apsara badge next to the version label. |
| `badge.label` | `string` | Badge text. |
| `badge.variant` | `"accent" \| "warning" \| "danger" \| "success" \| "neutral" \| "gradient"` | Badge colour. Default `accent`. |
| `content` | `{dir, label}[]` | Content dirs for this version. Entries may rename, reorder, or omit top-level content dirs. |
| `api` | `ApiConfig[]` | Version-scoped API specs, rendered at `/<dir>/apis/...`. Same shape as top-level `api:`. |

### preset

Optional deploy preset. Can be overridden by `--preset`.

```yaml
preset: vercel # vercel, cloudflare, or node-server
```

### logo

Logo configuration with theme-aware variants.
Logo with theme-aware variants.

```yaml
logo:
Expand Down Expand Up @@ -151,13 +260,9 @@ navigation:
links:
- label: GitHub
href: https://github.com/myorg/myproject
- label: API
href: /apis
social:
- type: github
href: https://github.com/myorg/myproject
- type: discord
href: https://discord.gg/example
```

**navigation.links**
Expand All @@ -176,7 +281,7 @@ navigation:

### search

Search functionality powered by Fumadocs.
Search functionality powered by Fumadocs. Automatically scoped to the active version.

```yaml
search:
Expand All @@ -189,7 +294,7 @@ search:
| `enabled` | `boolean` | Enable/disable search | `true` |
| `placeholder` | `string` | Search input placeholder | `Search...` |

When enabled, search is accessible via the navbar button or keyboard shortcut `Cmd+K` / `Ctrl+K`.
When enabled, search is accessible via the navbar button or keyboard shortcut `Cmd+K` / `Ctrl+K`. Active version comes from the URL; switching versions scopes the index.

### footer

Expand All @@ -212,7 +317,7 @@ footer:

### api

OpenAPI specification configuration for interactive API documentation.
OpenAPI specification configuration at the top level applies to the latest version (served at `/apis/...`). Version-scoped specs live under each `versions[].api`.

```yaml
api:
Expand All @@ -228,8 +333,6 @@ api:
placeholder: Enter your API key
```

Each entry in the `api` array creates a section of API documentation.

| Field | Type | Description |
|-------|------|-------------|
| `name` | `string` | API display name |
Expand All @@ -241,11 +344,9 @@ Each entry in the `api` array creates a section of API documentation.
| `auth.header` | `string` | Header name for auth token |
| `auth.placeholder` | `string` | Placeholder text in auth input |

API pages include a "Try it out" panel that uses the configured server URL and auth settings.

### llms

Configuration for LLM-friendly content generation. When enabled, Chronicle generates `/llms.txt` and `/llms-full.txt` endpoints.
Per-version `llms.txt` generation.

```yaml
llms:
Expand All @@ -254,7 +355,7 @@ llms:

| Field | Type | Description | Default |
|-------|------|-------------|---------|
| `enabled` | `boolean` | Enable/disable LLM content endpoints | `false` |
| `enabled` | `boolean` | Emit `/llms.txt` and `/<version-dir>/llms.txt` | `false` |

### analytics

Expand All @@ -274,7 +375,7 @@ analytics:

### telemetry

Prometheus metrics export via OpenTelemetry. When enabled, metrics are served on a separate port.
Prometheus metrics export via OpenTelemetry. Served on a separate port.

```yaml
telemetry:
Expand All @@ -293,10 +394,14 @@ Metrics are available at `http://localhost:<port>/metrics` in Prometheus exposit

## Defaults

If `chronicle.yaml` is missing or fields are omitted, these defaults apply:
When `chronicle.yaml` is missing or fields are omitted, these defaults apply:

```yaml
title: Documentation
site:
title: Documentation
content:
- dir: docs
label: Docs
theme:
name: default
search:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading