tale
AGENTS.md42 starsChanged 12 days agoMITView on GitHub
The repo facts for anyone writing under docs/. The method — reader tasks, observed behavior, useful images, native translations, and verified examples — is the write-docs skill; this file is what its "discover the repo's contract" step discovers. The per-check test reference lives in services/docs/tests/AGENTS.md. - Content: docs/{en,de,fr}/ — three full mirrors; en is the source of truth. A sparse de-CH regional tree is supported (override only pages whose wording genuinely differs from de). - Navigation: docs/nav.json — sidebar order…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository9 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .claude/CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- create-migrationSkill
- write-docsSkill
- write-translationsSkill
- create-migrationSkill
- write-docsSkill
- write-translationsSkill
The file
We split this AGENTS.md into the rules it gives an agent
7 rules. About 0 are common, 2 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 64
Every user-visible change updates en, de, and fr in the same PR.
- Very specific: line 120
After changing any frontmatter, regenerate the manifest the suite checks: bun run --filter @tale/docs build:search-index.
- Distinctive: line 129
Use a concise useful opening.
- Distinctive: line 136
Keep necessary warnings and troubleshooting visible.
- Very specific: line 167
Add "<old slug>": "<new slug>" to docs/redirects.json.
- Very specific: line 170
Keep the old slug's line in docs/published.json.
- Very specific: line 173
Run bun run lint:links, then point every link it reports at the new page.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Tale docs — the repo contract
The repo facts for anyone writing under docs/. The method — reader tasks, observed behavior,
useful images, native translations, and verified examples — is the write-docs
skill; this file is what its "discover the repo's contract" step discovers. The per-check test
reference lives in services/docs/tests/AGENTS.md.
The tree
- Content:
docs/{en,de,fr}/— three full mirrors;enis the source of truth. A sparsede-CHregional tree is supported (override only pages whose wording genuinely differs fromde). - Navigation:
docs/nav.json— sidebar order is array order;labelvalues are i18n keys undernav.groups.*resolved fromservices/docs/messages/{en,de,fr,de-CH}.yml. A page on disk but not in the nav is invisible; a nav slug with no file fails the suite. - Redirects:
docs/redirects.json— old slug → new slug for every moved, merged or deleted page; served as 301s and prerendered as meta-refresh stubs. A page that moved to tale.dev (the legal texts) maps to itshttps://tale.dev/…URL and keeps the reader's locale there. A section folder with no page of its own (/platform/automations) redirects to the first page under it innav.jsonorder — derived, never listed here, so reorderingnav.jsonmoves that target; aredirects.jsonentry for the folder wins. - Published addresses:
docs/published.json— every slug the site has ever served, append-only (the docs build records new pages; never delete a line). Each must keep answering in every locale, as a page or throughredirects.json: a page that goes away without a redirect failstests/published.test.ts. The retiredde-CH,de-ATandfr-CHtrees and guessed addresses (a title turned into a slug, a path translated whole such as/de/plattform/wissen/webseiten, a sidebar group's label such as/de/verwaltung) are answered by the server's near-miss resolver (lib/near-miss.ts), not by entries here; a guess no page clearly wins lands on the section its folders name, and one that names no section gets the 404, which points to/llms.txt. - The site:
services/docs/(Vite + React + TanStack Router, prerendered static HTML). The root and locale roots open the first guide indocs/nav.json, with the same shared documentation frame as every deep guide. There is no separate locale-rootindex.md; legacy root Markdown aliases redirect to the first guide's export. Guide pages keep the platform app design language — aSubPanelnavigation rail, one stickyh-13header strip carrying the breadcrumb trail and the page actions, the article column, and the "On this page" outline (a rail fromxl, a disclosure below it). That chrome is the shared@tale/ui/docs/*frame the design-system guide renders too; change it inpackages/ui, never in a site. Component map:services/docs/README.md→ The page layout.
This contract covers Tale’s product documentation. The separate English design-system guide
at services/ui-docs/content/ follows its own authoring contract
and adds live <Demo> examples; that tag is not part of this site’s Markdown registry.
Directory → tab → audience
| Directory | Tab | Audience |
get-started/ | Start | First success and orientation, with routes matched to the reader's role. |
cloud/ | Cloud | Managed-SaaS readers — onboarding, billing, data residency, trust, compliance. |
self-hosted/ | Self-hosted | Operators running Tale on their own infrastructure. |
platform/ | Platform | Everyday product tasks, feature guides, and explanations shared by Cloud and Self-hosted. |
tutorials/ | Tutorials | Guided end-to-end tasks on a running instance, with explicit prerequisites and checkpoints. |
develop/ | Develop | API consumers, webhook integrators, SDK users, source contributors. |
legal/ | (footer) | Privacy policy, terms of service, DPA. noindex: true; exempt from the journey treatment. |
platform/ vs self-hosted/configuration/. platform/ is the UI — anything a user does
inside the running app (Settings > …). self-hosted/configuration/ is server-side — config
files (TALE_CONFIG_DIR/**), env vars, CLI, Docker. When a feature has both, platform/ describes
only the UI path and links to the self-hosted reference. Never paste a JSON config snippet or an
env-var table into a platform/ page — it contradicts the Cloud reader's reality.
Locales ship together
Every user-visible change updates en, de, and fr in the same PR. locale-tree,
locale-outline, and locale-components check presence and structure; reviewers verify equivalent
meaning and completeness. DE and FR are authored natively per
write-translations (one narrator per language,
du/tu, loanword buckets), never rendered word-for-word. UI labels match
the relevant service’s messages/<locale>.yml (the platform’s messages/<locale>/<topic>.yml) merged over shared package catalogs character-for-character,
including locale fallback. Preserve factual currencies, values, jurisdictions, permissions, and
limits while translating. A locale changes the language, not the contract. The voice strike lists live in
packages/ui/src/i18n/tests/locales/<locale>/voice.ts. Internal links in non-en pages carry the
locale prefix (/de/..., /fr/...) — including href attributes on components.
The component registry
The renderer is react-markdown + rehype-raw; the authored vocabulary lives in
packages/ui/src/markdown/components/registry.tsx:
<Note> <Tip> <Info> <Warning> <Check> <Callout tone>, <Card title icon href> /
<CardGroup cols>, <Steps>/<Step title>, <Tabs>/<Tab title>, <CodeGroup> (tab labels
from the fence meta string: ```bash cURL), <Accordion>/<AccordionGroup>,
<Frame caption>, and ```mermaid fences. GFM alerts (> [!NOTE]) render as callouts. Icons
on <Card> are kebab-case Lucide names. Blank lines between every component tag and its
content — the markdown inside won't parse otherwise. Images only as
 markdown syntax inside <Frame> — a raw <img> escapes the image
checks.
Frontmatter opt-outs (Tale-specific)
noindex: true (legal/drafts), kind: index (section index pages whose cards provide the opening
orientation), noCurrencyCheck: true, noEmDashCheck: true, i18nLintExclude: ["check-id"] —
sparingly, with a comment.
Screenshots — the Tale pipeline
- Assets: WebP under
services/docs/public/images/<section>/(section mirrors the docs area), referenced/images/<section>/<name>.webp, dash-case content-named, < 200 KB, full-sentence alt. Enforced byservices/docs/tests/images.test.ts. - Capture: manifest-driven — every image is declared in
services/platform/tests/docs-screenshots/manifest.tsand captured withbun run docs:screenshots [-- --only <shot>]against the seeded local stack (the runbook isservices/platform/tests/docs-screenshots/README.md). No hand-captured image ships. When a PR changes a route, grep the manifest for it and regenerate in the same PR. - CLI output:
tools/cli/scripts/cli-sample-outputs.sh(sanitized) — but prefer fenced code. - Docs share EN captures by default; alt text and captions translate per locale. The same
pipeline supports
--locales en,de,frfor native UI captures used by marketing or a locale-specific layout example. DE/FR files live under<section>/<locale>/and the generated image manifest records each capture's locale.
Commands
bun run --filter @tale/docs dev # preview on :3002 (builds the search index first)
bun run --filter @tale/docs lint # oxlint --type-aware
bun run --filter @tale/docs test # the structural suite — see services/docs/tests/AGENTS.md
bun run --filter @tale/docs build # search index, prerender, llms.txt, sitemap
bun run format # repo-wide oxfmt — services/docs has no format scriptAfter changing any frontmatter, regenerate the manifest the suite checks:
bun run --filter @tale/docs build:search-index.
Content decisions
Give each page a primary job: first-time tutorial, focused how-to, explanation, reference, troubleshooting, or navigation. Match the assumed knowledge to the task, not a vague “all users” audience. Readers should be able to enter from search and identify the prerequisites and outcome.
Use a concise useful opening; one sentence can be sufficient. Add detail where it answers a real question: access requirements, inputs, choice of setting, visibility, persistence, result, limits, or recovery. A field inventory alone does not explain how to complete a task. A tutorial should provide a verified path and observable checkpoints without requiring optional reference reading.
Images clarify unfamiliar locations, states, or results. They are not required at every step; written instructions must remain complete without them. Tips need a concrete optional benefit. Keep necessary warnings and troubleshooting visible. End when the page has answered the need; a recap and a named closing are optional. Useful next links do not require a padding paragraph.
Existing pages are evidence to inspect, not “perfect” templates to reproduce. Find the canonical owner of a claim, verify it, and link it rather than spreading copies of limits or settings. Published URL changes require redirects and a repo-wide inbound-link sweep.
Product evidence and review
Drive the running platform's described tasks using seeded disposable data. Record the starting role/state, actions, result, and relevant failures in the task note outside the clone. Read source and tests for hidden behavior, but do not substitute them for using a UI. Verify code examples in the documented environment and label any excerpts or normalized output.
An observed mismatch is a docs or product finding. Fix an authorized defect with a regression check and rerun the flow; otherwise record it and document the verified limitation. Do not invent unobserved waiting times or platform promises. Keep existing videos unchanged when videos are outside the task's scope.
Review rendered pages at desktop and narrow widths. Check heading hierarchy, keyboard navigation, component rendering, image legibility, tables, and code. Read each locale independently for flow, then compare factual meaning. Run checks and inspect advisory locale findings; a green structural suite does not establish fluent or accurate prose.
Retire, rename or merge a page
A docs address that was ever published keeps answering: bookmarks, search results, links in older releases and language models all still ask for it.
- Choose the page that replaces it: the one that answers the same reader task. Only a page with no successor falls back to its section.
- Add
"<old slug>": "<new slug>"todocs/redirects.json. One locale-less entry covers/deand/fr, and a page that moved to tale.dev maps to itshttps://tale.dev/…URL. - Keep the old slug's line in
docs/published.json. Never delete a line. - Move or delete the file in all three locales, with
git mvfor a rename, and updatenav.json. - Regenerate with
bun run --filter @tale/docs build:search-index(the manifest and the ledger). - Run
bun run lint:links, then point every link it reports at the new page. That covers docs pages, READMEs, app help and the marketing site. - Renaming only a heading that others link to: keep its old id with
{#old-id}.
The gates hold you to it. bun run lint:links compares the change with its base commit. It refuses
a deleted or renamed page whose old address now answers 404 (retired-page-404), naming the
redirect to add, and a removed ledger line (published-line-removed). tests/published.test.ts
refuses any published slug that stops answering in any locale.
Pitfalls
- A file on disk but missing from
nav.jsonis invisible in the sidebar. - Translated heading anchors:
/de/foo#some-headingonly works if the German heading slugs tosome-heading, or the heading has that explicit ID. The link suite (tests/links.test.ts) verifies every fragment against the ids the target page renders. - External links cast as internal (
](/external-site)) 404 — fully qualify them. - Env-var and API reference content is authoritative in one place — link, don't duplicate.
- Moving, renaming or deleting a page without a redirect: follow Retire, rename or merge a page; the gates refuse anything less.
- Reordering
nav.jsoncan change where a section folder URL (/platform/<section>) redirects: it lands on the first page listed under that folder.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

