Skip to content

Commit de9f254

Browse files
committed
Add CLAUDE.md documenting the hub-and-spoke architecture
Covers the fetch-docs.mjs aggregation pattern, the cross-repo sidebar-maintenance coupling, why component sections are mounted under /docs/<slug>/ instead of /<slug>/ (GitHub Pages URL collision with each component repo's own un-disableable Pages site), the repository_dispatch update flow, and the Markdown/VitePress content gotchas found while migrating the six components off Jekyll.
1 parent 77b15c8 commit de9f254

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What this repo is
6+
7+
The org's root [VitePress](https://vitepress.dev) GitHub Pages site for the DirectProject Java Reference Implementation, published at `https://directprojectjavari.github.io/`. Because the repo name matches the org name exactly (`DirectProjectJavaRI/DirectProjectJavaRI.github.io`), it's the special GitHub "user/org site" — it serves at the domain root, not a `/reponame/` subpath, so `base: '/'` in the VitePress config.
8+
9+
This is a **hub-and-spoke aggregator**, not a self-contained docs repo. The actual Markdown content for each component (agent, gateway, etc.) lives and is reviewed in that component's *own* GitHub repo, on a dedicated `gh-pages` branch — not here, and not on those repos' `master`/`main` branches. This repo only holds the landing page (`docs/index.md`, `docs/overview.md`), the VitePress config/theme, and a build-time script that pulls each component's docs in and merges them into one site. There is no application code here.
10+
11+
## Commands
12+
13+
```bash
14+
npm install # one-time setup
15+
npm run docs:dev # local dev server with hot reload — http://localhost:5173/
16+
npm run docs:build # production build to docs/.vitepress/dist (same as CI)
17+
npm run docs:preview # serve the built dist/ output locally
18+
```
19+
20+
`docs:dev` and `docs:build` both have a `pre` script (`predocs:dev` / `predocs:build`) that runs `node scripts/fetch-docs.mjs` first — component content is never committed here, so it has to be fetched before every dev session and every build. There is no lint or test suite; `npm run docs:build` is the validation step (fails on broken Markdown/config and on dead internal links).
21+
22+
### Testing against an unpushed component branch
23+
24+
`scripts/fetch-docs.mjs` normally clones each component from its real GitHub URL/branch (per `scripts/components.json`). To preview changes on a component branch that hasn't been pushed yet, create `scripts/components.local.json` (gitignored) overriding one or more entries:
25+
26+
```json
27+
{ "agent": { "repo": "/absolute/path/to/local/clone", "branch": "some-branch" } }
28+
```
29+
30+
`git clone` accepts local filesystem paths directly, so this works without a network round-trip.
31+
32+
## Architecture
33+
34+
- `docs/index.md` — hero landing page (hand-built lookalike of VitePress's `layout: home`, since a real `home` layout page doesn't show the sidebar).
35+
- `docs/overview.md` — the actual "what is this project" content, linked from the hero.
36+
- `docs/.vitepress/config.mts` — title, `base: '/'`, nav, and the **hand-maintained sidebar** covering every page across all six components. There is no way to auto-generate this from the component repos' content, so **adding a page in a component repo also requires a sidebar entry here, in a separate PR to this repo.**
37+
- `docs/.vitepress/theme/` — thin extension of the default VitePress theme; `custom.css` carries the site's blue/teal palette (`#155799` / `#159957`, taken from the old `jekyll-theme-cayman` header gradient this site replaced) and the hand-built home-hero CSS.
38+
- `scripts/components.json` — the list of components: `{ slug, repo, branch }`. `branch` is that component's `gh-pages` branch, not `master`.
39+
- `scripts/fetch-docs.mjs` — for each entry, shallow-clones `repo@branch` and copies its `docs/` folder into `docs/<slug>/` here (deleting any stale copy first). Runs identically in CI and locally.
40+
- `.github/workflows/deploy.yml` — builds and deploys to GitHub Pages via Actions on push to `master`, on `repository_dispatch` (event type `docs-updated`, fired by a component repo when its docs change — see below), or manually via `workflow_dispatch`.
41+
42+
### The `/docs/<slug>/` URL prefix
43+
44+
Component sections are mounted at `/docs/agent/`, `/docs/gateway/`, etc. — **not** at the more obvious `/agent/`, `/gateway/`. This is a deliberate workaround, done via the `rewrites` block in `config.mts` (physical files still live at `docs/<slug>/` on disk; only the output route is remapped): every component repo (agent, gateway, direct-msg-monitor, direct-policy, dns, direct-project-stock) has **its own independent GitHub Pages site** already registered at `directprojectjavari.github.io/<reponame>/`, left over from before this repo existed. That registration can't be removed for this org — neither `DELETE /repos/{owner}/{repo}/pages` nor the Settings UI's "Unpublish site" button actually frees the path — so it permanently shadows anything this site tries to serve at the bare `/<reponame>/` path, regardless of what gets built here. If a new component is ever added, mount it under `/docs/<new-slug>/` for the same reason, unless the shadowing repo's Pages site is somehow retired first.
45+
46+
### Cross-repo doc update flow
47+
48+
1. Someone edits `docs/*.md` on a component repo's `gh-pages` branch and merges.
49+
2. That repo's `.github/workflows/notify-docs-hub.yml` (in each of the six component repos, not here) fires a `repository_dispatch` to this repo, authenticated via a `DOCS_DISPATCH_TOKEN` secret set in that component repo (a classic PAT with `repo` scope — cross-repo `repository_dispatch` can't use the default `GITHUB_TOKEN`).
50+
3. This repo's `deploy.yml` catches the dispatch, re-runs `fetch-docs.mjs` (pulling the fresh content), rebuilds, and redeploys.
51+
52+
Adding a **new** component to the hub means: give that repo a `docs/` folder on a dedicated branch (convention: reuse/repurpose its `gh-pages` branch), add its own `notify-docs-hub.yml` + `DOCS_DISPATCH_TOKEN` secret, then in this repo add an entry to `scripts/components.json`, a `rewrites` pair and sidebar section in `config.mts` (using the `/docs/<slug>/` prefix), and a `.gitignore` line for `docs/<slug>/`.
53+
54+
### Content gotchas inherited from the Jekyll → VitePress migration
55+
56+
Each component's docs were converted from a flat, un-frontmattered Jekyll site to VitePress-flavored Markdown. VitePress's Markdown pipeline runs through Vue's template compiler, which is much stricter than Jekyll was about a few patterns that show up in this content — worth checking for if migrating another component or seeing a mysterious "Element is missing end tag" build failure:
57+
58+
- A bare `<placeholder>`-style token in prose or a table cell (not inside a code fence) is parsed as an unclosed HTML tag. Wrap it in a code span: `` `<placeholder>` ``.
59+
- Two inline code spans butted directly against each other with no whitespace between (e.g. `` `<a>`\`<b>` ``) confuses the parser even though each span alone is fine. Merge into one span instead.
60+
- `http://` immediately followed by a backtick (e.g. `` http://`<server>` ``) triggers markdown-it's linkify *before* the code span is parsed, with the same failure mode. Put the whole URL inside one code span.
61+
- Bare `http://localhost...` URLs (not in a code span) get auto-linked and then flagged as dead links by VitePress's build-time link checker, since `localhost` isn't externally resolvable. Wrap in a code span.
62+
- Image filenames must be lowercase extensions (`.png`, not `.PNG`) — Vite's default asset handling doesn't recognize uppercase ones and fails the build.

0 commit comments

Comments
 (0)