Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 11 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,21 @@ Monorepo providing shared code style configurations for PleaseAI projects.

## Docs Site

- Located at `docs/` — Docus (Nuxt) deployed to Cloudflare Pages
- Bun workspace member; build works because of `bunfig.toml` hoisted linker (see Gotchas)
- Build: `cd docs && bun run build` → outputs to `docs/dist/`
- Deploy: `cd docs && bun run deploy` (wrangler)
- ADR: `docs/adr/0001-choose-documentation-framework.md`
- Located at `apps/docs/` (`@pleaseai/code-style-docs`) — [Nimbus](https://github.com/cloudflare/nimbus) (Astro 7 + Tailwind v4), static output deployed to the Cloudflare Pages project `pleaseai-code-style`
- Bun workspace member (`apps/*`); `bun run build` (turbo) builds it to `apps/docs/dist/`
- Dev / build / deploy: `bun run docs:dev`, `bun run docs:build`, `bun run docs:deploy` (`wrangler pages deploy`)
- Checks inside `apps/docs`: `bun run typecheck` (`astro check`), `bun run lint:docs` (Nimbus prose/MDX lint)
- Content: `apps/docs/src/content/docs/{en,ko}/` (MDX). Every page must exist in both locales at the same path; order pages with `sidebar.order` frontmatter
- i18n is wired by hand with Astro's i18n routing: `apps/docs/src/i18n/` (locales, UI strings, translation lookup), `<html lang>` + `hreflang` in `BaseLayout.astro`, language switcher in `Header.astro`
- Nimbus is pre-1.0 — keep its dependencies pinned to exact versions; upgrade from `apps/docs` with `npx @cloudflare/nimbus-docs migrate` / `outdated` / `diff` (see `apps/docs/AGENT.md`)
- ADRs: `docs/adr/` (current: `0003-migrate-docs-to-nimbus.md`)

## Gotchas

- `packages/perttier-config` directory is intentionally(?) misspelled — do not rename without coordinating release-please config, CI workflows, and npm package name
- `bunfig.toml` sets `linker = "hoisted"` — required for Docus to build. Bun 1.3.2+ defaults to `isolated` linker in workspaces, which puts Docus's raw `.ts` server files under `.bun/` symlinks where Nitro's `rollup-plugin-inject` chokes on them. Hoisted linker (npm-style flat `node_modules`) avoids this.
- Docs build requires `mcp: { enabled: false }` in `docs/nuxt.config.ts` — `@nuxtjs/mcp-toolkit` imports `agents/mcp` (Cloudflare Workers AI Agents) which breaks the `cloudflare_pages` preset.
- Docus `cloudflare_pages` preset outputs to `dist/`, not `.output/public/` — `wrangler.jsonc` `pages_build_output_dir` must match.
- `bunfig.toml` sets `linker = "hoisted"` — introduced for the former Docus site (Bun 1.3.2+ defaults to the `isolated` linker in workspaces, which broke Nitro's `rollup-plugin-inject` on Docus's raw `.ts` files). The Nimbus site has not been verified without it, so keep it until removing it is tested across all workspace packages.
- `apps/docs/src/components/ui/**` and `apps/docs/src/layouts/DocsLayout.astro` are kept as close to upstream Nimbus as possible and excluded from ESLint, so `nimbus-docs diff --apply` / `nimbus-docs add <slug> --overwrite` can update them. Local edits are limited to `aside`, `card`, `pagination`, and `search` (links and i18n strings from `src/i18n/locales.ts`); merge those by hand on upgrade.
- Docs URLs are file-style (`build.format: 'file'`, `trailingSlash: 'never'`): `/en/cli` is served from `en/cli.html`. Don't switch to directory format — Cloudflare Pages would redirect `/en/cli` to `/en/cli/`.

<!-- BEGIN:turborepo-agent-rules -->

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This is a [bun](https://bun.sh) monorepo orchestrated by [Turborepo](https://tur

The `packages/perttier-config` directory is intentionally misspelled. Do not rename it without coordinating the release-please config, CI workflows, and the npm package name.

The documentation site lives in [`docs/`](./docs) (Docus on Nuxt).
The documentation site lives in [`apps/docs/`](./apps/docs) (Nimbus on Astro).

## Getting started

Expand Down
22 changes: 22 additions & 0 deletions apps/docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
node_modules/
dist/
.astro/
.wrangler/
.nimbus/

.env
.env.local
.env.*.local
.env.production
.dev.vars
.dev.vars.*

npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

.DS_Store
.idea/
.vscode/*
!.vscode/extensions.json
140 changes: 140 additions & 0 deletions apps/docs/AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# This Nimbus docs site

> `CLAUDE.md` delegates here. Keep project instructions canonical in this file.

Astro-based docs. The `nimbus-docs` package handles content schemas, sidebar/TOC, MDX→markdown, build hooks, and the `nimbus-docs` CLI. Install dependencies first, then run it as `npx @cloudflare/nimbus-docs <command>`: npx uses the project's installed version. Before an install, npx fetches the latest release instead, which may differ from the site's version and give different results. The scoped name keeps npx from fetching the unrelated `nimbus-docs` package. Everything in `src/` is yours to edit.

## File layout

```
astro.config.ts # imports nimbus + defineNimbusConfig
nimbus.json # records the last reviewed Nimbus package version
src/
├── components.ts # MDX globals — components every .mdx can use without an import
├── components/ # AgentDirective, Header, Render + ui/<slug>/
├── content/
│ ├── docs/*.mdx
│ └── partials/*.mdx # referenced via <Render file="..." />
├── content.config.ts # registers docsCollection() + partialsCollection()
├── layouts/ # BaseLayout (NimbusHead), DocsLayout (sidebar/TOC/breadcrumbs)
├── lib/cn.ts # Tailwind className merger
├── pages/
│ ├── [...slug].astro
│ ├── [...slug]/index.md.ts # Markdown version of every page, all collections
│ ├── [...slug]/index.mdx.ts # authored source of every page, all collections
│ ├── [section]/llms.txt.ts # per-section llms.txt
│ ├── 404.astro
│ ├── index.astro # home page (the empty starter uses content/docs/index.mdx)
│ ├── llms.txt.ts
│ ├── llms-full.txt.ts
│ ├── nimbus-api/coordinates.json.ts # API citation manifest
│ ├── og.png.ts # site-level OG card
│ ├── og/
│ │ ├── _og-card-config.ts # shared OG theme tokens (underscore = not a route)
│ │ └── [...slug].ts # per-page OG cards
│ └── robots.txt.ts
└── styles/ # globals.css, prose.css
```

Cloudflare deploys also have `wrangler.jsonc` at the project root.

## Writing docs

Frontmatter validates against the schema from `docsCollection()` (`@cloudflare/nimbus-docs/content`). Required: `title`.

```mdx
---
title: My page
description: One-line summary.
---

Content here. The page H1 comes from `title` — don't repeat it in the body.

## Section heading
```

Rules:

- **Components are PascalCase.** Register one in `src/components.ts` to use it in every `.mdx` without an import, or import it in the file that uses it. A pre-build validator catches unresolved names with a "did you mean" hint.
- **Partials use `<Render file="..." />`.** Don't import `.mdx` directly. Shared content lives in `src/content/partials/<slug>.mdx`.
- **Icons use Nimbus's `Icon` + Phosphor.** `<Icon name="ph:<glyph>" class="w-4 h-4" />` from `@cloudflare/nimbus-docs/components/Icon.astro`. Glyphs: [phosphoricons.com](https://phosphoricons.com).
- **Don't remove `<AgentDirective />` from `BaseLayout.astro`.** It points agents at `/llms.txt`.

## Adding things

| Goal | Action |
|---|---|
| New doc page | Create `src/content/docs/en/<slug>.mdx` and `src/content/docs/ko/<slug>.mdx` (every page exists in both locales at the same path). Sidebar picks them up. |
| New partial | Create `src/content/partials/<slug>.mdx`. Use via `<Render file="<slug>" />`. |
| UI from registry | `npx @cloudflare/nimbus-docs add <slug>`. Register in `src/components.ts` if used in MDX. |
| Feature recipe | `npx @cloudflare/nimbus-docs add <feature-slug> --print`. Prints the recipe for you to follow; it changes no files itself. |
| Check it builds | `npx @cloudflare/nimbus-docs check` — build-free preflight (env + structure + authoring + types). `--json` for an agent loop, `--fix` to repair what's safe. |
| Custom page route | Add a file under `src/pages/`. |
| Custom OG style | Edit `src/pages/og/_og-card-config.ts`. |
| Check for updates | `npx @cloudflare/nimbus-docs outdated` — starter files behind their tag + registry components behind. |
| Upgrade Nimbus | Update the package, then run `npx @cloudflare/nimbus-docs migrate --dry-run --diff`. Review every change and required manual step before applying. |
| Upgrade a starter file | `npx @cloudflare/nimbus-docs diff <file>` to review, `diff --apply <file>` to pull a clean upstream change. |
| Upgrade a registry component | `npx @cloudflare/nimbus-docs add <slug> --overwrite`, then review with `git diff`. |

Sätteri is Nimbus's default Markdown and MDX processor. Extend it using `markdown.mdastPlugins` for Markdown AST transformations or `markdown.hastPlugins` for HTML AST transformations.
If the site replaces Sätteri with another processor, set `admonitions: false` and keep that processor's existing callout implementation.

List installable items: `npx @cloudflare/nimbus-docs list`.

## Agent interfaces

Read the release-matched guide at [`node_modules/@cloudflare/nimbus-docs/dist/docs-for-agents.md`](node_modules/@cloudflare/nimbus-docs/dist/docs-for-agents.md), especially for preview packages. Nimbus publishes discovery automatically; add project-owned Skills under `skills/<name>/SKILL.md`. Keep `<WebMCP />` in `BaseLayout.astro` for browser-agent search with default Pagefind. Markdown negotiation applies to request-rendered pages; static hosting and response headers follow the deployment target's setup.

## Upgrading Nimbus

Keep `nimbus.json` committed. Its `lastReviewedNimbusVersion` is the baseline Nimbus uses to select the versioned reviews crossed by a package upgrade; state-detected migrations come from the current project files. It is not a package pin and should not be edited by hand.

1. Update `@cloudflare/nimbus-docs` with the project's package manager.
2. Preview the complete plan with `npx @cloudflare/nimbus-docs migrate --dry-run --diff`. If no baseline exists yet, add `--from <previous-version>`.
3. Review every versioned entry and resolve each blocked/manual item.
4. Apply safe edits only with explicit consent: `npx @cloudflare/nimbus-docs migrate --yes`. Review the resulting diff, then rerun the preview.
5. When no migration remains, run `npx @cloudflare/nimbus-docs migrate --yes` again to record the completed review in `nimbus.json`.
6. Pull in starter fixes: `npx @cloudflare/nimbus-docs outdated` lists starter files that changed upstream. For each one, review it with `npx @cloudflare/nimbus-docs diff <file>`, and take a clean update with `diff --apply <file>`. Merge files you've edited by hand. `migrate` doesn't cover these.
7. Run the project's typecheck and production build, then run `npx @cloudflare/nimbus-docs check` again for post-build coverage.

Except for task-printing mode (`--print`), `migrate` exits nonzero while work or review remains; that is a pending-upgrade signal, not necessarily a command failure. Never skip versions by changing `nimbus.json` directly.

## Audit this site

First set `site` in `astro.config.ts` to the production URL; a fresh site still has the placeholder. Ask the user for the URL if you don't know it, and never make one up.

Then run `npx @cloudflare/nimbus-docs check --json`. It runs the environment, structural, authoring, and type checks build-free — config validity, `site` placeholder, route collisions, MDX component resolution, the lint rules, and a `tsc` type-check — and returns three top-level signals plus per-scope detail:

- **`status`** (`passed` | `failed` | `partial`) and **`readiness`** (`buildable` | `blocked` | `unknown`) are the primary signals. `status` is the whole-run verdict; `readiness` answers "does env + structure say it builds?". `ok` (=== zero errors) is kept for back-compat only.
- **`findings[{scope,code,severity,file,line,message,fixable,fix}]`** are problems we evaluated. Apply each `fix` (or `check --fix`).
- **`scopes[].notes[{code,reason,requiresBuild?,requiresInput?}]`** are checks we *couldn't* evaluate yet (e.g. types before a build). A note is never a finding and never carries a `fix` — you resolve it by making the missing thing exist (usually a build), not by `--fix`. `summary.notes` counts them.

Loop until `status !== "failed"` and no finding has a `fix` without `fix.requiresInput` — `summary.fixable` also counts fixes that need input (a placeholder `site`), which `--fix` can't apply for you. An error with no `fix` (such as `nimbus/dependencies-missing`) ends the loop too: do what its message says (install dependencies), then run `check` again, or stop and report it. A `partial` run with nothing left to fix is a **stop** (optionally build, then re-check), not a `--fix` retry. Exit is `1` only when `status` is `"failed"`. For full coverage (types + link-checking) run a build first, then `check` again. With server output, `check` stays `partial` with the note `nimbus/request-rendering-build-required` even after a build: it doesn't verify request-rendered pages, so a passing production build is the gate.

Then walk the categories below for what `check` doesn't cover yet — route-file existence, registry hygiene, the AI surface, post-build search, and Cloudflare config. Emit findings as:

```
- [error|warn|info] FILE:LINE — what + why + fix.
```

End with `Summary: N errors, N warnings.`

- **Config** — `astro.config.ts` calls `nimbus(defineNimbusConfig({ ... }))`; `site` is set; `editPattern` (if set) contains `{path}`; `output:` matches the deploy target.
- **Content** — `content.config.ts` registers `docsCollection()` (and `partialsCollection()` if used); every `.mdx` is inside a registered collection; frontmatter validates.
- **Sidebar** — every sidebar ref resolves to a content entry; no orphans; no slug collisions.
- **MDX** — every PascalCase component in `*.mdx` is registered or imported; every `<Render file=...>` resolves; code-fence languages are valid.
- **Routes** — `llms.txt.ts`, `robots.txt.ts`, `[...slug]/index.md.ts`, `og.png.ts`, `og/[...slug].ts` all exist.
- **Registry hygiene** — every `src/components/ui/<slug>/` is either MDX-registered or imported in `src/`; transitive deps (`lib/cn.ts`, etc.) exist.
- **AI surface** — `<AgentDirective />` renders in `BaseLayout.astro`; doc `<head>` has `<link rel="alternate" type="text/markdown" ...>`.
- **Search** — `data-pagefind-body` is on the docs main wrapper; after a production build, `dist/pagefind/` exists with ≥1 indexed page.
- **Cloudflare** (if applicable) — `wrangler.jsonc` has `name` and `compatibility_date`. This site deploys static output to Cloudflare Pages: `pages_build_output_dir = "dist"` (no `assets` block). Static output on Workers instead: `assets.directory = "./dist"` and `assets.not_found_handling = "404-page"`. Server output (`@astrojs/cloudflare`): no `assets.directory` or `main`; the adapter writes the deploy config to `dist/server/wrangler.json` at build time, so check that file after a build.

## Don't

- Hand-add components under `src/components/ui/` that exists in the Nimbus registry — use `npx @cloudflare/nimbus-docs add <slug>` so deps resolve.
- Import `.mdx` files directly — use `<Render file="..." />`.
- Remove `<AgentDirective />` unless asked.

## Project home

[nimbus-docs.com](https://nimbus-docs.com)
3 changes: 3 additions & 0 deletions apps/docs/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This Nimbus docs site

Read and follow [AGENT.md](./AGENT.md). It is the canonical project guidance for editing, auditing, upgrading, and validating this Nimbus site.
Loading
Loading