Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
158 commits
Select commit Hold shift + click to select a range
b95835f
chore: declare the nuxt stack instead of a playground override
TitusKirch Sep 2, 2026
747ef4b
refactor: make the repo root the layer, with www beside it
TitusKirch Sep 2, 2026
71b0231
build: hold TypeScript at 6 so the layer can be typechecked
TitusKirch Sep 2, 2026
6c30b5f
build: pin the whole graph to the TypeScript 6 line
TitusKirch Sep 2, 2026
6f4309f
fix: look for docs at the repository root, not the site root
TitusKirch Sep 2, 2026
66cb751
docs: explain where a project's docs and its site live
TitusKirch Sep 2, 2026
0020313
feat: set up shadcn-vue, Tailwind and the base theme
TitusKirch Sep 2, 2026
30c7fe5
feat: add the documentation shell — header, navigation, page and TOC
TitusKirch Sep 2, 2026
319267d
feat: ship callout and steps components for Markdown
TitusKirch Sep 2, 2026
fd72d4a
docs: record the theme setup and the layer path traps
TitusKirch Sep 2, 2026
0c9902d
fix: keep reka-ui to one copy so SSR survives a production build
TitusKirch Sep 2, 2026
0a66f85
feat: add the shadcn components the theme is built from
TitusKirch Sep 2, 2026
0fa43cb
feat: drive the navbar, landing and footer from app.config
TitusKirch Sep 2, 2026
fe77698
feat: split the landing page from the docs view
TitusKirch Sep 2, 2026
6e4e94e
feat: add code blocks, package-manager tabs, alerts and a file tree
TitusKirch Sep 2, 2026
96bffa0
feat: give headings anchors and calm the prose down
TitusKirch Sep 2, 2026
68c8d37
docs: demonstrate the new components in the docs themselves
TitusKirch Sep 2, 2026
b9674c7
fix: render icons as svg and rebuild the package-manager block
TitusKirch Sep 2, 2026
b57ca68
feat: lay the docs out the way nuxt.com does
TitusKirch Sep 2, 2026
b334a96
docs: split the docs into sections with real pages
TitusKirch Sep 2, 2026
ea361d7
fix: stop oxfmt from rewriting MDC blocks in docs/
TitusKirch Sep 2, 2026
4a7a1f4
feat: switch syntax highlighting on
TitusKirch Sep 2, 2026
c757cd0
fix: lay the callout out explicitly and colour the manager tabs
TitusKirch Sep 2, 2026
93a62af
feat: give files and code blocks an icon for their type
TitusKirch Sep 2, 2026
0152dca
feat: give each documentation section its own sidebar
TitusKirch Sep 2, 2026
308b4f3
fix: let the highlighted code actually reach the page
TitusKirch Sep 2, 2026
aad4649
fix: give the brand icons a colour per theme
TitusKirch Sep 2, 2026
e7eda61
feat: make every clickable surface react to the pointer
TitusKirch Sep 2, 2026
901c218
fix: make the section tabs and manager tabs behave like tabs
TitusKirch Sep 2, 2026
1ee6110
feat: quieten the callouts down
TitusKirch Sep 2, 2026
36a74d2
docs: add a guide section with nested pages
TitusKirch Sep 2, 2026
3fd6a3b
fix: bring the pointer cursor back
TitusKirch Sep 2, 2026
157ad4a
feat: make sidebar groups collapsible and tighten the tree
TitusKirch Sep 2, 2026
b3abf57
fix: stop the prose rules bleeding into the file tree and callouts
TitusKirch Sep 2, 2026
7b1b1d7
fix: stop the prose rules outranking the components inside them
TitusKirch Sep 2, 2026
c2aef15
fix: give dropdown entries a hover state
TitusKirch Sep 2, 2026
b9de4b7
feat: highlight the package-manager commands
TitusKirch Sep 3, 2026
7f6933c
feat: remember which package manager the reader picked
TitusKirch Sep 3, 2026
4777575
fix: stop a consumer's config lists being appended to the layer's
TitusKirch Sep 3, 2026
617a56b
fix: hold the footer at the bottom of the viewport, dvh not vh
TitusKirch Sep 3, 2026
cdc3087
feat: confirm a copy with a toast
TitusKirch Sep 3, 2026
1139664
fix: settle the package manager before the first frame
TitusKirch Sep 3, 2026
285a89b
feat: give the footer columns and a legal row
TitusKirch Sep 3, 2026
8cfa965
docs: point the aside at our own channels, and start a TODO
TitusKirch Sep 3, 2026
51a50e1
fix: give the toasts their stylesheet
TitusKirch Sep 3, 2026
6789b2c
fix: settle the package manager on the server, not after hydration
TitusKirch Sep 3, 2026
57b0a1b
feat: put Resources back in the navbar and fill the footer out
TitusKirch Sep 3, 2026
434a670
fix: carry the sections into the mobile navigation
TitusKirch Sep 3, 2026
e1a5b6a
docs: correct the typeset entry and log what is still open
TitusKirch Sep 3, 2026
cc0b15a
feat: replace the hand-written prose with shadcn/typeset
TitusKirch Sep 3, 2026
2b327e0
feat: give the toasts their four levels and status colours
TitusKirch Sep 3, 2026
eb4bbef
docs: tick off typeset and the escape hatch
TitusKirch Sep 3, 2026
6a6dc19
fix: drop the second icon library out of the generated components
TitusKirch Sep 3, 2026
e9e5430
feat: add previous/next, a breadcrumb and an active table of contents
TitusKirch Sep 3, 2026
6c5dd3e
feat: search the documentation with ⌘K
TitusKirch Sep 3, 2026
d8a7fd9
feat: give each section an overview, and fix the section row on mobile
TitusKirch Sep 3, 2026
42300ef
feat: serve llms.txt from the collection
TitusKirch Sep 3, 2026
6d7720e
chore: retire AI_SETUP.md and stop tracking the TODO list
TitusKirch Sep 3, 2026
2c38508
fix: keep prev/next inside its section and open the group the route l…
TitusKirch Sep 3, 2026
4e9acfc
fix: rebuild search on Content's own ranked index
TitusKirch Sep 3, 2026
acda174
feat: generate collections from a compact source list
TitusKirch Sep 3, 2026
afde35f
feat: serve a real MCP server instead of a JSON endpoint
TitusKirch Sep 3, 2026
e4eb96d
fix: make a search result one line, and lose the second close button
TitusKirch Sep 3, 2026
db217db
feat: group search hits by section, and give the empty dialog something
TitusKirch Sep 3, 2026
fea1be7
fix: let frontmatter icons reach the sidebar
TitusKirch Sep 3, 2026
682a4f4
fix: take the value away from the rule painting behind code tokens
TitusKirch Sep 3, 2026
0991753
feat: wire the theme to the generated collections
TitusKirch Sep 3, 2026
bb28b22
test: cover the layer's pure logic, and build the site in the gate
TitusKirch Sep 3, 2026
8924ad2
feat: run the development site on two repositories and two refs
TitusKirch Sep 3, 2026
a2b302b
fix: share one navigation query instead of five colliding ones
TitusKirch Sep 3, 2026
c69dd78
fix: keep Node APIs out of the browser, and find a prefixed section
TitusKirch Sep 4, 2026
112a112
fix: stop the navbar default forcing consumers to rewrite it
TitusKirch Sep 4, 2026
d149d70
fix: let wide blocks scroll instead of the page
TitusKirch Sep 4, 2026
b58c4b0
fix: keep the sidebar on the source the route is in
TitusKirch Sep 4, 2026
72e2578
fix: match the longest version prefix, not the first
TitusKirch Sep 4, 2026
8137bb0
fix: unwrap the extra level a version prefix adds to the tree
TitusKirch Sep 4, 2026
b8395c6
fix: keep dots in version URLs, and stop showing two version systems
TitusKirch Sep 4, 2026
d08ed4f
test: cover versioning, and move its logic where it can be tested
TitusKirch Sep 4, 2026
057a8ef
feat: one version control, beside the search, in a header that holds …
TitusKirch Sep 4, 2026
7e5d949
docs: give the documentation root a page
TitusKirch Sep 4, 2026
48035c2
fix: show the breadcrumb on a section root too
TitusKirch Sep 4, 2026
f974377
chore: move to pnpm 12.3.4
TitusKirch Sep 5, 2026
b903ac1
ci: call the shared workflow bodies at v0.8.0
TitusKirch Sep 5, 2026
25ce246
fix: stop the breadcrumb listing a section twice
TitusKirch Sep 5, 2026
67e69a3
feat: speak the reader's language, and configure duxt in one file
TitusKirch Sep 5, 2026
da4d403
chore: add the modules and tools the theme now builds on
TitusKirch Sep 5, 2026
e862ba3
feat: carry a version's lifecycle, origin and newest tag through the …
TitusKirch Sep 5, 2026
a435c8a
feat: tell the reader which version of the documentation they are in
TitusKirch Sep 5, 2026
66e105d
feat: say when a page last changed and who wrote it
TitusKirch Sep 5, 2026
f29c228
feat: report what the build would otherwise swallow
TitusKirch Sep 5, 2026
86c138d
feat: show the resolved sources in a devtools tab
TitusKirch Sep 5, 2026
49b3733
feat: redirect a page that moved
TitusKirch Sep 5, 2026
848ffd2
feat: describe every page to crawlers, models and social cards
TitusKirch Sep 5, 2026
faf246e
feat: publish a changelog feed
TitusKirch Sep 5, 2026
1d72e71
feat: hand a page to a model in one click
TitusKirch Sep 5, 2026
3c42609
feat: keep partials and drafts out of the page collections
TitusKirch Sep 5, 2026
6edd5ec
feat: add the Markdown components a reference page needs
TitusKirch Sep 5, 2026
5499107
feat: search every source at once
TitusKirch Sep 5, 2026
81671ac
feat: move through the docs by keyboard
TitusKirch Sep 5, 2026
d0149ff
feat: suggest the nearest page on a 404
TitusKirch Sep 5, 2026
67b7136
feat: ask whether a page helped, and store nothing
TitusKirch Sep 5, 2026
adb509d
fix: stop the layer shipping kirchDev's own links to every consumer
TitusKirch Sep 5, 2026
3a0602c
fix: give every landmark a name and the keyboard a way in
TitusKirch Sep 5, 2026
e843344
test: check the built site for accessibility regressions
TitusKirch Sep 5, 2026
4cc3383
chore: exercise four version states on the development site
TitusKirch Sep 5, 2026
ad84fec
docs: document everything the layer now ships
TitusKirch Sep 5, 2026
a6d00e1
refactor: split the validator's checks out of its module
TitusKirch Sep 6, 2026
b60327d
feat: give the devtools tab a panel per question
TitusKirch Sep 6, 2026
529a08f
feat: read a remote source's history instead of its shallow clone
TitusKirch Sep 6, 2026
5c94b5d
fix: raise three palette pairs to AA
TitusKirch Sep 6, 2026
36069c3
fix: keep the approximate search across every source
TitusKirch Sep 6, 2026
d59a192
fix: link a tagged version to its source, not to an edit form
TitusKirch Sep 6, 2026
42dd32b
feat: make the devtools tab readable at a glance
TitusKirch Sep 6, 2026
886e4f7
fix: give the navbar's docs entry a destination
TitusKirch Sep 6, 2026
19cfd80
fix: stop registering the layer's server routes twice
TitusKirch Sep 6, 2026
37690fb
feat: name the layer and its version in the footer
TitusKirch Sep 6, 2026
c6c8969
fix: stop the footer repeating the navbar's icon links
TitusKirch Sep 6, 2026
1c1d5e7
docs: rewrite the documentation as a sectioned tree
TitusKirch Sep 6, 2026
4c19572
chore: follow the renamed docs sections on the development site
TitusKirch Sep 6, 2026
17d2283
docs: rewrite the README around what the layer now ships
TitusKirch Sep 6, 2026
74fb76a
fix: stop shipping duxt's own docs structure as a layer default
TitusKirch Sep 6, 2026
86b653e
fix: stop the active sidebar entry reflowing onto a second line
TitusKirch Sep 6, 2026
b52d009
docs: shorten the guide titles to their own slugs
TitusKirch Sep 6, 2026
b44ccc7
docs: render every MDC component on its own reference page
TitusKirch Sep 6, 2026
691fa5d
docs: step through the guides with the steps component
TitusKirch Sep 6, 2026
6c5a6f2
docs: show the docs folder as a tree on the installation page
TitusKirch Sep 6, 2026
b1c90ab
docs: stop claiming Content resolves a locale from the file
TitusKirch Sep 6, 2026
270094d
fix: put the steps component's markers back on their rail
TitusKirch Sep 6, 2026
96728ee
fix: stop the version and locale menus filling the window
TitusKirch Sep 6, 2026
690f7ee
fix: centre the footer's powered-by line
TitusKirch Sep 6, 2026
4bffd68
fix: tell the browser which theme the page is in
TitusKirch Sep 6, 2026
f50087b
fix: resolve a text key that carries a structure
TitusKirch Sep 6, 2026
7d74227
feat: show a component's source beside the component
TitusKirch Sep 6, 2026
9484460
fix: translate the copy confirmation
TitusKirch Sep 6, 2026
7f46f1d
feat: rebuild the landing page around a live preview
TitusKirch Sep 6, 2026
6c3da98
chore: fill the landing page's new keys on the development site
TitusKirch Sep 6, 2026
9ccae52
docs: describe the preview block and the landing keys
TitusKirch Sep 6, 2026
58f9547
docs: explain how to collect page feedback
TitusKirch Sep 6, 2026
41e96a9
docs: credit what duxt is built on
TitusKirch Sep 6, 2026
9e36584
feat: dress the preview block and the landing frame like windows
TitusKirch Sep 6, 2026
d9cf4d0
docs: give every component, composable and endpoint its own page
TitusKirch Sep 6, 2026
5a466dd
feat: let a preview example stand as the page renders it
TitusKirch Sep 6, 2026
1165ae2
feat: build the preview block like the cards beside it
TitusKirch Sep 6, 2026
973cbe1
feat: drop the surface under a preview example
TitusKirch Sep 6, 2026
510c0ef
fix: keep a preview's source on the code surface
TitusKirch Sep 6, 2026
801df30
fix: give a preview one surface for both tabs
TitusKirch Sep 6, 2026
ef42d3e
feat: bundle the icons a docs tree names in its frontmatter
TitusKirch Sep 6, 2026
6da94cc
feat: drop the sidebar from a section that has one page
TitusKirch Sep 6, 2026
09ad10e
docs: make credits a section of its own
TitusKirch Sep 6, 2026
442436a
chore: drop the workflows source from the development site
TitusKirch Sep 6, 2026
26ab4aa
docs: credit Nuxt UI, not its pro tier
TitusKirch Sep 6, 2026
be13124
docs: call the layout the layout, not the chrome
TitusKirch Sep 6, 2026
6cf4598
fix: follow the development site's own URLs after the source went
TitusKirch Sep 6, 2026
6896470
fix: quote the frontmatter values that carry a colon
TitusKirch Sep 6, 2026
575d555
test: catch frontmatter YAML cannot read
TitusKirch Sep 6, 2026
aaad4e9
docs: group the components by what they do, not by where they sit
TitusKirch Sep 6, 2026
1e08d48
fix: close the two paths CodeQL found into git and the regex engine
TitusKirch Sep 6, 2026
f4f3de2
fix: let only a URL reach git ls-remote
TitusKirch Sep 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ permissions:
jobs:
check:
name: CI
uses: kirchDev/workflows/.github/workflows/_ci-check.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0
uses: kirchDev/workflows/.github/workflows/_ci-check.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
packages: read
actions: read
contents: read
uses: kirchDev/workflows/.github/workflows/_codeql.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0
uses: kirchDev/workflows/.github/workflows/_codeql.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0
2 changes: 1 addition & 1 deletion .github/workflows/fast-forward-queue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
pull-requests: read
checks: read
statuses: read
uses: kirchDev/workflows/.github/workflows/_fast-forward-queue.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0
uses: kirchDev/workflows/.github/workflows/_fast-forward-queue.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0
with:
pr: ${{ inputs.pr }}
secrets:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/promotion-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ permissions:
jobs:
promotion-pr:
name: Promotion PR
uses: kirchDev/workflows/.github/workflows/_promotion-pr.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0
uses: kirchDev/workflows/.github/workflows/_promotion-pr.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0
2 changes: 1 addition & 1 deletion .github/workflows/queue-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ jobs:
permissions:
contents: read
pull-requests: write
uses: kirchDev/workflows/.github/workflows/_queue-branch.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0
uses: kirchDev/workflows/.github/workflows/_queue-branch.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0
secrets:
BWS_ACCESS_TOKEN: ${{ secrets.BWS_ACCESS_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ jobs:
permissions:
contents: write
pull-requests: write
uses: kirchDev/workflows/.github/workflows/_release-please.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0
uses: kirchDev/workflows/.github/workflows/_release-please.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0
secrets:
BWS_ACCESS_TOKEN: ${{ secrets.BWS_ACCESS_TOKEN }}
19 changes: 13 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# region gitignore-sync
# stacks: core, git, node, vscode, intellij, macos, windows, linux, agents
# stacks: core, agents, git, node, nuxt, vscode, intellij, macos, windows, linux
# ─────────────────────────────────────────

# region core@v1
.DS_Store
# endregion

# region agents@v1
.claude/settings.local.json
.claude/worktrees/
# endregion

# region git@v1
*.orig
*.rej
Expand All @@ -31,6 +36,13 @@ coverage
*.tgz
# endregion

# region nuxt@v1
.nuxt
.output
.nitro
.data
# endregion

# region vscode@v1
.vscode/*
!.vscode/extensions.json
Expand Down Expand Up @@ -85,9 +97,4 @@ $RECYCLE.BIN/
.nfs*
# endregion

# region agents@v1
.claude/settings.local.json
.claude/worktrees/
# endregion

# endregion
4 changes: 3 additions & 1 deletion .oxfmtrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"pnpm-lock.yaml",
"README.md",
"CLAUDE.md",
"AGENTS.md"
"AGENTS.md",
"docs/**/*.md",
"www/content/**/*.md"
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"i18n-ally.localesPaths": ["i18n", "i18n/locales"]
}
31 changes: 23 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Retyping a change is exactly how the two drift; one reflowed line or reworded cl
> [!IMPORTANT]
> **Nothing here is decided.** `duxt` is at the idea stage — the repo currently carries the meta layer and nothing else. What follows is the working sketch plus the questions still open. Treat every "is" below as "is currently assumed"; do not harden any of it into code without asking.

The idea started in `kirchDev/greenhouse` as `ideas/nuxt-ai-docs.md`, where it is filed under that working title; `duxt` is the name it got here.

The sketch: `duxt` as a **Nuxt documentation layer on Nuxt Content v3**, published as `@kirchdev/duxt` and consumed with one line:

```ts
Expand All @@ -42,11 +44,20 @@ What that leaves as candidate value: the **ergonomics** (a compact `sources` lis

**Decided so far:**

- **The theme is shadcn-vue, wired through `shadcn-nuxt`** — a clean base with owned components, not Docus or Nuxt UI. No UI-Pro dependency, and the components are copied into the repo rather than imported, so overriding them is editing them.
- **Numbered section prefixes are a non-issue.** Content strips them itself: `1.guides/` renders at `/guides`, `99.adr/` at `/adr`. Verified in the playground. Reordering does not move a URL; only renaming the name part does.
- **No SQLite driver is installed.** Content's default is `better-sqlite3`, a native addon needing a node-gyp toolchain. `content.experimental.nativeSqlite` uses Node 24's built-in `node:sqlite` instead, which needs no package at all — the playground builds and renders with neither `better-sqlite3` nor `@libsql/client` present. It is flagged experimental in Content; if that changes, `@libsql/client` is the prebuilt fallback, not `better-sqlite3`.
- **The theme is shadcn-vue, wired through `shadcn-nuxt`** — a clean Tailwind 4 base with owned components in `app/components/ui/`, not Docus or Nuxt UI. Add one with `pnpm dlx shadcn-vue@latest add <name>`; `components.json` already points the CLI at the layer's own alias. The palette is the neutral shadcn set as CSS variables in `app/assets/css/duxt.css`, `dark` class toggled by `@nuxtjs/color-mode`; a consumer redefines a token in its own stylesheet rather than forking the file.
- **Markdown components are MDC, not MDX.** Content ships MDC, so `::callout{type="tip"}` works with no extra module. Components live in `app/components/content/`.
- **Numbered section prefixes are a non-issue.** Content strips them itself: `1.guides/` renders at `/guides`, `99.adr/` at `/adr`. Verified in `www/`. Reordering does not move a URL; only renaming the name part does.
- **No SQLite driver is installed.** Content's default is `better-sqlite3`, a native addon needing a node-gyp toolchain. `content.experimental.nativeSqlite` uses Node 24's built-in `node:sqlite` instead, which needs no package at all — `www/` builds and renders with neither `better-sqlite3` nor `@libsql/client` present. It is flagged experimental in Content; if that changes, `@libsql/client` is the prebuilt fallback, not `better-sqlite3`.

**Repo shape — the root IS the layer.** `nuxt.config.ts`, `content.config.ts` and `app/` sit at the repo root, and `package.json` points at them with `main: "./nuxt.config.ts"` plus a `files` allowlist, so `extends: ['@kirchdev/duxt']` resolves. `www/` is the consuming site beside it — the only workspace package, and the development target, exactly as `www/` is in `ZTL-UwU/shadcn-docs-nuxt`. `nuxt` is a peerDependency of the layer and a real dependency only of `www/`.

> [!IMPORTANT]
> **Nothing layer-relative resolves the way it reads.** Three places have hit this already, and a fourth will: the Content collection `cwd`, the `css` entry and `componentDir` in `nuxt.config.ts` (both go through the `layer()` helper resolving against `import.meta.url`), and the `@` alias — which belongs to whoever extends the layer, so the layer's own imports use `@duxt` instead. Assume any path written here is read from the consumer's directory until proven otherwise.

> [!IMPORTANT]
> **A layer's collections resolve against the LAYER, not the consumer.** Content sets `collection.__rootDir = curr.cwd` per layer, so a relative `source.cwd` in this repo's `content.config.ts` points into this repo — never into the site that extends it. The layer therefore computes an absolute path at load time (`join(process.cwd(), 'docs')`), which works because c12 executes the config. This is the seam the whole `sources` shorthand sits on.

If the layer is built, `playground/` is where it is developed and wants edge cases, ugly frontmatter, several sources and a tag to read from. [`kirchDev/duxt-starter`](https://github.com/kirchDev/duxt-starter) would be a **different artifact** — minimal and exemplary, what a stranger clones with `npx nuxi@latest init -t github:kirchDev/duxt-starter`. Do not conflate the two; a playground makes a bad starter.
`www/` wants edge cases, ugly frontmatter, several sources and a tag to read from. [`kirchDev/duxt-starter`](https://github.com/kirchDev/duxt-starter) would be a **different artifact** — minimal and exemplary, what a stranger clones with `npx nuxi@latest init -t github:kirchDev/duxt-starter`. Do not conflate the two; a development site makes a bad starter.

## Commands

Expand All @@ -56,22 +67,26 @@ If the layer is built, `playground/` is where it is developed and wants edge cas
| `pnpm lint` | `oxlint . --deny-warnings` |
| `pnpm format` | `oxfmt --check .` (note: `format` is the check, not fix) |
| `pnpm typecheck` | `tsc --noEmit` over the meta scripts |
| `pnpm check` | Runs `lint` + `format` + `typecheck` + `check:policy` — the CI gate |
| `pnpm typecheck:app`| `nuxt typecheck` over the layer, run through `www/` |
| `pnpm test` | `vitest run` over the layer's pure logic |
| `pnpm build:app` | `nuxt build` in `www/` — the gate's SSR check |
| `pnpm check` | Runs `lint` + `format` + both typechecks + `test` + `check:policy` + `build:app` + `check:a11y` — the CI gate |
| `pnpm check:policy` | Proves the two agent policy files ban the same commands |
| `pnpm check:a11y` | axe-core over five rendered pages of the built site |
| `pnpm lint:fix` | Auto-fix lint |
| `pnpm format:fix` | Auto-fix format |
| `pnpm check:fix` | Auto-fix lint + format |
| `pnpm skills:update`| Update project-scoped agent skills via the skills.sh CLI |
| `pnpm taze` | Interactive dependency upgrade check |
| `pnpm taze:w` | Write upgrade results |

There is no test suite yet — the repo currently carries only the meta layer. CI runs `pnpm lint`, `pnpm format`, `pnpm typecheck` and `pnpm check:policy` on PR; adding a check to the `check` script is enough, no workflow change needed.
Tests cover the layer's pure logic — the source resolver, the config merge, the icon lookup, the build validator, the redirect map, the 404's nearest-page scoring — in `tests/`, run by vitest. `tests/contrast.test.ts` is the odd one out and deliberate: it parses the palette out of `duxt.css` and measures every foreground against the background it is paired with, because that is the one accessibility rule `check:a11y` cannot answer (jsdom has no computed colour) and the one this theme actually broke. Component rendering is not covered: it needs a Nuxt environment, and the failures this repo actually had were SSR failures, which is why `check` builds the site instead. `check:a11y` then runs axe-core over that build: jsdom has no layout, so `color-contrast` and `target-size` are reported as skipped rather than passed, and the structural rules — landmarks, names, heading order, ARIA — are what it enforces. CI runs whatever `check` chains on PR; adding a check to the `check` script is enough, no workflow change needed.

## Architecture / conventions

- **Node 24, pnpm 12.** Pinned via `.nvmrc`, `engines`, and `packageManager`. `pnpm-workspace.yaml` enforces `minimumReleaseAge=4320` (3-day cooldown), isolated node-linker. Don't loosen these without reason. Package-manager enforcement carries no key on purpose: pnpm 11 replaced `packageManagerStrict`/`packageManagerStrictVersion` with `pmOnFail`, whose default `download` already errors on a foreign package manager and fetches the pinned pnpm version — every other value only weakens it, so leave it unset (the rationale sits as a comment in the file).
- **Node 24, pnpm 12, TypeScript 6.** Pinned via `.nvmrc`, `engines`, and `packageManager`. `pnpm-workspace.yaml` enforces `minimumReleaseAge=4320` (3-day cooldown), isolated node-linker. Don't loosen these without reason. **TypeScript stays on 6 deliberately**: 7 is the native port, whose `exports` map no longer exposes the compiler internals Volar builds on, so `vue-tsc` cannot run on it — and without `vue-tsc` the layer has no typecheck at all. Move to 7 when Volar does, not before. Package-manager enforcement carries no key on purpose: pnpm 11 replaced `packageManagerStrict`/`packageManagerStrictVersion` with `pmOnFail`, whose default `download` already errors on a foreign package manager and fetches the pinned pnpm version — every other value only weakens it, so leave it unset (the rationale sits as a comment in the file).
- **oxc, not eslint/prettier.** Linting via `oxlint`, formatting via `oxfmt`. Configs live in `.oxlintrc.json` / `.oxfmtrc.json`. `oxlint` uses `unicorn` + `oxc` plugins; rules deliberately minimal.
- **TypeScript, no build step.** The meta scripts and the three tool configs are `.ts` — Node 24 strips types natively, so `scripts/check-policy-parity.ts`, `commitlint.config.ts`, `lint-staged.config.ts` and `taze.config.ts` stay directly executable and each tool loads its own `.ts` config unaided. `tsconfig.json` is `noEmit` + `strict` + `erasableSyntaxOnly`, so only strippable syntax (no enums, no parameter properties) can be written; `pnpm typecheck` is the gate. Once `.vue` files land, `typecheck` moves to `vue-tsc`; `oxlint` + `oxfmt` cover `.vue` on their own, so no ESLint is coming.
- **TypeScript, no build step.** The meta scripts and the three tool configs are `.ts` — Node 24 strips types natively, so `scripts/check-policy-parity.ts`, `commitlint.config.ts`, `lint-staged.config.ts` and `taze.config.ts` stay directly executable and each tool loads its own `.ts` config unaided. `tsconfig.json` is `noEmit` + `strict` + `erasableSyntaxOnly`, so only strippable syntax (no enums, no parameter properties) can be written; `pnpm typecheck` is the gate for those. The layer itself is checked separately by `pnpm typecheck:app` (`nuxt typecheck` in `www/`), because `tsc` cannot see a Nuxt config's module options — those exist only in generated types. `oxlint` + `oxfmt` cover `.vue`, so no ESLint is coming.
- **Husky hooks** (`.husky/pre-commit`, `.husky/commit-msg`) run `lint-staged` and `commitlint`. `lint-staged.config.ts` excludes `README.md`, `CLAUDE.md`, and `AGENTS.md` (free-form prose) and `pnpm-lock.yaml`. `oxlint --fix --deny-warnings` then `oxfmt` on JS/TS; `oxfmt` only on JSON/YAML/MD.
- **Conventional Commits enforced** via `@commitlint/config-conventional`. Don't `--no-verify` unless explicitly asked.
- **release-please** drives the versioning. Files: `release-please-config.json`, `.release-please-manifest.json`, `.github/workflows/release-please.yml`. `release-type: node` (this is a published package, so `package.json` gets bumped too), `include-v-in-tag: true`, starting from `0.0.0`. Publishing to npm is a job added to `release-please.yml`, gated on `needs.release-please.outputs.release-created`.
Expand Down
Loading
Loading