Help center (Starlight)
The user-facing help center lives in docs/user/ and renders per-product guides
plus the VPAT Parser API reference. Itβs built with Starlight (Astro); the API
reference is rendered by starlight-openapi from
docs/api/vpat-parse-openapi.yaml.
Migrated off Docusaurus/Redoc β Starlight on 2026-09-11. Redocβs API reference produced WCAG AA violations that could only be fixed inside Redocβs source (keyboard traps,
aria-hiddenfocusables, clipped-at-200%-zoom tables β seedocs/admin/help-site-redoc-a11y-debt.md). starlight-openapi renders the same spec as native semantic markup, so the whole site β including the API reference β passes the pa11y WCAG2AA gate (49/49 pages) with no override CSS. Content is authored in Markdown as before; admonitions (:::note) carried over unchanged.
Where itβs served
It has its own hostname:
https://help.gevell.com β help center homehttps://help.gevell.com/pdf/ β Gevell PDF sectionhttps://help.gevell.com/api/vpat-parse β API referencedocs/user/astro.config.mjs sets site: https://help.gevell.com. The site is
served by a dedicated assets-only Cloudflare Worker defined in
docs/user/wrangler.toml (Workers Static Assets over ./dist) on the
help.gevell.com custom domain.
Old location (redirected)
The help center used to be mounted at acr.gevell.com/docs, served by the
apps/vpat worker. That worker now 301-redirects \/docs and \/docs/* to
help.gevell.com, preserving the sub-path. The pre-reorg PDF guides are
additionally covered by the redirects map in astro.config.mjs β the three that
moved under /pdf/ (e.g. /convert-by-email β /pdf/convert-by-email) and the
two retired ones (canvas-lti-setup, custom-gpt), which fall back to the /pdf/
hub rather than 404.
PDF app docs (pdf.gevell.com/docs). The converterβs own public help β
17 guides in apps/web/content/guides/*.md plus apps/web/content/faqs.md β was
folded into this help center (Phase 2). The guides now live under /pdf/*
(usage), /account-billing/* (account, billing, refunds), and
/getting-started/getting-support; the FAQs became /pdf/faq; the four
automation guides (MCP server, Claude Desktop skill, CI/CD, shared folder) were
consolidated into /pdf/integrations. apps/web/public/_redirects 301s every
old /docs/* URL to its new help-center home (per-slug rules first, a /docs/*
catch-all to /pdf/getting-started/ last). /docs/internal stays served
locally (admin-gated) via a passthrough rule placed before the catch-all. The
Canvas LTI and ChatGPT Custom GPT guides were intentionally not migrated;
their old URLs redirect to the /pdf/ hub. The apps/web/content/guides sources
remain in the app repo (now shadowed by the redirects) and can be pruned in a
follow-up.
Structure
Top-level sidebar sections are generated from the product registry
(packages/accessible-org-ui/src/products.ts) so the help center canβt drift
product-incomplete:
src/content/docs/getting-started/β landing + cross-product intro (first); itsindex.mdcarriesslug: /-equivalent placement as the site rootsrc/content/docs/<product-id>/β one section per registry product, in ordersrc/content/docs/account-billing/β sign-in, credits, plans, workshops (last)
scripts/sync-sidebar.mjs writes src/sidebar.generated.mjs (imported by
astro.config.mjs) β one Starlight sidebar group per section, label = canonical
product name, order = registry order, with the non-product sections SSO (90) and
Guides (99) interleaved. npm run build runs it first; npm run check:sidebar
(CI) fails if a registry product has no docs section or the generated sidebar has
drifted from the registry. The pure logic is unit-tested in
scripts/sync-sidebar.test.mjs (npm test).
Build & deploy
cd docs/usernpm ci # note: .npmrc pins legacy-peer-deps (vitest 4 + Astro's Vite)npm run deploy # sync:sidebar β astro build β wrangler deployThe docs build is validated in CI by .github/workflows/docs.yml on any PR
touching docs/user/** or docs/api/**: unit tests, the check:sidebar
coverage check, the Astro build, and a pa11y WCAG2AA scan of every built page
(served via astro preview, driven off dist/sitemap-0.xml).
A post-build integration, src/integrations/dedupe-ids.mjs, renames any
duplicate element id in the output (astro:build:done). It exists because
starlight-openapi emits two <h4 id="headers"> per operation page (request +
response Headers); without it the pa11y duplicate-id rule fails.
Adding a new productβs help
- Add the product to
packages/accessible-org-ui/src/products.ts. - Create
docs/user/src/content/docs/<id>/index.md(a short, accurate overview is enough). npm run sync:sidebarto regeneratesrc/sidebar.generated.mjs.
Skipping step 2 makes check:sidebar fail in CI β by design.
To keep a registry product OUT of the help center (it stays in the footer /
cross-promo but gets no help section), add its id to EXCLUDED_FROM_HELP in
scripts/sync-sidebar.mjs and delete its src/content/docs/<id>/ directory. The
check then stops requiring a section for it β and fails if a leftover one
reappears.
Screenshots (visual walkthroughs)
PDF-section pages embed screenshots from docs/user/public/img/pdf/, referenced
via <figure> + <img>. Light/dark pairs use two <img> tags with
Starlightβs dark:sl-hidden (the light image) and light:sl-hidden (the dark
image) utility classes β both carry the same alt (the display:none one is
ignored by assistive tech). Single-variant shots use one plain <img>. Images
live in public/ so they publish at /img/pdf/<file>; alt text lives in the
referencing .md.
These are copied from the PDF appβs curated set at
apps/web/public/docs/screenshots/ (hand-captured β there is no automated
generator yet). To refresh after a UI change: recapture in apps/web (light and
dark for a themed pair), copy the file(s) into public/img/pdf/ keeping the same
names, and confirm the alt text still matches. npm run build plus the pa11y CI
gate (fails on a missing alt) catch broken or unlabeled images.
| File(s) | Used on | Themed? |
|---|---|---|
dashboard-empty.png (+ -dark) | pdf/getting-started (upload area) | yes |
dashboard-row-expanded.png (+ -dark) | pdf/getting-started, pdf/downloading | yes |
compare.png | pdf/downloading (Compare view) | no |
documentsettings.jpg | pdf/downloading (Header & Footer) | no |
documentstyling.jpg | pdf/downloading (Styling) | no |
The sign-in screenshot was intentionally not used β the captured version showed retired βPDF Converterβ branding and a stale βSend Magic Linkβ flow. Recapture on-brand (Gevell PDF, one-time email code) before adding one. Other products (OrgChart, Audit) have no help-center screenshots yet.