Skip to content

Set up Fumadocs documentation site with Cloudflare Workers deploy - #16

Merged
Ryan Zhu (underthestars-zhy) merged 4 commits into
mainfrom
ryan/fumadocs
Jun 29, 2026
Merged

Set up Fumadocs documentation site with Cloudflare Workers deploy#16
Ryan Zhu (underthestars-zhy) merged 4 commits into
mainfrom
ryan/fumadocs

Conversation

@underthestars-zhy

@underthestars-zhy Ryan Zhu (underthestars-zhy) commented Jun 28, 2026

Copy link
Copy Markdown
Member

Summary

  • Scaffolds a Fumadocs (Next.js + MDX) documentation site under docs/, turning the loose collection of .mdx files into a buildable, searchable docs app with a static export.
  • Moves the existing developer docs into docs/content/docs/ and adds meta.json to control sidebar ordering.
  • Adds a GitHub Actions workflow that builds the static export and deploys it to Cloudflare Workers — production on push to main, ephemeral preview URLs on pull requests.
  • Removes two stale PR write-up files (docs/loop-is-retry.md, docs/storage-persistence.md); their content now lives in the structured docs, and index.mdx links to the in-site pages and the root CONSTITUTION.md instead.
  • Wires up static search (Orama), OpenGraph image generation, and llms.txt / llms-full.txt / per-page markdown routes for LLM consumption.

Prerequisites

The deploy workflow expects two repository secrets:

Secret Purpose
CLOUDFLARE_API_TOKEN Authenticates wrangler to deploy/upload
CLOUDFLARE_ACCOUNT_ID Target Cloudflare account

For correct OpenGraph image URLs in production, set NEXT_PUBLIC_SITE_URL (e.g. https://docs.example.com) in the build environment; it falls back to http://localhost:3000.

Usage

cd docs
pnpm install
pnpm dev            # local dev at http://localhost:3000
pnpm build          # Next.js static export -> docs/out
pnpm types:check    # fumadocs-mdx + next typegen + tsc --noEmit

Changes

CI / deploy

  • .github/workflows/docs.yml — pnpm + Node 24 build; wrangler deploy on main/manual, wrangler versions upload (preview) on PRs. Path-filtered to docs/**.
  • docs/wrangler.toml — static-assets-only Worker serving ./out.
  • docs/public/_redirects//docs.

App & routes (docs/app/)

  • layout.tsx, (home)/ landing page, docs/[[...slug]]/page.tsx + docs/layout.tsx docs shell.
  • api/search/route.ts static search endpoint; og/docs/[...slug] OG images.
  • llms.txt, llms-full.txt, llms.mdx/docs/[[...slug]] LLM/markdown routes.

Components & lib

  • components/ — MDX components, root provider, Orama search dialog.
  • lib/source.ts, lib/shared.ts, lib/layout.shared.tsx, lib/cn.ts — content source, shared config, layout options.
  • source.config.ts, next.config.mjs, postcss.config.mjs, tsconfig.json, package.json, pnpm-lock.yaml, .gitignore, app/global.css.

Content

  • Moved cli-and-operations, core-concepts, declarations, extending-astrolabe, getting-started, index, modifiers, state-and-persistence, telemetry-and-updates .mdx into docs/content/docs/.
  • Added docs/content/docs/meta.json for navigation order.
  • Updated index.mdx "Design anchors" to link to in-site pages and the root CONSTITUTION.md.

Removed

  • docs/loop-is-retry.md, docs/storage-persistence.md (superseded by the structured docs).

Test plan

  • cd docs && pnpm install --frozen-lockfile succeeds.
  • pnpm build produces a static export in docs/out.
  • pnpm types:check passes.
  • pnpm dev renders every doc page; sidebar order matches meta.json; search returns results.
  • Opening this PR triggers the Docs workflow and produces a Cloudflare preview URL.
  • Internal doc links and the CONSTITUTION.md link resolve.
  • /llms.txt, /llms-full.txt, and a per-page content.md route return markdown.

🤖 Generated with Claude Code


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Summary by CodeRabbit

  • New Features
    • Added a new documentation site with a home page, full docs browsing, in-site search, Open Graph sharing images, and LLM-friendly text/markdown endpoints.
    • Added a redirect so the site root opens the docs section.
  • Bug Fixes
    • Improved shared link previews with better per-page metadata and image handling.
    • Refined global layout/scroll behavior for a smoother reading experience.
  • Chores
    • Added documentation build/deploy setup (including static export) and local docs configuration.
    • Added updated docs content and meta configuration.

Scaffold a Fumadocs (Next.js static-export) documentation site in docs/ from
the existing guide MDX. Includes client-side Orama static search, generated OG
images, and llms.txt routes. Content moves to docs/content/docs with meta.json
driving nav order; dangling design-note links in index.mdx are fixed.

Add .github/workflows/docs.yml: builds the static export and deploys it to
Cloudflare Workers Static Assets on push to main (docs changes), and uploads a
preview version on pull requests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e080fff6-cc09-4cbb-b8d1-af2ef29dae5a

📥 Commits

Reviewing files that changed from the base of the PR and between 9965e79 and 8155a56.

📒 Files selected for processing (1)
  • .github/workflows/docs.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/docs.yml

📝 Walkthrough

Walkthrough

Adds a new docs/ Next.js documentation site with Fumadocs source/config, app routes for docs, search, LLM text, and OG images, plus Cloudflare deployment and GitHub Actions support. It also updates docs content metadata, README, redirects, and removes two stale markdown files.

Changes

Docs Site Bootstrap

Layer / File(s) Summary
Project config and tooling
docs/package.json, docs/tsconfig.json, docs/next.config.mjs, docs/postcss.config.mjs, docs/.gitignore, docs/wrangler.toml, docs/public/_redirects
Adds the docs package manifest, TypeScript and Next.js config, PostCSS setup, ignore rules, Cloudflare Workers asset config, and root redirect to /docs.
Shared config and UI helpers
docs/lib/shared.ts, docs/lib/source.ts, docs/lib/layout.shared.tsx, docs/lib/cn.ts, docs/source.config.ts, docs/components/mdx.tsx, docs/components/search.tsx, docs/components/provider.tsx
Defines shared route/git constants, Fumadocs source helpers, layout options, the cn re-export, MDX component merging, the Orama search dialog, the provider wrapper, and the Fumadocs source config.
App shell, docs page, and search route
docs/app/layout.tsx, docs/app/global.css, docs/app/(home)/layout.tsx, docs/app/(home)/page.tsx, docs/app/docs/layout.tsx, docs/app/docs/[[...slug]]/page.tsx, docs/app/api/search/route.ts
Adds the root layout and global styles, the home route, the /docs layout, the docs catch-all page with static params and metadata, and the static search API route.
LLM and OG routes
docs/app/llms.txt/route.ts, docs/app/llms-full.txt/route.ts, docs/app/llms.mdx/docs/[[...slug]]/route.ts, docs/app/og/docs/[...slug]/route.tsx
Adds the LLM index, full LLM text export, per-page markdown LLM route, and OG image route with non-revalidating handlers and static params generation.
Content, README, and workflow
docs/content/docs/meta.json, docs/content/docs/index.mdx, docs/storage-persistence.md, docs/loop-is-retry.md, docs/README.md, .github/workflows/docs.yml
Populates docs page metadata, rewrites the design-anchors section, removes two markdown files, adds the docs README, and adds the GitHub Actions workflow for docs deployment.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hop hop, the docs take shape,
Pages, search, and routes in drape.
LLM scrolls and OG gleam,
Cloudflare carries the build upstream.
Tiny paws did lots today,
Now the docs site hops away. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: a Fumadocs docs site setup with Cloudflare Workers deployment.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ryan/fumadocs

Comment @coderabbitai help to get the list of available commands.

The pnpm/action-setup step runs at the repo root (uses: steps ignore
defaults.run.working-directory), where there is no package.json, so it
cannot read the packageManager field. Pin the version explicitly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
docs/components/search.tsx (1)

28-33: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the ORama client per locale.

This recreates the search client on every render. If useDocsSearch() keys off client identity, each keystroke can trigger needless reinitialization and extra work. Memoizing it by locale keeps the dialog stable.

♻️ Proposed change
 import { useDocsSearch } from 'fumadocs-core/search/client';
 import { oramaStaticClient } from 'fumadocs-core/search/client/orama-static';
 import { create } from '`@orama/orama`';
 import { useI18n } from 'fumadocs-ui/contexts/i18n';
+import { useMemo } from 'react';
@@
 export default function DefaultSearchDialog(props: SharedProps) {
   const { locale } = useI18n(); // (optional) for i18n
+  const client = useMemo(
+    () =>
+      oramaStaticClient({
+        initOrama,
+        locale,
+      }),
+    [locale],
+  );
+
   const { search, setSearch, query } = useDocsSearch({
-    client: oramaStaticClient({
-      initOrama,
-      locale,
-    }),
+    client,
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/components/search.tsx` around lines 28 - 33, The ORama client passed
into useDocsSearch is recreated on every render, causing unstable client
identity and unnecessary reinitialization. Memoize the result of
oramaStaticClient(initOrama, locale) by locale before passing it into
useDocsSearch, so the search dialog stays stable across keystrokes. Update the
search component to keep the client instance stable unless locale changes.
docs/.gitignore (1)

23-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Ignore Wrangler’s local state directory.

Running Wrangler from this package will leave a .wrangler/ directory under docs/, and it is easy to commit by accident. Add it here with the other generated artifacts.

Suggested diff
 # others
 .env*.local
 .vercel
 next-env.d.ts
+/.wrangler
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/.gitignore` around lines 23 - 26, The docs .gitignore is missing
Wrangler’s generated local state directory, so add the .wrangler/ entry
alongside the other generated artifacts in this file. Update the ignore list
near the existing .vercel and next-env.d.ts entries so running Wrangler from
docs does not leave a trackable .wrangler/ directory behind.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/docs.yml:
- Around line 40-47: The Cloudflare deploy step in the docs workflow currently
runs for every pull_request, which causes forked PRs to fail because they cannot
access secrets. Update the Deploy to Cloudflare Workers job to only run for
trusted PRs, using the existing github.event_name logic in the
wrangler-action@v3 step and the surrounding workflow conditions so preview
uploads/deploys are skipped for forked contributors.
- Around line 30-34: The docs workflow currently runs the deploy-related setup
unconditionally, which can break forked pull_request runs when Cloudflare
secrets are unavailable. Update the workflow around the wrangler-action/deploy
step in docs.yml to run only when the PR is not from a fork or when the required
credentials are present, so preview deploys are skipped safely for external
contributors.

In `@docs/app/`(home)/page.tsx:
- Around line 5-13: The root docs landing page still shows the scaffold
placeholder in the page component, so replace the “Hello World” content in the
home page with production-ready branded copy or change the page behavior to
redirect to /docs. Update the existing landing page component in page.tsx so the
default / route no longer exposes the unfinished placeholder and instead matches
the migrated documentation experience.

In `@docs/app/docs/`[[...slug]]/page.tsx:
- Around line 30-33: The GitHub source link in ViewOptionsPopover is built with
the wrong repository path, causing broken “view on GitHub” links for docs pages.
Update the githubUrl construction in the docs page component to include the
correct docs content prefix from the repo root, using the existing page.path
value so it points to docs/content/docs/... instead of content/docs/... .

In `@docs/app/layout.tsx`:
- Line 13: The metadataBase setup in the app layout currently only falls back on
nullish values, so an empty string or malformed NEXT_PUBLIC_SITE_URL can still
crash the docs app when new URL is constructed. Update the metadataBase
initialization in the layout logic to validate the env value first, treat
blank/invalid values as missing, and fall back safely to the localhost URL
before calling new URL. Keep the fix localized to the metadataBase assignment so
the layout remains resilient to bad configuration.

In `@docs/public/_redirects`:
- Line 1: The root redirect in the _redirects file is overriding the new home
route and making the landing page unreachable. Update the redirect rule so / is
not always sent to /docs, and verify it does not conflict with the newly added
app/(home)/page.tsx route; if the home page should ship, remove or narrow this
redirect so the root path can resolve to the home page.

---

Nitpick comments:
In `@docs/.gitignore`:
- Around line 23-26: The docs .gitignore is missing Wrangler’s generated local
state directory, so add the .wrangler/ entry alongside the other generated
artifacts in this file. Update the ignore list near the existing .vercel and
next-env.d.ts entries so running Wrangler from docs does not leave a trackable
.wrangler/ directory behind.

In `@docs/components/search.tsx`:
- Around line 28-33: The ORama client passed into useDocsSearch is recreated on
every render, causing unstable client identity and unnecessary reinitialization.
Memoize the result of oramaStaticClient(initOrama, locale) by locale before
passing it into useDocsSearch, so the search dialog stays stable across
keystrokes. Update the search component to keep the client instance stable
unless locale changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f3c5db7f-62c6-4990-8b1a-79b8a27b512c

📥 Commits

Reviewing files that changed from the base of the PR and between f26b4e9 and 9965e79.

⛔ Files ignored due to path filters (1)
  • docs/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (40)
  • .github/workflows/docs.yml
  • docs/.gitignore
  • docs/README.md
  • docs/app/(home)/layout.tsx
  • docs/app/(home)/page.tsx
  • docs/app/api/search/route.ts
  • docs/app/docs/[[...slug]]/page.tsx
  • docs/app/docs/layout.tsx
  • docs/app/global.css
  • docs/app/layout.tsx
  • docs/app/llms-full.txt/route.ts
  • docs/app/llms.mdx/docs/[[...slug]]/route.ts
  • docs/app/llms.txt/route.ts
  • docs/app/og/docs/[...slug]/route.tsx
  • docs/components/mdx.tsx
  • docs/components/provider.tsx
  • docs/components/search.tsx
  • docs/content/docs/cli-and-operations.mdx
  • docs/content/docs/core-concepts.mdx
  • docs/content/docs/declarations.mdx
  • docs/content/docs/extending-astrolabe.mdx
  • docs/content/docs/getting-started.mdx
  • docs/content/docs/index.mdx
  • docs/content/docs/meta.json
  • docs/content/docs/modifiers.mdx
  • docs/content/docs/state-and-persistence.mdx
  • docs/content/docs/telemetry-and-updates.mdx
  • docs/lib/cn.ts
  • docs/lib/layout.shared.tsx
  • docs/lib/shared.ts
  • docs/lib/source.ts
  • docs/loop-is-retry.md
  • docs/next.config.mjs
  • docs/package.json
  • docs/postcss.config.mjs
  • docs/public/_redirects
  • docs/source.config.ts
  • docs/storage-persistence.md
  • docs/tsconfig.json
  • docs/wrangler.toml
💤 Files with no reviewable changes (2)
  • docs/storage-persistence.md
  • docs/loop-is-retry.md
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: Docs / deploy: Set up Fumadocs documentation site with Cloudflare Workers deploy

Conclusion: failure

View job details

##[group]Running self-installer...
 Error: No pnpm version is specified.
 Please specify it by one of the following ways:
   - in the GitHub Action config with the key "version"
   - in the package.json with the key "packageManager"
     at readTarget (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:8195)
     at runSelfInstaller (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:6702)
     at async install (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:5706)
     at async runMain (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:2804)
     at async main (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:2726)
 ##[error]Error: No pnpm version is specified.

GitHub Actions: Docs / 0_deploy.txt: Set up Fumadocs documentation site with Cloudflare Workers deploy

Conclusion: failure

View job details

##[group]Running self-installer...
 Error: No pnpm version is specified.
 Please specify it by one of the following ways:
   - in the GitHub Action config with the key "version"
   - in the package.json with the key "packageManager"
     at readTarget (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:8195)
     at runSelfInstaller (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:6702)
     at async install (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:5706)
     at async runMain (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:2804)
     at async main (/home/runner/work/_actions/pnpm/action-setup/v4/dist/index.js:1:2726)
 ##[error]Error: No pnpm version is specified.
🧰 Additional context used
🪛 zizmor (1.26.1)
.github/workflows/docs.yml

[warning] 26-26: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 30-30: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): this step

(cache-poisoning)

🔇 Additional comments (13)
docs/components/mdx.tsx (1)

1-15: LGTM!

docs/components/provider.tsx (1)

1-8: LGTM!

docs/app/global.css (1)

1-12: LGTM!

docs/app/(home)/layout.tsx (1)

1-6: LGTM!

docs/app/docs/layout.tsx (1)

1-11: LGTM!

docs/package.json (1)

15-16: 🩺 Stability & Availability

Remove this dependency warning. docs/pnpm-lock.yaml already resolves fumadocs-core@16.10.6 and fumadocs-mdx@15.0.13, so these ranges are not a bootstrap blocker; the suggested downgrade is unnecessary.

			> Likely an incorrect or invalid review comment.
docs/app/og/docs/[...slug]/route.tsx (1)

23-27: 🗄️ Data Integrity & Integration

No change needed here. lang isn’t part of this route, so generateStaticParams() ignores it.

			> Likely an incorrect or invalid review comment.
docs/app/llms.txt/route.ts (1)

4-7: 🩺 Stability & Availability

No dynamic = 'force-static' needed here

output: 'export' already requires this handler to be build-time renderable, and this route doesn’t use request-time APIs. revalidate = false is fine; adding dynamic = 'force-static' here isn’t necessary.

			> Likely an incorrect or invalid review comment.
docs/app/docs/[[...slug]]/page.tsx (1)

16-29: LGTM!

Also applies to: 35-63

docs/app/api/search/route.ts (1)

1-9: LGTM!

docs/content/docs/meta.json (1)

1-13: LGTM!

docs/content/docs/index.mdx (1)

120-127: LGTM!

docs/README.md (1)

1-46: LGTM!

Comment thread .github/workflows/docs.yml Outdated
Comment thread .github/workflows/docs.yml Outdated
Comment thread docs/app/(home)/page.tsx
Comment on lines +5 to +13
<div className="flex flex-col justify-center text-center flex-1">
<h1 className="text-2xl font-bold mb-4">Hello World</h1>
<p>
You can open{' '}
<Link href="/docs" className="font-medium underline">
/docs
</Link>{' '}
and see the documentation.
</p>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace the scaffold placeholder before shipping.

The root docs landing page currently renders Hello World, which looks unfinished for a production docs site. Either redirect / to /docs or swap this for branded copy that matches the migrated documentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/app/`(home)/page.tsx around lines 5 - 13, The root docs landing page
still shows the scaffold placeholder in the page component, so replace the
“Hello World” content in the home page with production-ready branded copy or
change the page behavior to redirect to /docs. Update the existing landing page
component in page.tsx so the default / route no longer exposes the unfinished
placeholder and instead matches the migrated documentation experience.

Comment on lines +30 to +33
<ViewOptionsPopover
markdownUrl={markdownUrl}
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/content/docs/${page.path}`}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the repository path in the GitHub source link.

The docs files in this PR live under docs/content/docs/..., but this URL points at content/docs/... from the repo root, so the "view on GitHub" action will 404 for every page.

Suggested fix
         <ViewOptionsPopover
           markdownUrl={markdownUrl}
-          githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/content/docs/${page.path}`}
+          githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/docs/content/docs/${page.path}`}
         />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<ViewOptionsPopover
markdownUrl={markdownUrl}
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/content/docs/${page.path}`}
/>
<ViewOptionsPopover
markdownUrl={markdownUrl}
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/docs/content/docs/${page.path}`}
/>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/app/docs/`[[...slug]]/page.tsx around lines 30 - 33, The GitHub source
link in ViewOptionsPopover is built with the wrong repository path, causing
broken “view on GitHub” links for docs pages. Update the githubUrl construction
in the docs page component to include the correct docs content prefix from the
repo root, using the existing page.path value so it points to
docs/content/docs/... instead of content/docs/... .

Comment thread docs/app/layout.tsx
// Set NEXT_PUBLIC_SITE_URL (e.g. https://docs.example.com) in CI so OpenGraph
// image URLs resolve to the deployed origin instead of localhost.
export const metadata: Metadata = {
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? 'http://localhost:3000'),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Guard metadataBase against empty or invalid env values.

new URL(process.env.NEXT_PUBLIC_SITE_URL ?? ...) still throws when the variable is set to '' or any malformed URL. That turns a config typo into a hard build/runtime failure for the whole docs app.

🛡️ Proposed change
+function getMetadataBase() {
+  const siteUrl = process.env.NEXT_PUBLIC_SITE_URL?.trim();
+
+  try {
+    return new URL(siteUrl || 'http://localhost:3000');
+  } catch {
+    return new URL('http://localhost:3000');
+  }
+}
+
 export const metadata: Metadata = {
-  metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? 'http://localhost:3000'),
+  metadataBase: getMetadataBase(),
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? 'http://localhost:3000'),
function getMetadataBase() {
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL?.trim();
try {
return new URL(siteUrl || 'http://localhost:3000');
} catch {
return new URL('http://localhost:3000');
}
}
export const metadata: Metadata = {
metadataBase: getMetadataBase(),
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/app/layout.tsx` at line 13, The metadataBase setup in the app layout
currently only falls back on nullish values, so an empty string or malformed
NEXT_PUBLIC_SITE_URL can still crash the docs app when new URL is constructed.
Update the metadataBase initialization in the layout logic to validate the env
value first, treat blank/invalid values as missing, and fall back safely to the
localhost URL before calling new URL. Keep the fix localized to the metadataBase
assignment so the layout remains resilient to bad configuration.

Comment thread docs/public/_redirects
@@ -0,0 +1 @@
/ /docs 302

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

This redirect makes the new home page unreachable.

The stack context says this PR also adds docs/app/(home)/page.tsx, but this rule sends every / request straight to /docs. If the landing page is meant to ship, drop this redirect; otherwise the home route is dead in deployed environments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/public/_redirects` at line 1, The root redirect in the _redirects file
is overriding the new home route and making the landing page unreachable. Update
the redirect rule so / is not always sent to /docs, and verify it does not
conflict with the newly added app/(home)/page.tsx route; if the home page should
ship, remove or narrow this redirect so the root path can resolve to the home
page.

@underthestars-zhy
Ryan Zhu (underthestars-zhy) merged commit 513a244 into main Jun 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant