Skip to main content

Writing standards

These standards keep every page consistent regardless of who (or what) wrote it.

Page types​

Every page is exactly one of five types — never mix them:

TypePurposeTemplate
ConceptWhat something is and why it matters — no stepstemplates/concept.md
TaskOne goal, numbered stepstemplates/task.md
ReferenceTables of settings, limits, fieldstemplates/reference.md
API endpointOne REST endpoint: schemas, samples, errors, business rulestemplates/api-endpoint.md
TroubleshootingSymptom → cause → fixtemplates/troubleshooting.md

Page templates​

Start every new page by copying its template from the templates/ folder at the repo root. The task template skeleton:

---
title: <Verb + object, e.g. "Invite team members">
description: <One sentence, ≤160 chars, states the outcome>
sidebar_position: <n>
---

One-paragraph intro: what you'll accomplish and when you'd want to.

## Before you begin
## Steps
## Verify
## Troubleshooting (only if needed)
## Related

KB frontmatter fields​

Every template also carries three fields that map the page into the knowledge base (in-app help and the AI support assistant):

FieldPurpose
categoryThe KB component the page belongs to (Items, POS, Sale Invoices, …) — groups pages in the KB.
keywordsWhat users actually type when searching. Include the synonyms users use, not only the product's terms — bill/invoice, label/barcode.
audiencevendor or internal — controls whether the page is visible in the customer-facing KB.

Pages marked audience: internal must also set draft: true in their frontmatter: drafts never ship in the public production build, while the KB export still includes them with internal visibility. A test gate (npm test) enforces the pairing.

Style rules​

  • Second person ("you"), imperative steps ("Select Save"), present tense.
  • One action per numbered step — if a step needs "and," split it.
  • Bold UI element names exactly as the product shows them: Settings.
  • Keyboard keys in <kbd> tags.
  • Define jargon at first use or link its concept page.
  • Banned words in docs: simply, just, easy, easily, marketing superlatives. Vale enforces these as errors (Docs.BannedWords).
  • Every step must be self-contained in text — never "as shown below", "click the highlighted button", or any instruction whose meaning lives only in an image. Screenshots illustrate; text carries the meaning. Guide content is also consumed without images — by the in-app help search and by an AI support assistant that reads the text alone.
  • :::warning before any destructive or irreversible action.

Map the product's navigation​

The User Guide is grouped by what the reader is doing — setting up, selling, buying, closing the day — not by the app's menu tree. A newcomer does not know the menu yet, and a menu name like "Day Books" tells them nothing; a section called "Money & daily close" does. Inside that grouping every screen stays findable by its app name. The rules:

  • One folder per journey section (docs/guides/<section>/ with a _category_.json whose label is plain language — "Money & daily close"). Its index.md is the landing page: one sentence on what the section is for, an In the app: line naming the app menu or menus it covers, and a table of the screens linking to their guides.
  • One page per screen (submenu item). The page title (and H1) is the exact on-screen label ("Sale Invoices"); the sidebar_label keeps that name and appends what the screen is for after an em-dash ("Sale Invoices — GST billing") — the sidebar stays navigable by the app's own names while telling a newcomer what each entry does. The intro sentence names the path in the app ("Open it from Day Books → Day Book").
  • Task pages nested under a screen (products-stock/items/add-edit-items.md) keep the task template (Before you begin → Steps → Verify) and a plain task title; the screen page above them is the video-first one.
  • sidebar_position follows the reader's order of need within a section — never the alphabet.
  • Every app menu is covered from day one, even before its guides exist: an overview page with a "Coming soon" marker, so each guide has a predictable home before it is written.
  • Moving a page changes its URL. Add a redirect in docusaurus.config.ts for every published URL that moves.

API reference pages​

Start from templates/api-endpoint.md and follow it exactly:

  • One page per endpoint, under docs/developers/<resource>-api/ — never append endpoints to a shared page.
  • Section order is fixed: Overview (with role and plan <Badge> chips) → Request → Response → Status and error codes → Business rules.
  • Sample request tabs use <Tabs groupId="lang"> so the reader's language choice syncs site-wide. Tab order: JSON payload first (when the endpoint has a body), then curl, Java, Python, JavaScript.
  • Role and plan badges sit directly under the <ApiEndpoint> line, above Overview — "what this endpoint is" and "who may call it" belong in the same block, and a reader deciding whether an endpoint is available to them should not have to read a paragraph first.
  • Required parameters are marked Yes * in the Required column. The asterisk is the scannable signal; the word carries the meaning for screen readers and for the plain-text knowledge-base export.
  • Response includes a Field | Type | Description schema table, with a lead-in link to the shared object definition.
  • Every error row carries a machine-readable code slug (validation_failed, rate_limited, server_error, …) matching the API error format.
  • When you add an endpoint, update the endpoints table on the resource's index page (for example the Items API index).

Media pipeline​

Screenshots​

npm run capture -- --url /settings --out static/img/settings/api-keys.png --highlight "#new-key-btn"
  • 1280×800 viewport at 2× scale, element highlighting built in.
  • Name files verb-object.png under static/img/<section>/.
  • Every image needs real alt text — describe what's shown.
  • Only seeded demo data on screen. Never real customer data.

Walkthrough videos​

npm run record -- --flow tools/flows/purchase-invoices.mjs \
--out static/video/purchases/purchase-invoices --poster marker:success --storage-state auth.json
  • Run as long as the operation takes. A clip shows one job from start to finish. A full create, read, update, and delete pass is legitimately several minutes, and cutting it short to hit a target length leaves out the part the viewer came for.

  • Anything long needs chapters. Give each stage a chapter: cue in the flow and viewers jump straight to the step they want. The quality gate requires a chapter track past 90 seconds, and never caps how long a clip may run.

  • Every step needs a say: cue. Those become the caption track, which is a WCAG 2.1 §1.2.2 Level A requirement and the only searchable text a video has.

  • Pin the poster to a marker. ui.mark('success') in the flow plus --poster marker:success keeps the poster on the right frame after a re-record, where a fixed timestamp drifts. The recorder also rejects a blank frame and picks another.

  • Playwright records .webm; ffmpeg produces the web-ready .mp4. Each recording also writes a .webp poster, a .vtt caption track, a .chapters.vtt chapter track, and a .meta.json holding the duration, the poster's origin, and a transcript.

  • Store the files under static/video/<section>/ and embed every track:

    <Video
    src="/video/purchases/purchase-invoices.mp4"
    poster="/video/purchases/purchase-invoices.webp"
    captions="/video/purchases/purchase-invoices.vtt"
    chapters="/video/purchases/purchase-invoices.chapters.vtt"
    />
  • Check the result with npm run media -- --manifest tools/media/<module>.json --check-videos. It reads the committed files only, so it needs no running app.

Quality gates​

Run before committing — all six must pass:

npm run lint:md # markdownlint-cli2: structure
npm run lint:prose # Vale: errors block; Microsoft-style warnings are advisory
npm run lint:js # ESLint over tools/ and tests/
npm run typecheck # components and config
npm test # tooling unit tests
npm run build # broken-link check

PDF manual​

The same Markdown builds a printable manual (chapters listed in tools/pdf-manifest.json):

npm run pdf

Component notes: Figure becomes a plain image, Video becomes a link line, Mermaid diagrams are skipped in PDF output.