Internal Docs Site¶
The project docs (from docs/) are published as a static site using Zensical (successor to MkDocs Material), deployed to Cloudflare Pages at cslewis-docs.fueled.engineering, gated behind Cloudflare Access for @fueled.com SSO.
.context/ is internal working memory and is not published — it stays in the repo for agents and engineers, not the docs site.
Quick start (local)¶
# Preview locally (hot-reload)
./scripts/docs-build.sh serve
# One-off build → site/
./scripts/docs-build.sh build
Requires uv (install). Zensical runs via uvx — no global install needed.
How it works¶
scripts/docs-build.shassemblesdocs/intodocs/_build/- Zensical reads
zensical.toml(docs_dir = "docs/_build") and producessite/ - GH Action (
.github/workflows/docs.yml) deployssite/to Cloudflare Pages on every push tomain - Cloudflare Access gates the site with Google Workspace SSO (
@fueled.com)
Both docs/_build/ and site/ are gitignored.
Adding pages¶
- Add your
.mdfile underdocs/ - Add a nav entry in
zensical.toml(nav = [ … ]) under the appropriate section - Push to
main— auto-deploys
.context/ is internal-only and never published — keep working notes there, reader-facing docs under docs/.
One shelf per audience¶
The docs are split by who reads them, not by entity. Three shelves:
| Shelf | Audience | Where |
|---|---|---|
| Editor guide | The people working in the CMS | docs/editor-guide.md, one file |
| API reference | Mobile and client developers | docs/api/ — index.md for the conventions, one page per entity |
| Reference, guides, ADRs | Backend engineers | docs/reference/, docs/guides/, docs/adr/, docs/architecture.md |
Rules that follow from that split:
- One entity, one API page.
docs/api/passages.mdcarries the concept ("what a passage is") and its endpoints. Do not split the concept into a second file; a reader who wants the endpoints wants the concept on the way past. - All editor-facing content goes in
docs/editor-guide.md. One file, so it exports as a single coherent PDF for the client's editors and nothing drifts between per-entity copies. Add a chapter, do not add a file. - Split the editor guide only when it passes roughly 1,500 lines, and then into
docs/editor-guide/with a build step that concatenates the chapters. Until then, keep it as one file. - Never nav an empty stub. A dead-end page is worse than none.
- Reference pages are generated where they can be.
docs/reference/data-model.mdis rendered from the models bymake data-model-doc, and a test fails when it drifts. Edit the prose above the generated marker; never edit the block below it. - Do not keep a design proposal as a reference page. Pre-build design that the code has moved past reads as fact and misleads. Put the decision in an ADR, the open questions in
.context/, and delete the page; git keeps the text.
This replaced a per-entity folder layout (docs/<entity>/index.md + api-guide.md + editor-guide.md) on 2026-09-23. That layout put three audiences inside every folder and left five near-duplicate editor guides that could not be shared as one document.
Setup for a new Fueled project¶
Copy these files into any repo:
| File | Purpose |
|---|---|
zensical.toml |
Site config — edit site_name, nav |
scripts/docs-build.sh |
Build script — assembles docs/ → _build/ |
.github/workflows/docs.yml |
CI deploy to Cloudflare Pages |
1. Cloudflare Pages project¶
CLOUDFLARE_ACCOUNT_ID=97e8452a103b40bfa5d44e08ceca38bb \
wrangler pages project create <project-name> --production-branch main
Or create via Cloudflare dashboard → Pages → Create project → Direct upload.
2. GitHub secrets¶
Add to repo Settings → Secrets and variables → Actions:
| Secret | Value |
|---|---|
CLOUDFLARE_API_TOKEN |
API token with Cloudflare Pages: Edit on Fueled account |
CLOUDFLARE_ACCOUNT_ID |
97e8452a103b40bfa5d44e08ceca38bb |
Update --project-name in .github/workflows/docs.yml to match step 1.
3. Custom domain¶
- In Cloudflare Pages → your project → Custom domains → Add (e.g.
<name>-docs.fueled.engineering) - In Cloudflare DNS →
fueled.engineeringzone → Add CNAME:<name>-docs→<project-name>.pages.dev(proxied)
4. Cloudflare Access (auth gate)¶
Cloudflare Zero Trust → Access → Applications → Add:
- Type: Self-hosted
- Application domain:
<name>-docs.fueled.engineering - Policy: Allow → Emails ending in
@fueled.com
This gates the entire site behind Google Workspace SSO. Add specific email addresses for client stakeholders.
Zensical config reference¶
Config lives in zensical.toml (TOML, under [project]) — Zensical's replacement for mkdocs.yml. The file ships heavily commented; edit it directly. The load-bearing, non-obvious settings:
| Setting | Value | Why it matters |
|---|---|---|
docs_dir |
"docs/_build" |
Points at the assembled tree, not raw docs/ — building straight from docs/ breaks the ADR section index + glossary tooltips (see How it works). |
nav |
explicit TOML array | Section → page tree; add pages here (see Adding pages). |
site_url |
https://cslewis-docs.fueled.engineering/ |
Canonical URL in the HTML head. |
[[project.theme.palette]] |
default + slate |
Light/dark toggle. |
Build-critical Markdown extensions ([project.markdown_extensions.*]):
pymdownx.superfenceswith amermaidcustom fence — renders the diagrams in the design docs.pymdownx.snippetsauto_appends the generated_build/_includes/abbreviations.md— this powers the glossary tooltips below.admonition/pymdownx.details— theStatus — Live/Plannedboxes.attr_list+md_in_html— the grid cards on section-landing pages.
Enabled nav/UX features include navigation.instant(.prefetch), navigation.sections, navigation.indexes, navigation.path, navigation.top, navigation.tracking, content.code.copy/annotate/select, content.tooltips, and search.highlight; the rest are toggled in the commented features array. zensical.toml is the source of truth — don't re-list the full config here (that just drifts). Full option catalogue: https://zensical.org/docs/setup/.
Glossary tooltips¶
Domain terms from docs/glossary.md automatically render as hover tooltips across all pages. The build script parses the glossary table and generates _build/_includes/abbreviations.md during assembly — no manual sync needed.
To add a tooltip: just add a row to docs/glossary.md. Next build picks it up.
Section index pages¶
Sections with navigation.indexes enabled use an index.md as the section landing page. These live at:
docs/reference/index.md— Reference section landingdocs/guides/index.md— Guides section landingdocs/api/index.md— API reference landing, which also carries the shared conventions
Use Material's grid cards for visual navigation on these pages.
Agent instructions¶
When updating published docs under docs/, remember:
- Run ./scripts/docs-build.sh build to verify no build errors
- Add new pages to nav in zensical.toml
- docs/_build/ is ephemeral — never edit files there directly
- HTML files in docs/ pass through as-is
.context/ is internal-only — it is not assembled into the site or deployed, so these steps (and the docs-deploy trigger) don't apply to it.