User Documentation and Screenshots
How the user documentation at /docs/user is structured and how its real-app screenshots are captured and refreshed.
The end-user guide at /docs/user is written in Markdown per language and illustrated with real screenshots of the running app. Screenshots come from an isolated demo workspace, never from a real instance, and every screenshot carries numbered markers that are measured from the live DOM.
Content layout
| Path | Purpose |
|---|---|
docs/user-guide/<de|en|it>/<slug>.md | One chapter per file, with title and description frontmatter. German is the source of truth. |
src/lib/docs/user-guide/chapters.ts | Chapter order, navigation groups, icons, and the app route each chapter opens. |
src/lib/docs/user-guide/screenshots.json | Generated manifest: image path, size, and marker boxes per shot and language. |
public/docs/user/screens/<lang>/<shot>.webp | Generated screenshots. |
src/app/docs/user/page.tsx, src/app/docs/user/[slug]/page.tsx | Overview and chapter routes; ?lang=en or ?lang=it switches the language. |
A screenshot is placed in a chapter with the opening tag on its own line and the closing tag on the next line, followed by the numbered legend:
<docs-shot id="emails-inbox" alt="Posteingang in der Normal-Ansicht">
</docs-shot>
1. **Ordner** – …
2. **Postfach** – …
The legend must have exactly one item per marker. src/lib/docs/user-guide/content.test.ts enforces this, the tag format, alt text, identical shot order across languages, that every captured shot is used, and that every /docs/user/<slug>#anchor link resolves. Anchors come from ## headings of the target language.
Screenshot pipeline
All tooling lives in scripts/docs/:
| Script | Role |
|---|---|
user-docs-server.mjs | Starts Next on port 3220 against the separate clapilot_docs database. Workspace, state, and media directories live in .userdocs-workspace/; the agent runtime, mail servers, and model providers point at dead endpoints so nothing leaves the machine. --app-dir <checkout> serves a production build instead of next dev. |
prepare-user-docs-db.mjs | Creates and migrates the docs database and the fictional team (Carla Lindner as admin, Henrik Seidel, Mira Hartwig). With --content it runs the preview demo seed through the running server, rewrites display text (umlauts instead of ae/oe/ue, example.com/example.org addresses, phone numbers from the fictional 040 66969-xxx range), then seeds chats, team chat, notes, wiki pages, automations, a pending approval, extra modules, and workspace skills. |
user-docs-shots.mjs | Shot definitions: route, preparation steps, and marker targets. Labels are written in German and resolved per language through the i18n dictionaries; key:<i18n key> targets templated labels. |
capture-user-docs-screenshots.mjs | Captures every shot per language in a fresh browser context at 1440×900 (scale 1.25), measures markers, writes WebP files and the manifest. |
Refreshing screenshots
node scripts/docs/prepare-user-docs-db.mjs
node scripts/docs/user-docs-server.mjs --app-dir <clean production build>
node scripts/docs/prepare-user-docs-db.mjs --content
node scripts/docs/capture-user-docs-screenshots.mjs --lang de,en,it
Useful options: --only <id,id> captures selected shots, --preview <dir> additionally writes PNGs with the markers drawn in for review, and --survey <dir> captures raw pages without markers.
Notes:
- Build the app for
--app-dirfrom a clean checkout withCLAPILOT_NEXT_DIST_DIR=.next-userdocs npm run build.next devworks too, but recompiles triggered by other edits can break captures. - The capture pins the browser clock to 09:40 Europe/Berlin on the seeding day, uses Playwright's headless shell so native date inputs follow the capture language, and refreshes the demo mail cache before each shot because the fictional mailbox is served from cache.
- Two shots mask details of the offline demo environment in the page only: the admin agent page hides the "agent cron unreachable" banner, and the admin mailbox page shows
mail.example.cominstead of the dead local mail host. Nothing is saved. - Views that need a live model response, such as regenerating an email reply draft, cannot be captured; describe them in text instead.
