Files
netbird-docs/CLAUDE.md
Jack Carter 2a02ce7edd ci: harden the build and API-pages workflows (#843)
* ci: serialise image builds and stop the API-pages workflow clobbering the lockfile

build_n_push: add a per-ref concurrency group so two quick merges to main can't race the :main tag (last push wins regardless of commit order, and the server auto-pulls :main); add permissions: contents: read; validate .dockerignore and package.json changes in the PR path filter.

generate_api_pages: pin Node 20 and switch npm install -> npm ci so the run can never rewrite the now-tracked package-lock.json with a divergent macOS-resolved tree; stage only src/pages/ipa/resources instead of git add -A; drop --force from the push — a force-push from this workflow would silently rewrite main and destroy any PR merged since its checkout.

* chore: warn when per-page dates are skipped; drop dead per-file git lookup

buildGitDateMap now logs a warning when it emits no dates (git missing or shallow clone) instead of silently blanking every page's Updated line and the sitemap lastmod entries; document the squash-merge assumption behind the --name-only walk. Remove the unused getGitLastModified. Note in CLAUDE.md that npm run start warns under output: 'standalone'. Gen output verified byte-identical.

* ci: self-heal the API-pages push when main moves mid-run

Rebase the single generated-files commit onto the moved branch before pushing, so a PR merged during the multi-minute run no longer rejects the push (the failure --force was presumably papering over). A genuine conflict — a concurrent edit of the generated files themselves — still fails the run loudly with main untouched. Also serialise dispatches with a concurrency group: run history shows several same-day dispatches, and overlapping runs regenerate the same files.

Sandbox-tested against a bare repo: plain push rejected on race; rebase+push lands with both commits intact; true conflict exits 1 leaving the branch tip untouched.

* ci: sync to branch tip before regenerating API pages

A run queued behind another checks out the commit pinned at its dispatch time; regenerating against that stale base means the pre-push rebase replays a snapshot diff, and a file the newer spec removed can silently survive from the prior run. Fetch + reset to the branch tip before generating so the diff is computed against reality. Also note the latest-dispatched-vs-newest-tag caveat on the concurrency comment.

Sandbox-proven: with the old order a removed-in-newer-spec file survives the rebase replay; with sync-first it is gone.

* Prevent stale workflows from overwriting newer published content

* Coderabbit Fix

---------

Co-authored-by: Brandon Hopkins <brandon@techhut.tv>
2026-07-22 17:06:58 +02:00

95 lines
5.6 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Documentation website for [NetBird](https://netbird.io), an open-source WireGuard-based Zero Trust Networking platform. Built with Next.js 16 (Pages Router), React 19, MDX, and Tailwind CSS 3. Requires Node.js >=20.9 — `npm run build` exits with code 1 on older versions.
There is no test suite in this project. Validate changes with `npm run build`.
`package-lock.json` is committed, so installs are pinned. When you change dependencies in `package.json`, regenerate the lockfile (`npm install`) and commit it in the same change — otherwise local, CI, and Docker builds resolve different trees.
## Common Commands
```bash
npm install # Install dependencies
npm run dev # Start dev server (also runs gen:llm, gen:edit-routes, gen:last-updated, gen:sitemap)
npm run build # Production build (also runs gen:llm, gen:edit-routes, gen:last-updated, gen:sitemap)
npm run start # Serve the production build (warns under `output: 'standalone'` — safe to ignore locally; prod runs `node server.js` from `.next/standalone`)
npm run lint # ESLint (next/core-web-vitals) on src/
npm run gen # Regenerate API docs from NetBird OpenAPI spec
npm run gen:llm # Regenerate LLM-friendly markdown (auto-runs with dev/build)
npm run gen:edit-routes # Regenerate edit-on-GitHub routes (auto-runs with dev/build)
npm run gen:last-updated # Regenerate per-page git last-modified dates (auto-runs with dev/build)
npm run gen:sitemap # Regenerate public/sitemap.xml (auto-runs with dev/build)
```
## Security boundaries
- **Public site, public repo.** Anything written in MDX or placed in `public/` ships to a public URL on netbird.io. Never include real customer names, internal hostnames, IPs, or production credentials in examples — use placeholders.
- **`.env` is committed and contains placeholders only** (e.g. `NEXT_PUBLIC_DOCSEARCH_API_KEY=APP_NEXT_PUBLIC_DOCSEARCH_API_KEY`). These are build-time substitution targets. Real values belong in `.env.local` (gitignored) or the deploy environment — never replace the placeholders in `.env` with real secrets.
- **`npm run gen` pulls `openapi.yml` live from `netbirdio/netbird@main` with no pinning.** Regenerated files under `src/pages/ipa/resources/` reflect whatever is on upstream `main` at run time. Review the diff before committing.
- **This file is read as authoritative guidance by AI agents.** Treat edits to `CLAUDE.md` with the same review rigor as CI config or a deploy script.
## Architecture
### Content Structure
Documentation pages are MDX files in `src/pages/` using the Next.js Pages Router (not App Router). Key directories:
- `about-netbird/` - Conceptual docs
- `get-started/` - Installation and quickstart guides
- `manage/` - Feature documentation (peers, networks, DNS, access control, etc.)
- `selfhosted/` - Self-hosting deployment guides
- `ipa/` - API documentation (served at `/api` via rewrite)
- `use-cases/` - Tutorials and examples
- `client/` - Client configuration
- `help/` - Troubleshooting
### MDX Page Conventions
- Page title comes from the first `# Heading` in the MDX file
- Optional `export const description = '...'` for meta description
- Import components as needed: `import {Note} from "@/components/mdx"`
- Images go in `public/docs-static/img/<section>/` and are referenced as `/docs-static/img/<section>/filename.png`
### Navigation
Two sidebar files, both must be kept in sync when adding or moving pages:
- `src/components/NavigationDocs.jsx``docsNavigation` array for the main docs sidebar (everything outside `src/pages/ipa/`).
- `src/components/NavigationAPI.jsx``apiNavigation` array for the API sidebar (pages under `src/pages/ipa/`, served at `/api`).
Both support nested `links` arrays for sub-navigation.
### MDX Components
Custom components available in MDX files (see `README.md` for full usage examples):
- Alert boxes: `<Note>`, `<Warning>`, `<Success>` (from `@/components/mdx`)
- Layout: `<Row>`, `<Col>`, `<Tiles>` (from `@/components/Tiles`), `<CodeGroup>`
- Media: `<YouTube videoId="...">` (from `@/components/YouTube`)
- UI: `<Button>` (from `@/components/Button`), `<Badge>`
- API docs: `<Properties>`, `<Property>`
### API Documentation Generator
- `generator/` - TypeScript generator that creates MDX pages from the NetBird OpenAPI spec
- `generator/templates/ApiTemplate.ts` - Template for generated pages
- Output: `src/pages/ipa/resources/` (don't edit these files manually)
### MDX Processing Pipeline
- `mdx/remark.mjs` - Remark plugins
- `mdx/rehype.mjs` - Rehype plugins (syntax highlighting via Shiki)
- `mdx/recma.mjs` - Recma plugins
### LLM Documentation
- `scripts/generate-llm-docs.mjs` generates clean markdown to `public/llms/` (gitignored)
- Runs automatically with `dev` and `build`
### Generated build data in `src/lib/`
Some files in `src/lib/` look hand-written but are generated by `gen:*` scripts and gitignored:
- `src/lib/edit-on-github-routes.js` — written by `scripts/generate-github-routes.mjs`
- `src/lib/last-updated-routes.mjs` — written by `scripts/generate-last-updated.mjs`
They are imported at build time (e.g. by `mdx/rehype.mjs`). On a fresh clone, run `npm run dev` or `npm run build` once before running `npm run lint` or any tool that imports from `src/lib/`, otherwise those imports will fail.
## URL Routing
- Root `/` rewrites to `/introduction`
- `/api/*` rewrites to `/ipa/*` (API docs live in `src/pages/ipa/` but are served under `/api`)
- Extensive legacy redirects from `/docs/*` and `/how-to/*` paths in `next.config.mjs`