# docs.beardrive.ai The public product documentation: CLI, sync model, self-hosting. Astro + [Starlight](https://starlight.astro.build), static output, Pagefind search. ```sh npm install npm run dev # http://localhost:4321 npm run build # -> dist/ npm run preview ``` ## Why this is a standalone site Unlike the hub frontend (`internal/webapp/static`) and the cloud landing page (`cloud/internal/landing/dist`), this is **not** embedded into a Go binary: - Docs change far more often than the binary. Embedding them would mean a Go rebuild and redeploy to fix a typo. - A Pagefind search index has no business shipping inside every self-hoster's install. It lives in the OSS repo because that is what it documents. "Edit this page" resolves to something an outside contributor can open a PR against. ## Design tokens `scripts/tokens.mjs` reads the `@theme` block in `internal/webapp/frontend/src/tw.css` — the source of truth for the BearDrive palette — and emits `src/styles/tokens.gen.css`. That file is generated, gitignored, and regenerated by `npm run dev` and `npm run build`, so the palette cannot drift. `src/styles/custom.css` maps Starlight's `--sl-color-*` variables onto it and invents no colors of its own. (The cloud landing page can't do this — it sits in a different Go module and keeps a *copy* of the tokens, policed by its own `check-tokens.mjs`.) ## Adding a page Drop a `.md` file under `src/content/docs/
/` with `title` and `description` frontmatter, then add its slug to the `sidebar` in `astro.config.mjs`. Sidebar order is explicit, not alphabetical. Write `description` for every page: it is the meta description, the search result snippet, and what `llms.txt` shows. ## llms.txt `starlight-llms-txt` generates `/llms.txt`, `/llms-small.txt`, and `/llms-full.txt` at build time. Convention puts `llms.txt` at the **root** domain, not a docs subdomain — so `beardrive.ai/llms.txt` should redirect or proxy to `docs.beardrive.ai/llms.txt`. That redirect lives in the cloud landing page and is the one cross-repo coordination point this split introduces. ## Structure The sidebar order in `astro.config.mjs` **is** the recommended path, and the recommended path is agent-first: - **Start here** — what it is, set up with your agent, first hour. No `brew install` appears in this group. - **Working with agents** — the workflows the product exists for. - **Manual setup (optional)** — the CLI route: install, set up by hand, skills and hooks in detail. Same destination, more steps; one click away, never on the critical path. - **Use cases** — job-shaped titles ("Share work across your team's agents"), persona named in the first line and in the `description`. These pages ROUTE: who it's for, what you get, the one setup difference, links out. The moment one starts teaching a feature, it links to the guide that owns it instead. - **Self-hosting**, **Reference**, **Concepts** — unchanged in intent. Keep new onboarding content out of Manual. If a page teaches someone how to get started, it belongs in Start here and should say what to ask an agent, not what to type. ## Deploying Static output in `dist/`. Any static host works; build command `npm run build`, output directory `dist`, project root `web/docs`. ### Redirects The docs were reorganized around the agent-first path, so three old URLs moved: | Old | New | |---|---| | `/start/install` | `/manual/install/` | | `/start/quickstart` | `/manual/setup-by-hand/` | | `/guides/connect-an-agent` | `/start/setup/` | `astro.config.mjs` declares these, which in a static build emits **meta-refresh pages** — fine for humans, weak for search engines. Real 301s belong in the host. **Firebase Hosting** (simplest static option on GCP — CDN, TLS, and custom domains included): ```json { "hosting": { "public": "dist", "ignore": ["firebase.json", "**/.*"], "redirects": [ { "source": "/start/install", "destination": "/manual/install/", "type": 301 }, { "source": "/start/quickstart", "destination": "/manual/setup-by-hand/", "type": 301 }, { "source": "/guides/connect-an-agent", "destination": "/start/setup/", "type": 301 } ] } } ``` **Cloud Storage behind an external Application Load Balancer:** put the rules in the URL map, which redirects before the bucket is ever reached. ```sh gcloud compute url-maps edit docs-url-map # pathMatchers[].pathRules[]: # - paths: ["/start/install"] # urlRedirect: # pathRedirect: "/manual/install/" # redirectResponseCode: MOVED_PERMANENTLY_DEFAULT # stripQuery: false ``` Whichever host wins, keep the Astro `redirects` block as well: it is the portable fallback, and it keeps local `npm run preview` honest. Note that the build reads a file **outside** `web/docs` (the token source), so the host must check out the whole repository rather than just this subdirectory.