Part 1 of 3. Stack: #50742 → #50744 → #50743. ## Problem We have several problems: - Style guidance lives in lots of places and need consolidation - Our CONTRIBUTING guide has turned into one massive style document that needs to be broken up ## Solution Add `apps/docs/style-guide/` as plain markdown. | File | Covers | | --- | --- | | `README.md` | What the guide covers, who it's for, how to contribute, and the references it defers to | | `WORD_LIST.md` | Terminology, spelling, capitalization, and the `agent` / `LLM` / `AI` distinction. Moved from `apps/docs/` with history intact | | `01-voice-and-tone.md` | Audience, brevity, sentence construction | | `02-elements.md` | Which component renders each piece, and linking conventions | | `03-page-structure.md` | Document types, information types, grouping, chunking, timeless documentation | ### New content This guide is mostly rearrangement and glue, but it includes some new content: - Links and cross-reference formatting - WORD_LIST entries for LLM and AI agent - Timeless documentation guidance - Accessibility guidance - Sharper guidance on brevity and chunking ## Manual testing 1. Open `apps/docs/style-guide/` on this branch and confirm `README.md` renders below the file list. 2. Follow every link in `README.md` and read the document through. 3. You can test by locally pointing an agent at the style-guide and seeing that it makes great choices when revising a document. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added a documentation style guide covering voice and tone, page structure, and guidance for writing procedures, code, tables, diagrams, media, and links. * Added a word list with preferred spelling, capitalization, and usage, including guidance on inclusive and concise language. * Added recommendations for reviewing documentation drafts and runnable examples. * Replaced the existing word list page’s content with a link to its new location in the style guide. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Nik Richers <nik@validmind.ai>
18 KiB
Choose your components
Once you know what kind of information you have, this is the catalog of forms it can take. Each entry leads with when the component is warranted, then its syntax.
"Component" means the MDX components the docs app provides, such as <Admonition> and
<Tabs>. "Element" means a plain Markdown construct, such as a list or a heading.
| If you're deciding | Read |
|---|---|
| Which form the information should take | Choosing a component |
| How to handle admonitions, emphasis, headings, and lists | Text |
| How to write steps, code, and tabs | Steps and code |
| How to show structured data or a diagram | Data and diagrams |
| How to add an image or a video | Media |
| How to link out or list related pages | Navigation |
| Which constructs to leave out | Don't use these |
Choosing a component
Start from the information type, per 03-page-structure.md.
| You have | Reach for |
|---|---|
| Actions the reader performs in order | A procedure |
| A stage-by-stage explanation | Prose, or a when/then table |
| The parts of something | A table or a diagram |
| A warning or a rule the reader must not miss | An admonition |
| A definition or an idea | Prose, a list, or a diagram |
| Alternative instructions per platform or language | Tabs |
| A curated set of links on an index page | A content listing |
When a phrase fits more than one category, pick the most specific one.
Text
Admonitions
Use an admonition for information a reader might otherwise miss
Reach for one when missing the information would change the outcome of the task. Use one to separate helpful but optional guidance from the main flow. Don't use one for information that belongs in the main explanation or procedure. They highlight important information and get less effective when overused, so don't stack them or use them as decoration.
Begin every admonition with its impact and purpose: the "so what."
Use the first sentence to tell the reader why the information matters: what could happen, what changes, or what benefit they gain. Add background or instructions after the impact is clear.
- Recommended:
Deleting this project permanently removes its database and backups. Export any data that you want to keep before you continue. - Not recommended:
Before you continue, there are a few things that you should know about project deletion.
Don't restate an admonition in the body text
An admonition and the paragraph next to it should cover distinct points. A risk stated twice reads as an editing mistake and trains readers to skip the box.
Choose the type that matches the severity:
| Type | Use for |
|---|---|
danger |
Data loss, exposed data, or another severe, hard-to-reverse outcome |
deprecation |
A deprecated feature or behavior |
caution |
Bugs, failed operations, or unexpected results, short of danger |
note |
A prerequisite, constraint, or clarification that carries no risk |
For danger and caution, state the consequence first, then how to avoid it. For
deprecation, state how the change affects the reader, then the migration path. When a
note is essential to completing a step, put it in the procedure instead of an
admonition.
Structure an admonition with these props:
title(optional): a short callout title. Don't put Markdown or HTML headings inside an admonition. If the content needs a heading to structure the page, move the heading and its section outside the admonition.children: rich body content such as paragraphs, lists, links, and code.actions(optional): standalone calls to action, kept separate from the body. Contextual links and interactive examples stay in the body when they're part of the explanation.
<Admonition type="note" title="Optional title" actions={<Button>Continue</Button>}>
Your content here
</Admonition>
Emphasis
Use bold, italics, and code for distinct purposes
Don't use them interchangeably or to add visual emphasis alone.
| Format | Use for |
|---|---|
| Bold | A UI label, a term the reader must not miss, or an inline label |
| Italics | A new term on first definition, or a title |
Code |
Anything typed, copied, or read literally by the system |
Bold covers the controls a reader interacts with, such as buttons, menu items, and
field names: Click **Save**. It also marks a term they can't afford to skip, as in
**Never** commit your service role key. The third case is the label opening a
paragraph or list item, as in **Recommended**:.
Use italics sparingly, and never for a UI label or for general emphasis. A title set in italics by convention, such as a book or a third-party product, is the other case.
Code covers filenames, paths, commands, flags, environment variables, function and parameter names, configuration keys, and literal values.
A command name is code, not bold, even though the reader also interacts with it.
Don't format for emphasis beyond these three. Screen readers announce text modifications, so a sentence carrying several kinds of formatting is read aloud with the formatting narrated between the words.
Name a control by its label
An icon has no accessible name a reader can match against what you wrote. Write Click **Notifications** rather than Click the bell icon.
Headings
Format headings in sentence case
Capitalize the first word and any proper nouns, and lowercase everything else: Set up authentication rather than Set Up Authentication.
A heading can't carry meaning on its own. See
01-voice-and-tone.md.
Headings are also anchor targets. Other pages, apps/www, and Studio all deep-link into
guide anchors, so renaming a heading breaks those links. Moving a section or changing
its level preserves the anchor; only renaming breaks it.
Lists
Choose the list type by whether order matters
Use an ordered list for steps taken in sequence, and an unordered list when order
doesn't matter. Use Arabic numerals (1, 2, 3) for ordered lists and dashes (-)
for unordered lists.
Prefer a paragraph to a single-item list
A list of one signals content that was meant to grow and didn't. Exceptions: layout consistency across sibling sections, or an item that needs the visual separation.
Don't nest lists more than two deep
1. List item
2. List item
1. List item
2. List item
3. List item
- List item
- List item
<!-- DON'T ADD ANOTHER LEVEL OF NESTING -->
- Overly nested list item
Don't use these
Blockquotes
Use an admonition when the content needs emphasis, or prose when it doesn't.
Footnotes
Put the information in the sentence, or in a linked section when it's substantial enough to need one.
Steps and code
Procedures
Use a procedure when a human or an agent must perform actions to reach an outcome
The format makes that expectation explicit.
Write sequential actions as an ordered list. Begin each step with an imperative verb, and include one action or a closely related set of actions per step. Give the reader enough context to know where to act.
For how many steps to present at once and when to split a procedure into phases, see
chunking in 03-page-structure.md.
An apparent one-step procedure can become two steps when there's a real orientation action:
- Open a terminal in your project directory.
- Run
supabase start.
The first step establishes the operating context for both readers and agents. Don't add
a redundant orientation step to a genuinely atomic instruction. Write Click **Save**.
rather than adding Locate the **Save** button as a separate step.
Code blocks
Keep code lines short so the reader doesn't scroll
Split long shell commands with \.
JavaScript and TypeScript in code blocks are formatted by Prettier, and your pull
request is blocked from merging if the Prettier check fails. Run pnpm format from the
repository root, or set up automatic formatting in your editor.
Prefer lowercase for SQL
Write select * from table rather than SELECT * FROM table.
Optionally specify a filename after the language specifier:
```ts environment.ts
```
Optionally highlight lines with mark=${lineNumber}:
```js mark=12:13
```
Tabs
Use tabs for alternative instructions across platforms or languages
The same task, done differently depending on the reader's stack. Don't use tabs for sequential content or to hide information the reader needs either way.
The optional queryGroup prop lets a reader link directly to a tab, such as
/docs/my-page?packagemanager=npm.
<Tabs scrollable size="small" type="underlined" defaultActiveId="npm" queryGroup="packagemanager">
<TabPanel id="npm" label="npm">
// ...
</TabPanel>
<TabPanel id="yarn" label="Yarn">
// ...
</TabPanel>
</Tabs>
Data and diagrams
Tables
Use a table when each row shares the same set of attributes
A part and its description, a type and when to use it, an if and a then. A table with one populated column is a list.
Keep cells short. When a cell needs more than a sentence or two, the content probably belongs in prose with the table reduced to a summary.
Introduce a table in the sentence before it
Not every screen reader announces that a table is coming. A reader can land in the first cell with no idea what the rows hold.
Don't merge cells
A merged cell breaks the row-and-column relationship a screen reader uses to read a table, so the reader loses track of which heading applies. If the content needs merged cells, it needs two tables.
Diagrams
Use a diagram to support the prose
A rendered diagram reaches fewer readers than the sentence next to it, so the text near it has to carry the takeaway on its own. A reader using a screen reader, a reader on a slow connection, and an agent reading the markdown export all depend on that sentence.
Every diagram needs accTitle and accDescr
Mermaid renders them into the SVG as <title> and aria-labelledby, which is what a
screen reader announces. Without them the diagram is an unlabeled graphic. accTitle is
one line naming what the diagram shows; accDescr describes the content, and takes a
braced block when it runs past one line. See the Mermaid accessibility
options.
Write a fenced code block with mermaid as the language. The MDX renderer routes these
through the shared Mermaid component, so theming follows light and dark mode
automatically. For the full syntax, see the Mermaid diagram
reference.
```mermaid
sequenceDiagram accTitle: Sign-in token exchange accDescr { A user clicks Sign in. The
browser requests authorization from Supabase, and Supabase returns a token to the
browser. }
participant User participant Browser participant Supabase
User->>Browser: Clicks "Sign in" Browser->>Supabase: Request authorization
Supabase->>Browser: Return token
```
- Put a standard Mermaid keyword, such as
sequenceDiagram,flowchart, orerDiagram, on the first line.flowchartaccepts a direction such asLRorTD. - Write
accDescrfor someone who can't see the diagram. Name the nodes and the relationships between them. Restating the title tells that reader nothing. - Keep each diagram focused on a single flow or concept. Split a dense diagram into smaller ones.
- Wrap node labels containing special characters in double quotes, including
*,/, spaces, and punctuation:A["content/**/*.md"]. - Don't hardcode colors. The component themes the diagram for both modes.
A diagram whose content can't survive being described in accDescr and the surrounding
prose is carrying too much. Split it, or replace it with a table.
Media
Images
Use an image when the reader needs to recognize something on screen
A dashboard control that's hard to describe in words is the usual case. Upload images to
apps/docs/public/img.
Use .svg for vector illustrations and .png for screenshots and other non-vector
graphics. Supported browsers receive .webp versions automatically.
Redact sensitive information
Remove API keys and any other secret visible in a screenshot before you upload it.
Write alt text that describes the image
A topic name is what the nearby heading already says. Describe what a reader who can't see it would need: the labeled parts, the relationships between them, and any values it carries.
Every image needs an alt attribute
Give a decorative image an empty one, alt="", so a screen reader skips it rather than
reading a filename.
Never put new information only in an image
Whatever the image shows has to also exist in the text, because a reader who can't see it has no other source.
Don't use an image of text, code, or terminal output
Use real text, which can be read aloud, searched, copied, and translated.
Videos
Include a video as a table of contents video
Don't place a video in the main text. Define it in the page frontmatter:
---
tocVideo: 'rzglqRdZUQE'
---
Navigation
Links
Link selectively
Every link is a decision the reader has to make, so a page dense with them costs more attention than it saves. When a term needs one sentence of explanation, write the sentence instead of sending the reader away. Link the same destination once per page, unless the page is long enough that a reader is unlikely to have seen the first one.
Write link text that describes the destination
Use the target's title, or a phrase that names what the reader gets. The text has to make sense read on its own, because assistive technology can list every link on a page out of context.
- Recommended:
For more information about policies, see [Row Level Security](/docs/guides/database/postgres/row-level-security). - Not recommended:
For more information about policies, [click here](/docs/guides/database/postgres/row-level-security). - Not recommended:
See [this guide](/docs/guides/database/postgres/row-level-security).
Put the identifying words first, and keep the text short
Use the shortest span that still describes the destination: see the [reference section](/link) rather than [see the reference section](/link).
Never use a bare URL as link text
Name the thing instead.
- Recommended:
[HTTP/1.1 RFC](https://www.rfc-editor.org/rfc/rfc2616) - Not recommended:
[https://www.rfc-editor.org/rfc/rfc2616](https://www.rfc-editor.org/rfc/rfc2616)
Introduce a link with see, and say what the reader will find
Write For more information about X, see Y rather than For more information on X, see Y. The about clause is what tells a reader whether the link is worth following.
Keep sentence punctuation outside the link
Write see [Test your code](/link). rather than see [Test your code.](/link).
Say when a link does something the reader won't expect
A download, a new tab, or a jump within the page should be named in the link text or the sentence around it.
Say when a link leaves Supabase docs
Name the destination in the sentence rather than relying on an icon: see the Postgres documentation on [row security policies](https://www.postgresql.org/docs/current/ddl-rowsecurity.html).
Don't include the https://supabase.com origin
For pages on supabase.com, link with a path. Use a /docs/... path for a page in
Supabase docs, such as [getting started](/docs/guides/getting-started). Use a
site-root path for a page outside docs, such as [open the Supabase Dashboard](/dashboard).
Link to a section with its anchor
Within a page, name the section: see the [Links](#links) section of this document.
Across pages, append the anchor to the path:
[Chunking](./03-page-structure.md#chunking). Anchors come from heading text, so
renaming a heading breaks every link to it. See Headings.
For when to cross-reference a section rather than repeat it, see Navigation and glue.
Content listings
Use a content listing on an overview or index page
A content listing holds a curated set of links, such as "Get started", "Next steps", "Examples", or "Resources". Place the component inline in the guide MDX:
<ContentListings id="storage-get-started" />
Use a partial only when the block is reused or gated with $Show at the partial level.
For an individual item that depends on a feature flag, set feature on the item rather
than wrapping the whole listing.
For the data file, ID uniqueness rules, and the test command, see CONTRIBUTING.md.