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
6 changes: 6 additions & 0 deletions .changeset/calm-upgrades-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@cloudflare/nimbus-docs": minor
"@cloudflare/create-nimbus-docs": patch
---

Add a versioned breaking-change manifest, explicit reviewed upgrade baselines, agent-readable migration plans, shared `check` and `outdated` diagnostics, safe starter drift updates, starter agent upgrade guidance, and automatic migration guidance during Astro configuration.
2 changes: 1 addition & 1 deletion .changeset/clean-routes-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
"@cloudflare/create-nimbus-docs": patch
---

Allow user-owned Astro pages and scaffolded Markdown and `llms.txt` endpoints to use native rendering semantics while retaining entrypoint-aware checks for active Nimbus contracts and composing with unrelated integration routes. These dynamic endpoints now resolve their payloads when rendered on request. Endpoint helpers now live at `@cloudflare/nimbus-docs/agent-endpoints`; the existing `@cloudflare/nimbus-docs/publication` entrypoint remains supported.
Allow user-owned Astro pages and scaffolded Markdown and `llms.txt` endpoints to use native rendering semantics while retaining entrypoint-aware checks for active Nimbus contracts and composing with unrelated integration routes. These dynamic endpoints now resolve their payloads when rendered on request. Endpoint helpers now live at `@cloudflare/nimbus-docs/agent-endpoints`; the existing `@cloudflare/nimbus-docs/publication` entrypoint remains supported. Sub-path sitemaps now list the deployment root once.
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [ ] Correct tier (framework / starter / registry) per the boundary test
- [ ] Edited `packages/nimbus-starter-source/`, not the `templates` branch
- [ ] Changeset added (`create-nimbus-docs` changeset if the starter changed)
- [ ] Breaking changes are labeled `breaking-change` and add a linked upgrade manifest entry
- [ ] `pnpm typecheck`, `pnpm -r test`, and `pnpm templates:check` all green

<details>
Expand Down
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
versioning-strategy: increase
schedule:
interval: weekly
day: tuesday
groups:
non-major:
update-types:
- minor
- patch
patterns:
- "*"
34 changes: 12 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: CI

# Red/green signal on every PR: typecheck (whole workspace) + test + audit.
# Red/green signal on every PR: typecheck, test, and dependency regressions.
on:
pull_request:
branches: [main]
Expand Down Expand Up @@ -54,6 +54,8 @@ jobs:

- run: pnpm --filter ./packages/nimbus-docs build

- run: pnpm test:upgrades

- run: pnpm -r test

lint:
Expand Down Expand Up @@ -106,31 +108,19 @@ jobs:
exit 1
fi

audit:
name: Audit
dependency-review:
name: Dependency review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
permissions:
contents: read
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
- name: Reject vulnerable production dependency changes
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
node-version: 24
cache: pnpm

# `pnpm audit` needs the resolved tree to populate advisory paths; without
# an install it returns advisories with empty `paths` and the fail-closed
# shape guard rejects the run.
- run: pnpm install --frozen-lockfile

# Fail closed: a non-JSON or unsupported audit response means this gate
# cannot classify published-package risk reliably.
- name: Audit published package prod deps
run: pnpm audit:published-prod

- name: Report full workspace high+ audit
run: pnpm audit --audit-level high
continue-on-error: true
fail-on-severity: high
fail-on-scopes: runtime
license-check: false
show-patched-versions: true
13 changes: 13 additions & 0 deletions .github/workflows/freshness-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ name: Freshness guard
on:
pull_request:
branches: [main]
types: [opened, synchronize, reopened, labeled, unlabeled]

permissions:
contents: read
Expand All @@ -19,7 +20,19 @@ jobs:
# Need the base branch present locally to diff against it.
fetch-depth: 0

- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile

- name: Require a create-nimbus-docs changeset when templates change
run: node scripts/freshness-guard.mjs
env:
BASE_REF: ${{ github.base_ref }}
- name: Validate upgrade declarations
run: pnpm upgrades:check
env:
BASE_REF: ${{ github.base_ref }}
BREAKING_CHANGE: ${{ contains(github.event.pull_request.labels.*.name, 'breaking-change') }}
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ jobs:

- run: pnpm install --frozen-lockfile

- run: pnpm upgrades:check

# Build only what gets published. The root `build` also builds the private
# @nimbus/www site + starter source; a failure there must not block the npm
# release. release.mjs re-verifies the templates against the packed bits.
Expand Down Expand Up @@ -120,7 +122,7 @@ jobs:
if: "!(github.event_name == 'workflow_dispatch' && inputs.publish_only)"
uses: changesets/action@3841a0683d3cfa6dae0f9bb335290003010fe3f0 # v1.9.0
with:
version: pnpm changeset version
version: pnpm changeset:version
publish: node scripts/release.mjs publish
commit: "chore: bump package versions"
title: "chore: bump package versions"
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Before you open a PR:
- Put the change in the right place: framework bugs and plumbing in `nimbus-docs`, styling and layout in the starter, optional extras in the registry.
- Edit `packages/nimbus-starter-source/`, never the `templates` branch — that's generated, and direct edits get clobbered on the next release.
- Add a changeset for anything user-facing. Starter edits need a `create-nimbus-docs` changeset, or the freshness guard fails the PR.
- For every intentional public API break, apply the `breaking-change` PR label and add a linked entry to the comprehensive upgrade manifest. Every entry carries manual guidance; add a migration ID, detector, transform, bounded task, and focused fixtures only when maintainers deliberately classify the change as common, mechanical, and canonically detectable. Run `pnpm upgrades:check`. CI verifies the declaration, pending changeset, and manifest continuity.
- Check that `pnpm typecheck`, `pnpm -r test`, and `pnpm templates:check` pass.

### Local development
Expand Down
4 changes: 4 additions & 0 deletions apps/www/nimbus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "https://nimbus-docs.com/schema/nimbus.json",
"lastReviewedNimbusVersion": "0.13.1"
}
54 changes: 54 additions & 0 deletions apps/www/public/schema/nimbus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://nimbus-docs.com/schema/nimbus.json",
"title": "Nimbus project record",
"type": "object",
"properties": {
"$schema": { "type": "string" },
"version": { "type": ["string", "null"] },
"lastReviewedNimbusVersion": { "type": ["string", "null"] },
"templatesTag": { "type": ["string", "null"] },
"variant": { "type": ["string", "null"] },
"registry": { "type": "string" },
"reconstructed": { "type": "boolean" },
"preview": { "type": "object" },
"serverOutput": {
"type": "object",
"properties": {
"adapter": { "type": "string" }
},
"required": ["adapter"],
"additionalProperties": true
},
"install": {
"type": "object",
"properties": {
"root": { "type": "string" },
"aliases": {
"type": "object",
"additionalProperties": { "type": "string" }
}
},
"additionalProperties": true
},
"components": {
"type": "array",
"items": {
"type": "object",
"properties": {
"slug": { "type": "string" },
"type": { "type": "string" },
"version": { "type": ["string", "null"] },
"source": { "type": ["string", "null"] },
"hash": { "type": ["string", "null"] },
"files": { "type": "array", "items": { "type": "string" } },
"modified": { "type": "boolean" },
"handAuthored": { "type": "boolean" }
},
"required": ["slug", "type", "source", "hash", "files"],
"additionalProperties": true
}
}
},
"additionalProperties": true
}
51 changes: 42 additions & 9 deletions apps/www/src/content/docs/cli.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: CLI
description: The nimbus-docs CLI — list what's available, add it to your project, lint your content.
description: Use the nimbus-docs CLI to install registry features, migrate package APIs, review copied code, and check content.
sidebar:
order: 2
---
Expand Down Expand Up @@ -47,7 +47,7 @@ If a component is already installed, `add` keeps your copy — it never clobbers

<PackageManagers pkg="@cloudflare/nimbus-docs" type="dlx" args="add badge --overwrite" />

`--yes` assents to prompts (e.g. dependency installs) without touching existing files — so it's safe in CI. Use `--overwrite` when you actually mean "replace my files."
For `add`, `--yes` assents to prompts such as dependency installs but still keeps existing files. Use `--overwrite` when you actually mean "replace my files."

Once installed, the component lives in your repo. Edit freely — there's no upstream API to break. Each `add` also appends an entry to your [`nimbus.json`](/project-structure) — slug, source registry, the registry release it came from, and a content hash — so later upgrades can track what you own.

Expand Down Expand Up @@ -107,23 +107,56 @@ It scans your installed components, matches each against the registry, and write
- **modified** — you've edited it; the record keeps the source identity so upgrades can still compare.
- **hand-authored** — yours, from no registry.

The starter version and `templates-v*` tag can't be recovered from the repo alone, so they're left blank (and flagged `reconstructed`) for you to fill in if you know them.
The starter version, `templates-v*` tag, and previously reviewed Nimbus version can't be recovered from the repo alone, so they're left blank (and flagged `reconstructed`). Use `migrate --from <version>` to establish the upgrade range.

<PackageManagers pkg="@cloudflare/nimbus-docs" type="dlx" args="init --root packages/docs" comment="scan a nested package (monorepo)" />
<PackageManagers pkg="@cloudflare/nimbus-docs" type="dlx" args="init --force" comment="rebuild an existing record" />

## Keeping up to date

You own your files, so upgrades are opt-in — nothing changes under you. Two commands, one for each tier:
Package managers update Nimbus itself; Nimbus updates known API usage and reviews copied code:

```sh
pnpm up @cloudflare/nimbus-docs --latest
pnpm exec nimbus-docs migrate
pnpm exec nimbus-docs outdated
```

### `nimbus-docs migrate`

Composes every declared breaking change between the project's `lastReviewedNimbusVersion` and the installed Nimbus version. It shows complete diffs for statically proven edits and bounded review tasks for everything else. Customized or ambiguous code is never forced.

Existing projects without a reviewed baseline must provide the exact Nimbus version whose migrations they last completed:

```sh
pnpm exec nimbus-docs migrate --from PREVIOUS_VERSION
```

Use `--dry-run` or `--diff` for a read-only plan, `--yes --json` for an agent-safe apply loop, and `--print` for a self-contained Markdown handoff. A computed Astro `srcDir` can be supplied explicitly with `--src-dir <relative-dir>`.

Nimbus applies an edit only when it recognizes the source and can prove the change is safe. Customized or ambiguous code remains unchanged and is returned as a review task. `migrate --print` emits that task for any agent or workflow; Nimbus does not launch one itself.

Migration output includes the selected version range, required reviews, planned diffs, blockers, and errors. Files outside the reported scan boundary are not claimed as checked.

After completing all reported work, explicitly confirm it and advance the committed reviewed baseline:

```sh
pnpm exec nimbus-docs migrate --from PREVIOUS_VERSION --yes
```

Repeat `--from` only when the project has no recorded baseline. A clean interactive rerun asks before recording the reviewed version; agents provide that consent with `--yes`. Nimbus never records completion while a detectable migration remains. Then run `outdated` to review user-owned starter and registry code, followed by `nimbus-docs check`, `astro check`, and the production build. The `migrate` output is the version-selected upgrade guide.

### `nimbus-docs outdated`

The read-only "am I behind?" check, across both tiers:
The read-only "am I behind?" overview across package APIs, starter files, and registry components:

<PackageManagers pkg="@cloudflare/nimbus-docs" type="dlx" args="outdated" />

- **Registry components** — compares each recorded content hash against the current registry; run `add <slug> --overwrite` to update.
- **Starter files** — compares your scaffolded files against the upstream `templates-v*` tag. Because those files came from a tag that was never in your git history, plain `git diff` can't show this. Content files are hidden by default (`--all` to include them).
- **Package APIs** — points pending source migrations and version-selected reviews to `migrate`.
- **Registry components** — compares each recorded content hash against the current registry and classifies the recorded local footprint. Registry updates remain review-only because overwrite can also affect dependencies.
- **Starter files** — compares your scaffolded files against the upstream `templates-v*` tag, including additions and removals. Because those files came from a tag that was never in your git history, plain `git diff` can't show this. Content files are hidden by default (`--all` to include them).

Pass `--json` for deterministic agent-readable findings. Projects without complete `nimbus.json` provenance still receive Package API results and an explicit partial-coverage result.

### `nimbus-docs diff [file]`

Expand All @@ -132,11 +165,11 @@ Read-only detail for starter files — what you changed, and what changed upstre
<PackageManagers pkg="@cloudflare/nimbus-docs" type="dlx" args="diff" comment="every changed starter file" />
<PackageManagers pkg="@cloudflare/nimbus-docs" type="dlx" args="diff src/components/ui/aside/Aside.astro" comment="one file" />

Each file is one of: **clean to pull** (upstream changed, you didn't), **hand-merge** (you both changed it), or **your changes** (you edited it, upstream didn't). For a clean file you can let the CLI write the upstream version:
Each file is one of: **clean to pull** (upstream changed, you didn't), **added/removed upstream**, **hand-merge** (you both changed it), or **your changes** (you edited it, upstream didn't). For clean updates, additions, and removals, you can let the CLI apply one reviewed change:

<PackageManagers pkg="@cloudflare/nimbus-docs" type="dlx" args="diff src/components/ui/aside/Aside.astro --apply" />

`--apply` is explicit and per-file, and refuses anything you've edited — it only pulls clean upstream changes, never merges. Review with `git diff` afterward. Pass `--to <templates-vX.Y.Z>` to target a specific tag, or `--template-dir <path>` to compare offline against a local checkout.
`--apply` is explicit and per-file, rejects symlink/path escapes, and rechecks the clean preimage or absence before writing — it never merges. Review with `git diff` afterward. Pass `--to <templates-vX.Y.Z>` to target a specific tag, or `--template-dir <path>` to compare offline against a local checkout.

## `nimbus-docs lint`

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@
"typecheck": "pnpm --filter ./packages/nimbus-docs build && pnpm -r typecheck",
"lint": "eslint",
"lint:fix": "eslint --fix",
"audit:published-prod": "node scripts/audit-published-prod.mjs",
"dev": "pnpm --filter nimbus-starter-source dev",
"build:templates": "node packages/create-nimbus-docs/scripts/copy-template.mjs",
"api-reference:check": "node scripts/api-reference-check.mjs",
"workers-feasibility:check": "node scripts/workers-feasibility-check.mjs",
"templates:check": "node scripts/templates-check.mjs",
"templates:sync": "node scripts/sync-templates-repo.mjs",
"upgrades:check": "node scripts/upgrade-manifest.mjs",
"test:upgrades": "node --test scripts/upgrade-manifest.test.mjs scripts/sync-reviewed-baselines.test.mjs",
"local": "node scripts/local.mjs",
"local:auto": "node scripts/local.mjs --auto",
"local:reset": "node scripts/local.mjs --auto --reset",
"local:add": "node scripts/local-add.mjs",
"changeset": "changeset",
"changeset:version": "changeset version",
"changeset:version": "changeset version && node scripts/sync-reviewed-baselines.mjs",
"changeset:publish": "changeset publish"
},
"engines": {
Expand Down
1 change: 1 addition & 0 deletions packages/create-nimbus-docs/scripts/copy-template.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const EXCLUDED_DIRS = new Set([
"dist",
"pnpm-lock.yaml",
".nimbus",
"nimbus.json",
// Templates dir holds per-variant content overrides for the generator.
// It is internal to the source tree and never ships in a template.
"templates",
Expand Down
19 changes: 19 additions & 0 deletions packages/create-nimbus-docs/src/scaffold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
cpSync,
existsSync,
lstatSync,
readFileSync,
realpathSync,
readdirSync,
renameSync,
Expand Down Expand Up @@ -68,6 +69,7 @@ function writeNimbusJson(
const record = {
$schema: "https://nimbus-docs.com/schema/nimbus.json",
version,
lastReviewedNimbusVersion: preview ? null : frameworkVersion(target),
templatesTag: preview ? null : `templates-v${version}`,
variant: options.content,
registry: DEFAULT_REGISTRY_URL,
Expand All @@ -89,6 +91,23 @@ function writeNimbusJson(
);
}

function frameworkVersion(target: string): string | null {
try {
const pkg = JSON.parse(
readFileSync(join(target, "package.json"), "utf8"),
) as {
dependencies?: Record<string, unknown>;
devDependencies?: Record<string, unknown>;
};
const spec = pkg.dependencies?.["@cloudflare/nimbus-docs"] ??
pkg.devDependencies?.["@cloudflare/nimbus-docs"];
if (typeof spec !== "string") return null;
return /^[~^]?([0-9]+\.[0-9]+\.[0-9]+)(?:$|[-+\s])/.exec(spec.trim())?.[1] ?? null;
} catch {
return null;
}
}

// Entries that must never survive into a scaffolded project, whether the
// source was a giget download or a local `--template-dir`. `.nimbus` is
// gitignored build output (lint.json / routes.json) — defense-in-depth for any
Expand Down
Loading
Loading