Writing docs
How a Remy app's docs are laid out and written with Fumadocs: folders, frontmatter, media, components, translations and the CLI.
Every Remy app keeps its docs the same way, so the shared tasks and the Fumadocs CLI work in each one.
There are two docs sites, served by the docs Worker (the docs/ app, apart from the app Worker): the guide
for the app's users at /docs, and these developer docs at /dev.
Each has its own languages, search, llms.txt and Ask AI folder.
Who each part is for
The docs have three parts, and each is written from one reader's side. Google's AI Mode, Gemini and every other assistant tell them apart only by what the pages say, so keep them apart:
| Part | Reader | Writes about | Never |
|---|---|---|---|
Product guide, content/users/ (/docs) | someone using the app | what they see and do in the app | code, tools, the repository, deploys |
Developer docs, content/dev/ (/dev) | a developer building Remy or an app on it | code, tasks, tools, rules | how to use the app, beyond a link to the guide |
API reference (/reference) | a developer calling the API | endpoints, generated from the contract | prose; it is generated |
- A page that needs the other side links to it in one line ("Building it? The developer docs.").
- Each part's home page opens by saying who it is for; its titles end with the part's name (
docs.config.ts,titles), and so do itsllms.txtand MCP server (Docs in your AI tools). - The parts, their readers, llms files and MCP servers are one list,
src/lib/sections.ts.
Layout
i18n.jsonis the site's languages:defaultLanguageandlanguages. The site's URLs, language menu, search and translation tasks all read it. The two sites' lists differ: developer docs are translated only into the languages we support developers in.meta.jsonis the site's navigation:pagessets the order,"---Heading---"starts a section,"[Title](https://…)"is a link out.- A translation sits beside its page:
index.es.mdbesideindex.md, at/dev/es/. - The guide's pictures and videos are in
docs/public/media, referenced by URL (/media/formats.png); the developer docs have Mermaid diagrams and type tables; the API reference is its own section at/reference, made from the oRPC contract.
How a page reaches the reader
flowchart LR A["docs/content/*.md, *.mdx"] --> B["fumadocs-mdx macro"] B --> C["loader: src/lib/source.ts"] C --> D["Docs pages: /docs, /dev"] C --> E["Search: /api/search/dev"] C --> F["/dev/llms.txt and .md pages"] C --> G["MCP server: /api/mcp/dev"] C --> H["Social images: /og/dev/..."] I["oRPC contract"] --> J["fumadocs-openapi"] --> K["API reference: /reference"]
Frontmatter
Every page starts with a title and a description. The description is the page's summary in search
results, llms.txt and link previews.
---
title: "Formats"
description: "How dates, numbers, currency and direction change with the language you choose."
---Pictures and videos
Take them with the project's own tool, so they show the real app:
npm run shots -- /formats --out docs/public/media for a picture, and add --video
for a short recording of the page.
Fumadocs sizes it, and a click enlarges it.
Components
In .mdx pages: <Callout> (or :::note, :::warning in any page), <Cards> and <Card>, <Tabs>
and <Tab>, <Steps> and <Step>, <Accordions> and <Accordion>, <Files>, <Folder> and
<File>, a ```mermaid diagram, and a type table read from our TypeScript:
Prop
Type
The Fumadocs CLI
npm run docs:cli -- feature <name> (remy-auth only) runs the pinned Fumadocs CLI in the shared docs
Worker, packages/ui/src/docs; its cli.json maps the folders there, and what it writes is a change to
the package, reviewed like any other. Apps take the Worker from the package and never run it.
| Feature | What it gave this site |
|---|---|
llms | /<site>/llms.txt, /<site>/<lang>/llms-full.txt, /<site>/<lang>/<page>.md |
mcp | an MCP server per part, /api/mcp/docs, /api/mcp/dev, /api/mcp/reference (Docs in your AI tools) |
og | a social image per page |
webmcp | the docs as tools for agents in the browser |
Translations
Write English only. dev:land translates on main after the landing, one writer at a time
(translations: one writer); npx remy i18n check docs lists what each
language still needs.
The command line
remy, the tooling every Remy app installs with the package: the scripts, the layout they read, a new app, publishing packages, translations, Cloudflare and plans.
Docs in your AI tools
Every MCP server and llms.txt here, who each is for, how to add them to ChatGPT, Claude, Cursor, VS Code or Gemini, and how Google's AI Mode sees the docs.