From c81da115cc16aa26e20bf6d846de04410e1ef2c0 Mon Sep 17 00:00:00 2001 From: Devin Michael Date: Tue, 6 Oct 2026 12:07:35 +0700 Subject: [PATCH 1/2] chore: constrain dependency updates to supported release lines --- .github/dependabot.yml | 17 +++++++++++++ .github/workflows/ci.yml | 2 ++ docs/MAINTENANCE.md | 18 ++++++++++++++ package-lock.json | 20 ++++++++-------- package.json | 17 ++++++------- scripts/check-dependency-compatibility.mjs | 28 ++++++++++++++++++++++ 6 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 scripts/check-dependency-compatibility.mjs diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 213d4ef..ca6706c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,6 +6,23 @@ updates: schedule: interval: weekly open-pull-requests-limit: 5 + # package.json owns the supported release lines. Minor/major upgrades to + # the framework stack are deliberate migrations, not routine maintenance. + versioning-strategy: lockfile-only + groups: + react: + patterns: + - react + - react-dom + - "@types/react" + - "@types/react-dom" + fumadocs: + patterns: + - "fumadocs-*" + next: + patterns: + - next + - "@next/third-parties" - package-ecosystem: github-actions directory: / diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f713fe8..6663bfe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,8 @@ jobs: - run: npm ci + - run: npm run check-dependency-compatibility + # prebuild runs audit-developer-links, validate-links, and check-capabilities. - run: npm run build diff --git a/docs/MAINTENANCE.md b/docs/MAINTENANCE.md index ecc8c34..a30fefd 100644 --- a/docs/MAINTENANCE.md +++ b/docs/MAINTENANCE.md @@ -25,6 +25,24 @@ fan-out). The stable watch path is `content/changelog/*.mdx`. | `npm run validate-links` | Internal docs link integrity | | `npm run audit-developer-links` | Stale developer-doc URL patterns | | `npm audit --omit=dev` | Dependency advisories | +| `npm run check-dependency-compatibility` | Matching React/Fumadocs packages and Node types | + +## Dependency updates + +Dependabot proposes weekly lockfile updates within the release lines declared in +`package.json`. Next.js, React, and Fumadocs use patch-only (`~`) ranges. Their +minor and major upgrades require a migration PR with an explicit range change, +`npm run build`, and both search checks. Keep security alerts and security update +PRs enabled; a security fix outside these ranges needs an explicit range change +and the same validation rather than remaining blocked by the maintenance policy. + +React and React DOM must resolve to exactly the same version and update together +with their type packages. Fumadocs core and UI must also match exactly; MDX has +its own version line and should be reviewed with the Fumadocs group. Update +Next.js and `@next/third-parties` together. Node types stay on the major declared +in `.node-version` (also used by CI), and TypeScript stays on the supported major +until a deliberate compiler migration. CI checks the installed package versions +so a green build alone cannot approve a mismatched pair. ## Deprecated: changelog migration scripts diff --git a/package-lock.json b/package-lock.json index 7b48f5e..5c0b232 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,14 +8,14 @@ "name": "nextcommerce-docs", "version": "0.1.0", "dependencies": { - "@next/third-parties": "^16.3.1", - "fumadocs-core": "^16.10.3", - "fumadocs-mdx": "^14.3.2", - "fumadocs-ui": "^16.10.3", + "@next/third-parties": "~16.3.1", + "fumadocs-core": "~16.10.3", + "fumadocs-mdx": "~14.3.2", + "fumadocs-ui": "~16.10.3", "lucide-react": "^1.38.0", - "next": "^16.3.6", - "react": "^19.1", - "react-dom": "^19.1", + "next": "~16.3.6", + "react": "~19.2.4", + "react-dom": "~19.2.4", "zod": "^4.3.6" }, "devDependencies": { @@ -5715,9 +5715,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index f238f21..83524b1 100644 --- a/package.json +++ b/package.json @@ -14,17 +14,18 @@ "check-search-quality": "node scripts/check-search-quality.mjs", "check-capabilities": "node scripts/check-capabilities.mjs", "check-markup": "node scripts/check-markup.mjs", - "sync-capabilities": "node scripts/sync-capabilities.mjs" + "sync-capabilities": "node scripts/sync-capabilities.mjs", + "check-dependency-compatibility": "node scripts/check-dependency-compatibility.mjs" }, "dependencies": { - "@next/third-parties": "^16.3.1", - "fumadocs-core": "^16.10.3", - "fumadocs-mdx": "^14.3.2", - "fumadocs-ui": "^16.10.3", + "@next/third-parties": "~16.3.1", + "fumadocs-core": "~16.10.3", + "fumadocs-mdx": "~14.3.2", + "fumadocs-ui": "~16.10.3", "lucide-react": "^1.38.0", - "next": "^16.3.6", - "react": "^19.1", - "react-dom": "^19.1", + "next": "~16.3.6", + "react": "~19.2.4", + "react-dom": "~19.2.4", "zod": "^4.3.6" }, "devDependencies": { diff --git a/scripts/check-dependency-compatibility.mjs b/scripts/check-dependency-compatibility.mjs new file mode 100644 index 0000000..3fe47e6 --- /dev/null +++ b/scripts/check-dependency-compatibility.mjs @@ -0,0 +1,28 @@ +// Catch coupled-package drift that a successful Next.js build can miss. +import { createRequire } from 'node:module'; +import { readFileSync } from 'node:fs'; + +const require = createRequire(import.meta.url); +const version = (name) => require(`${name}/package.json`).version; +const failures = []; + +for (const [left, right] of [['react', 'react-dom'], ['fumadocs-core', 'fumadocs-ui']]) { + const leftVersion = version(left); + const rightVersion = version(right); + if (leftVersion !== rightVersion) { + failures.push(`${left} ${leftVersion} and ${right} ${rightVersion} must match exactly`); + } +} + +const nodeMajor = readFileSync(new URL('../.node-version', import.meta.url), 'utf8').trim(); +const typesVersion = version('@types/node'); +if (typesVersion.split('.')[0] !== nodeMajor) { + failures.push(`@types/node ${typesVersion} must match the supported Node ${nodeMajor} release line`); +} + +if (failures.length > 0) { + console.error('check-dependency-compatibility: FAIL'); + for (const failure of failures) console.error(` - ${failure}`); + process.exit(1); +} +console.log('check-dependency-compatibility: React, Fumadocs, and Node types are aligned'); From ac64e425882f8cc4d7d8389cc4fecb39764fa244 Mon Sep 17 00:00:00 2001 From: Devin Michael Date: Tue, 6 Oct 2026 12:15:27 +0700 Subject: [PATCH 2/2] fix: prepare llms.txt for an asynchronous Fumadocs index --- app/llms.txt/route.ts | 5 ++--- docs/MAINTENANCE.md | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/llms.txt/route.ts b/app/llms.txt/route.ts index 0f4b525..0ae2c0a 100644 --- a/app/llms.txt/route.ts +++ b/app/llms.txt/route.ts @@ -7,9 +7,8 @@ export const dynamic = 'force-static'; const generator = llms(source); -export function GET() { - const index = generator - .index() +export async function GET() { + const index = (await generator.index()) // The shared loader must keep site-relative URLs for the app's own routing, // so the generated index is absolutized here instead — agents fetch this // file standalone, with no base URL to resolve against. diff --git a/docs/MAINTENANCE.md b/docs/MAINTENANCE.md index a30fefd..f5e2993 100644 --- a/docs/MAINTENANCE.md +++ b/docs/MAINTENANCE.md @@ -70,3 +70,23 @@ Before making the GitHub repository public (or on a periodic cadence): GitHub settings checklist: private vulnerability reporting, Dependabot alerts, secret scanning, branch protection on `main`. + +## Fumadocs 16.15 migration requirements + +The 16.10.3 -> 16.15.12 upgrade needs more than a version bump: + +- `llms(source).index()` becomes asynchronous. Resolve it before rewriting links + in `/llms.txt`; the async handler also works with the current synchronous API. +- Static search switches from Orama to ZBSearch. Migrate the quality checker with + the browser and exported index, preserving all three queries and size budgets. +- ZBSearch disables stemming by default. Enabling English stemming in both the + exporter and browser still changes ranking: in the tested 16.15.12 build, the + subscriptions guide was outside the first 10 results for `subscription`. + Resolve that regression before changing the supported Fumadocs release line; + do not weaken or rename the probe to make the upgrade pass. +- Core and UI must use the same version. MDX has its own version line. Validate + the production build, `/llms.txt`, all search checks, and browser search before + merging the migration. The 16.15 upgrade also changes Motion and UI primitives, + so check the docs layout and navigation in the preview. + +Routine maintenance stays on the 16.10 patch line until these checks pass.