# Documentation website

Hugo builds this site into static HTML, CSS and JavaScript. Cloudflare Workers Static Assets serves the output at https://cicadel.fauzaanu.com. There is no Cicadel application server, database or paid search service.

## Build and verify

Install **Hugo 0.169.0**, Go (the version in the root `go.mod`), Python 3 and Node.js 22 or later. From this directory:

```sh
npm ci
npm run build
npm run check
python3 scripts/test-check-urls.py
python3 scripts/check-urls.py   # every URL in the built site; --offline skips external sites
node --check static/app.js
node scripts/test-search.cjs
python3 scripts/test-versions.py
python3 scripts/test-examples.py
npx wrangler deploy --dry-run
```

`HUGO=/path/to/hugo npm run build` selects a specific binary. Build output is `public/`; never edit or commit generated content. Open the generated HTML using your preferred local static hosting tool for manual visual review.

## Authoring

Edit the original Markdown in `docs/` and module READMEs. `data/navigation.json` maps source files to the first steps, topic guides, how-to guides, reference, releases and internals sections. That four-part structure comes from Django's docs; the voice and design do not. Follow [Writing the docs](https://cicadel.fauzaanu.com/en/0.2.7/internals/writing-docs/index.md) for tone, page shape, callouts and diagrams. Add a source entry there to publish a guide. Internal Markdown links are rewritten to the correct version; repository-only files link to their matching Git source. Page headings produce the table of contents. Search is built locally into `index.json` and filtered by selected version.

The "chemical light" theme lives in `layouts/` and `static/`: a near-black ground with glow-stick green (`--chem-500`, `#7dff3a`) and a deeper green for light mode. Pages have a left navigation tree, an "On this page" rail that tracks your position, previous/next cards, callouts rendered from GitHub alert syntax (`> [!NOTE]`) and diagrams inlined from `docs/diagrams/*.svg` so they follow the theme. Search opens with Ctrl/Command K or `/` and supports arrow keys. The theme follows the system setting until you choose one. Geist and Geist Mono are self-hosted (SIL OFL; see `static/fonts/`). No third-party scripts or remote font requests are used.

`check.py` verifies relative links and `#fragments`. `check-urls.py` verifies every absolute URL: links to this site must resolve to a built page, links into this repository are checked against git (at `main` in the tree being published, otherwise at the linked release commit), workflow-run links use the authenticated `gh` API, and external sites are requested over HTTP. A broken link that exists only inside a frozen release is a warning, because release pages cannot change; fix it in dev.

The cicada mark and the hero art come from `design/`. `static/cicada.svg` is the traced mark used by the logo and favicon; `python3 scripts/cicada-ascii.py` (needs Pillow) regenerates `data/cicada.json`, the ASCII art the home page animates with `static/cicada.js`.

## LLM-readable documentation

The build generates these public endpoints automatically:

- `/llms.txt`: the development documentation index, plus links to every version.
- `/llms-full.txt`: the complete development documentation in one text file.
- `/en/VERSION/llms.txt` and `/en/VERSION/llms-full.txt`: version-specific indexes and full bundles.
- `/en/VERSION/GROUP/PAGE/index.md`: clean Markdown for each published guide. Section and overview pages also have `index.md` copies.
- `/en/VERSION/sources/PATH.md`: supplemental documents outside the website navigation.

The application index includes the application navigation and sources listed in `data/application-sources.json`. Framework philosophy, contributor guides, roadmaps and implementation evidence have a separate `/en/VERSION/framework/llms.txt` index and `llms-full.txt` bundle. Keep application guides short and task-oriented, with working code and copyable agent prompts; put framework decisions in the framework section. Absolute documentation URLs in prompts follow the selected version automatically.

Together the two corpora include all Markdown in `docs/`, `contrib/`, `examples/` and `skills/`, plus the project README, changelog, roadmap, security policy, battery inventory and this authoring guide. Repository agent instructions and build artifacts are excluded. A version's `llms-manifest.json` records each source and Markdown URL so completeness can be checked. Relative documentation links point to Markdown in the same version; code examples remain unchanged.

Each HTML documentation page advertises its Markdown copy with `rel="alternate" type="text/markdown"` and its version's index with `rel="describedby"`. The HTTP `Link` header advertises the root index too. Markdown and text exports have explicit content types and require no JavaScript.

Exports read the same working tree or frozen release commit as the HTML build. Release snapshots include supplemental documents and authoring skills, not just the main navigation. The version test modifies both ordinary and supplemental guides after a simulated release to verify isolation.

## Versions and releases

`versions.json` initially contains only `dev`, built from the current checkout. After publishing a release tag:

```sh
python3 scripts/add-version.py v0.1.0
npm run build
npm run check
```

Commit and push the updated manifest to `main`; GitHub Actions builds and publishes the complete site. The helper resolves the tag to an immutable commit SHA. Release content **and navigation** are read from that commit; subsequent changes to `dev` cannot rewrite them. Releases must include the website navigation manifest. Fetch full Git history when building; CI uses `fetch-depth: 0`. Each version is served at `/en/VERSION/`. The root redirects to `/en/dev/` until a stable release policy changes it. Existing versions are always rebuilt alongside dev, so a deployment preserves their URLs. Do not remove published versions from the manifest.

## Deploy

The tracked `wrangler.jsonc` targets the personal account and the `cicadel-docs` Worker, with the custom domain `cicadel.fauzaanu.com`. Set `CLOUDFLARE_API_TOKEN` securely in the process environment and `CLOUDFLARE_ACCOUNT_ID` to the configured account. Never commit credentials.

```sh
npm run build
npm run check
npm run deploy
python3 scripts/check-live.py
```

The `Documentation` GitHub Actions workflow builds static assets, HTML, search and both LLM corpora on every push and pull request. It tests links, frozen versions, executable documentation examples and JavaScript, then archives the verified `public/` directory. On pushes to `main`, a separate publish job downloads that exact artifact and deploys it to Cloudflare. Pull requests never receive deployment credentials or publish. Manual `workflow_dispatch` on `main` can republish a checked build.

The GitHub `documentation` environment holds the `CLOUDFLARE_API_TOKEN` secret. The account and Worker are explicit in the workflow/config. Deployment jobs are serialized and never cancelled mid-upload. The post-deploy check compares live exports and fonts with the artifact, checks page discovery, the root redirect and a missing-page 404. A failing check makes the Actions run fail. Review the run before considering a docs update delivered.

Future agents only edit source Markdown, navigation or theme files, run the required local checks, then commit and push. They need no local Cloudflare credentials. Never commit `public/` or tokens. Run all repository-required CI checks locally before any push. Static asset requests are served without Worker code execution.


### Non-browser access on Cloudflare

The zone-level custom rule in `cloudflare/browser-integrity-rule.json` skips only Browser Integrity Check for `GET` and `HEAD` on `cicadel.fauzaanu.com`. This prevents Cloudflare error 1010 for ordinary HTTP clients fetching public documentation. Other hostnames, methods, managed firewall rules and rate limits are unaffected. The rule is applied separately through the Cloudflare Rulesets API; Wrangler does not manage it. Its stable rule reference is `cicadel_docs_machine_readable`.

`check-live.py` deliberately uses Python's default HTTP client without browser impersonation, cookies or JavaScript. It compares every documentation export and font with the local build and checks the root redirect and 404 response. Run it after deployment to detect content drift or an edge security setting that blocks LLM readers.
