---
title: "Writing style guide"
description: "The rules and conventions every page on this site follows, from voice and terminology to plan callouts, page structure, and review."
url: "https://support.outpostplatform.com/contribute/style-guide/"
product: "platform"
type: "reference"
status: "draft"
ai_summary: "The Outpost documentation style guide. Covers audience, voice, US English, the ban on em and en dashes, product and plan names, terminology, page types and their structure, the availability block that states plans, platforms, and permissions, plan limit callouts, preview labels, UI label formatting, code, links, dates, asides, tables, images, and the review checklist."
source: "https://gitlab.com/outpostplatform/docs/-/edit/main/src/content/docs/contribute/style-guide.md"
license: "CC BY 4.0"
---

# Writing style guide

This guide is how Outpost documentation is written. It exists so that pages
written by different people over several years read as one voice, and so that
a reviewer can point at a rule instead of at a preference. Every page on this
site follows it, and every merge request is reviewed against it.

Much of it is enforced. `npm run lint` runs markdownlint plus the Outpost
dash and banned term rules, and `npm run build` runs a link validator, the
frontmatter schema, and a gate over the finished site. Where a rule is checked
automatically, this guide says so.

## Who we write for

Three readers use this site, often for the same feature:

| Reader | What they need from a page |
| --- | --- |
| IT department managers | What a feature does, which plan includes it, what it costs in effort, and what it means for security and compliance. |
| MSP owners | The same, plus how it works across many clients, what it does for billing and margins, and what their clients see. |
| Technicians at both | The exact steps, the exact labels, the permission they need, and what to do when it does not work. |

Write for the technician and make sure the manager can find their answer in
the first paragraph. The opening paragraph of every page says what the feature
or task is, who it is for, and what the reader has when they finish. A manager
who reads only that paragraph and the availability block knows whether the
feature applies to them.

Assume the reader is an experienced IT professional who is new to Outpost.
Do not explain what DNS, a domain controller, or an MSI is. Do explain every
Outpost concept the first time a page uses it, with a link to its concept
page.

## Voice and tone

Professional, precise, calm, and direct. The reader is at work, often with
something not working, and they want the answer. Write the way a senior
colleague explains a system to a peer.

- **Second person, present tense, active voice.** "You enroll the endpoint."
  Not "the endpoint is enrolled by the administrator" and not "we will enroll".
- **Outcome first.** Say what a step achieves before saying which button to
  select. A reader who already knows the button still needs to know why.
- **One idea per sentence.** If a sentence needs a semicolon to hold together,
  it is two sentences.
- **No marketing language.** The product does not "seamlessly", "effortlessly",
  or "powerfully" do anything. It is not "best in class" or "cutting edge".
  State what it does and let the reader judge it. No exclamation marks.
- **No promises.** Describe what the released product does. A page is not the
  place to announce a plan. Features that are built but not released carry the
  preview label described below, and nothing else on the site mentions future
  work.
- **Respect the reader's time.** No preamble ("In this article, we will..."),
  no recap at the end, no padding.

### Words to avoid

These four words are banned, because each one tells a reader who is stuck
that their problem is their own fault:

- simply
- just
- easy
- obviously

Delete them. A sentence almost never needs a replacement.

Also avoid:

| Avoid | Write instead |
| --- | --- |
| please (in an instruction) | The instruction on its own |
| note that | Nothing, or a `:::note` aside |
| should (when you mean does) | does |
| click, click on | select |
| hit (a key or button) | press, select |
| via | through, by, using |
| e.g., i.e., etc. | for example, that is, and so on |
| utilize | use |
| in order to | to |
| allows you to | lets you, or rewrite with you as the subject |
| leverage | use |
| whitelist, blacklist | allowlist, blocklist |
| master (for a primary copy) | primary, main |
| abort | stop, cancel |
| kill (except a literal console label such as **Kill process**) | stop, end |

## Spelling and punctuation

### US English

Write US English, because the console does: enroll, organization, license,
color, canceled, behavior. The one exception is a UI label that the console
spells differently, which you quote exactly as it appears.

### No em dashes and no en dashes

Neither U+2014 (the em dash) nor U+2013 (the en dash) appears anywhere on this
site: not in body text, headings, frontmatter, tables, code comments, or alt
text. This is enforced by the `outpost-no-dashes` lint rule and again by
`scripts/check-dist.mjs` over the built site.

A sentence that seems to want a dash wants something else:

| Instead of a dash for | Use |
| --- | --- |
| An aside in the middle of a sentence | Commas, or parentheses |
| An explanation or a list that follows | A colon |
| A sharp change of thought | A full stop and a new sentence |
| A range of numbers or dates | "to": "1 to 90 days", "2026-10-01 to 2026-10-31" |
| A compound such as "two-factor" | A hyphen, which is allowed |

The hyphen (U+002D) is fine where English uses one: "two-factor
authentication", "S3-compatible", "per-client".

Two hyphens in a row outside code are turned into a dash when the page is
built, and the build then fails. Put every command and flag in code
formatting, such as `outpost-agent uninstall --keep-data`.

### Other punctuation

- Use the serial comma: "Windows, Linux, and macOS".
- Use straight quotes, not curly ones.
- Put one space after a full stop.
- End every list item that is a full sentence with a full stop. Leave fragments
  without one. Do not mix the two in one list.
- Do not end a heading with punctuation.

## Names

### Product and company

| Write this | Not this |
| --- | --- |
| Outpost | Any earlier product name |
| Outpost Business Solutions, PBC (legal contexts only) | Outpost Inc, Outpost PBC |
| the console, or the Outpost console | the dashboard, the web app, the portal |
| the Outpost portal | the billing site, the account site |
| Depot | the server, the tenant server |
| Agent, or the Outpost agent | the client, the endpoint software |
| Tray, or the Outpost tray app | the desktop client |
| Remote Outpost | offline Outpost, the air gapped build |
| Outpost Sync | sync, the sync feature |
| Outpost Cloud Storage | Outpost storage, the cloud bucket |
| Pioneer AI | the AI, the assistant |

What each name refers to:

- **The console** is the web application your team signs in to at your Outpost
  address to manage endpoints. Most pages are about the console.
- **The Outpost portal** is where an account owner signs up, chooses and
  changes a plan, and manages payment methods and invoices.
- **Depot** is the server software behind the console. Use the name when the
  server itself matters, such as deployment, architecture, and the API. Where
  a reader only needs to know where to select something, write "the console".

Outpost runs other central services. This site never names them and never asks
a reader to do anything in them. What a customer deals with is their Outpost
account, the Outpost portal, and their subscription, so write those. If the
architecture makes it unavoidable, write "the Outpost service".

### Banned strings

A short list of strings must never appear anywhere in this repository. They
are former customer and program names, and the old product name. The list is
`lint/banned-terms.json`. The linter fails any file that contains one, and
`scripts/check-dist.mjs` fails the build if one reaches the finished site.

### Plan names

The four plans are **Home Lab**, **Essentials**, **Enterprise**, and **MSP**.
Write them exactly that way, capitalized, without "plan" glued on unless the
sentence needs it: "Enterprise includes the service desk", "on the MSP plan".
Never write "Pro", "Business", "IT", "free tier", or "paid tier". When you mean
every plan except Home Lab, write "paid plans".

Prices, rates, and storage allowances appear on one page only:
[Plans and limits](/account/plans-and-limits/). Other pages state which plans
include a feature, state a numeric limit where the limit changes what the
reader does, and link to that page. This keeps a price change to one edit.

## Terminology

Use these terms with these meanings, every time. Define a term on first use
on a page, or link it to the glossary.

| Term | Meaning |
| --- | --- |
| endpoint | A computer with the Outpost agent installed. Also "managed endpoint". Not "device", "machine", "asset", or "node" in prose. |
| unmanaged device | A device Outpost tracks without an agent, such as a switch, printer, or camera found by network discovery. |
| active endpoint | An endpoint online for four hours or more in a billing period. It is what Enterprise and MSP bill for. |
| client | One organization an MSP manages. On Essentials and Enterprise, the single organization. Not "tenant" or "customer" in prose. |
| site | A physical location that groups endpoints. |
| device group | A named group of endpoints by function. |
| tag | A label a technician applies to endpoints. |
| profile | A named bundle of settings assigned to endpoints. |
| policy | The settings an endpoint ends up with after every profile that applies to it is resolved. |
| baseline | A built-in profile that implements a compliance framework. |
| technician | Anyone on your team who signs in to the console. |
| owner | The console role with full control, including billing. |
| end user | The person who uses an endpoint day to day. |
| enroll, enrollment | Connecting an endpoint to your Outpost. Not "register", "onboard", or "add". |
| retire | Removing an endpoint from management. Not "delete" or "decommission". |

Use the word the console uses. If the console says **Device groups**, the page
says device groups, even if another product calls them collections.

## UI text and navigation

- Quote every UI label exactly as the console shows it, including its
  capitalization, in **bold**: select **Download installer**.
- Write a navigation path with each step in bold, separated by `>`:
  **Settings** > **Team**. Start from the left navigation rail, or say where
  else the path starts, such as the profile menu or the header.
- Use "select" for buttons, links, menu items, tabs, and checkboxes. Use
  "enter" for typing into a field. Use "turn on" and "turn off" for switches.
- Name a field by its label: in **Valid for (days)**, enter `30`.
- Do not describe where a control sits on screen ("the blue button at the top
  right"). Layouts change and colors are not accessible.
- Keyboard keys are in `<kbd>` elements: <kbd>Ctrl</kbd>+<kbd>C</kbd>.

## The availability block

Every page about a product feature carries an `availability` block in its
frontmatter. The site renders it as a box under the page title, the same way on
every page, so a reader can answer "can I use this?" before reading anything
else. GitLab's tier and offering line does the same job.

```yaml
availability:
  plans: [enterprise, msp]
  platforms: [windows, linux, macos]
  permission: remote:initiate
```

| Field | Values | When to set it |
| --- | --- | --- |
| `plans` | `home-lab`, `essentials`, `enterprise`, `msp` | Always, on a feature page. List every plan that includes the feature, in that order. All four renders as "All plans". |
| `platforms` | `windows`, `linux`, `macos`, `freebsd`, `openbsd` | When the feature runs on the endpoint and does not work on every platform the agent supports. |
| `permission` | A permission code such as `script:approve` | When a technician needs a specific permission. Use the most specific one for the page's main task. |
| `preview` | `true` | When the feature is a preview. See below. |

Leave the block off pages that are not about a feature, such as concept pages
about the platform as a whole, account pages, and reference indexes.

### A section gated differently from its page

When one section of a page has a different availability from the rest, put
the component directly under that section's heading. The page must be `.mdx`
to use it.

```mdx
import Availability from '../../../components/Availability.astro';

## Record sessions

<Availability feature="session-recording" />
```

`feature` takes a key from `src/data/plans.json`, so the plans come from the
same file as every other plan statement on the site. `plans`, `platforms`,
`permission`, and `preview` work the same as in frontmatter.

### Plan limits

When a limit changes what a reader can do, state it where they will hit it,
and link to [Plans and limits](/account/plans-and-limits/):

```markdown
:::note
Home Lab allows up to 15 managed endpoints and Essentials up to 50. During a
free trial, Enterprise and MSP allow up to 100. See
[Plans and limits](/account/plans-and-limits/).
:::
```

Take every number from `src/data/plans.json`. When a limit changes, change it
there first, then search the site for the old number.

When a feature is refused because of the plan, quote the message the console
shows, such as **Not included in your plan** or **Plan limit reached**, so a
reader who searches for it lands on the right page.

## Preview features

A preview feature is built and in testing, and not generally available.
Preview pages exist so customers in a pilot can use the feature and so the
documentation is ready on release day.

- Set `availability.preview: true`. The site adds a **Preview** badge in the
  sidebar and a preview notice under the title. Do not write your own.
- Do not state prices, release dates, or commitments on a preview page.
- Describe what the preview does now. Do not describe what it might do later.
- When the feature is released, remove `preview`, review the page against the
  released product, and update its `status`.

## Page types

Every page is one of six types, declared in `type` and written from the
matching template in `templates/`:

| `type` | Answers | Template |
| --- | --- | --- |
| `concept` | What is this, how does it work, and when would I use it? | `templates/concept.md` |
| `how-to` | How do I do one specific thing? | `templates/how-to.md` |
| `reference` | What are all the values, options, or limits? | `templates/reference.md` |
| `troubleshooting` | Why is this not working, and how do I fix it? | `templates/troubleshooting.md` |
| `release-note` | What changed in this version? | `templates/release-note.md` |
| `landing` | Where do I go in this section? | Section index pages only |

A page that is two types is two pages. The most common mistake in product
documentation is a concept page that turns into a procedure halfway down, so a
reader who wanted the procedure reads theory first and a reader who wanted the
theory stops at the first command.

### How a feature section is organized

A feature section follows the same shape every time, like Cloudflare's product
sections:

1. **Overview** (`concept`, the section's `index.md`). What the feature is, who
   uses it, how it works, the plans that include it, and links to every task.
2. **Tasks** (`how-to`). One page per task, named for the task.
3. **Reference** (`reference`). Settings, policy keys, permissions, limits,
   and statuses, as tables.
4. **Troubleshooting** (`troubleshooting`), when there are real failure modes
   to document.

Small features can combine the overview and a single task, but never the
reference.

### Titles

- Task pages start with a verb in the imperative: "Enroll an endpoint",
  "Approve a script".
- Concept pages are a noun phrase: "Remote access", "How Outpost is hosted".
- Reference pages name the thing listed: "Remote access policy settings".
- Troubleshooting pages say what is being fixed: "Troubleshoot remote access".
- Sentence case. No "How to" prefix, no question marks.

### How-to structure

```markdown
One or two sentences: what the reader has when they finish, and when they
would want it.

## Before you begin

- The plan, permission, or role required, if any.
- Anything that must already exist, as links.

## <Task heading, imperative>

1. One action per step.
2. ...

## Verify

How to confirm it worked, and what a good result looks like.

## Next steps

- Links to what most readers do next.
```

"Before you begin" holds anything the reader cannot undo. If a step restarts a
service, disconnects a session, or wipes data, say so there, not in the step.

### Concept structure

Open with what it is and who it is for. Then explain how it works, then the
decisions a reader makes about it (with the plan and platform differences),
then "Related" links. No numbered procedures.

### Reference structure

A short introduction, then tables. Keep the first column the thing a reader
looks up. Sort rows in the order the console shows them, or alphabetically if
there is no order.

## Frontmatter

`src/content.config.ts` is the schema, and the build fails on a page that does
not satisfy it.

```yaml
---
title: Enroll an endpoint
description: Download an installer from the console and enroll a Windows, Linux, or BSD endpoint.
type: how-to
product: agent
status: draft
audience:
  - it-admin
  - msp
availability:
  plans: [home-lab, essentials, enterprise, msp]
  permission: enroll:manage
tags:
  - enrollment
sidebar:
  order: 2
---
```

- `title` is sentence case and is the only H1. Do not repeat it as a heading.
- `description` is one sentence of 160 characters or fewer. It is the search
  result, the meta description, and the card text, so write it for someone who
  has not opened the page.
- `product` is the component the page is about. Feature pages in the console
  are `depot`. Account, plan, and platform pages are `platform`.
- `audience` lists every reader the page serves. Pages for people using the
  Tray on their own computer use `end-user`.
- `status` is `stub`, `draft`, or `reviewed`. A page you have written is
  `draft`. `reviewed` requires `last_reviewed` and means someone checked the
  page against the released product on that date.
- `ai_summary` is optional and written for a model, not a reader. It goes into
  the search index, the page manifest, and the Markdown copy of the page.
- `sidebar.order` places the page within its section. The overview is `1`.
  Order tasks the way a reader does them.

## Headings

- The H1 is the `title`. The body starts at H2.
- Sentence case: "Before you begin", not "Before You Begin".
- No skipped levels.
- Nothing below H3 appears in the table of contents. If a page needs H4 to
  stay navigable, it is two pages.
- Headings are anchors that other pages and search results link to. When you
  rename one, keep the old anchor: `## Enroll an endpoint {#enrollment}`.

## Lists

- Use a numbered list for steps that happen in order, and a bulleted list for
  everything else.
- One action per numbered step. If the reader needs to check something between
  two actions, they are two steps.
- Introduce a list with a full sentence or a fragment ending in a colon.
- When a step branches, name the branch in bold and keep each branch complete:
  **On Windows**, ... **On Linux**, ...

## Code and commands

Every fence names its language, which `MD040` checks:

````markdown
```powershell
Get-Service outpost-agent
```
````

Use `text` for output that is not a language and `console` for a session that
mixes commands and output.

- Placeholders are angle bracketed, lowercase, with hyphens: `<your-address>`,
  `<enrollment-token>`. Say what to replace each one with the first time.
- Example hostnames are under `example.com`. Real Outpost hostnames appear only
  where the page is about that exact host.
- No prompt characters such as `$` or `PS>` at the start of a command.
- Show only commands you have run against the released product.
- Trim long output to the lines that matter.

## Links

- Internal links are root relative with a trailing slash: `/agent/install/`.
  Relative links fail the build.
- Link text says where the link goes: "see [Plans and
  limits](/account/plans-and-limits/)". Never "here", "this page", or "click
  here", which `MD059` fails.
- Links to anchors are checked, so a link to a renamed heading fails the build.
- Link the first mention of an Outpost concept on a page to its concept page.
  Do not link the same page twice in one section.
- External links are fine, and are checked weekly. Prefer vendor documentation
  (Microsoft, Apple, the Linux distribution) over third-party blogs.

## Dates, times, numbers, and versions

- Dates are ISO 8601: `2026-10-12`.
- Times are UTC and say so.
- Durations and counts use numerals: "30 days", "5 minutes", "3 admin users".
- Use commas in numbers of four or more digits: "2,000".
- Write units with a space: "50 GB", "4 hours".
- Versions appear as they do in the product: `0.4.1`, not `v0.4.1`, except in a
  tag name such as `depot-v0.4.1`.
- Never write "currently", "recently", "new", "soon", or "now". Write the
  version or the date, or nothing.

## Asides

Four kinds, and no others:

```markdown
:::note
Context a reader does not need in order to succeed.
:::

:::tip
A faster way for someone who already understands the slow way.
:::

:::caution
Getting this wrong costs time or causes an outage.
:::

:::danger
Getting this wrong loses data, exposes data, or locks someone out.
:::
```

Use no more than two asides per screen of text. If everything is important,
nothing is.

## Tables

Use a table when the reader will look up one row, not read all of them. Keep
the first column the thing being looked up. A table of two columns and two
rows is a sentence. Use "Yes" and "No" in availability tables, not check marks.

## Images

- Store the image next to the page and reference it relatively.
- Use the light appearance only.
- Alt text describes what the reader is meant to see: "The endpoint list with
  one endpoint offline", not "screenshot".
- Never put a value the reader needs only in an image. A screenshot illustrates
  the text. It does not replace it.
- Crop to the part of the screen that matters, and remove real names,
  addresses, and identifiers.

## Security, privacy, and sensitive content

- Never include a real secret, token, password, customer name, hostname, IP
  address, or endpoint identifier, even an expired one.
- When a task can expose credentials, disconnect users, or delete data, say so
  in "Before you begin" and use a `:::caution` or `:::danger` aside.
- Describe security features accurately and specifically. Do not claim
  compliance with a framework; say which controls a feature helps meet.

## Accessibility and inclusive language

- Do not use direction or color alone to identify anything.
- Write descriptive link text and alt text.
- Use gender-neutral language. Refer to people as "they".
- Avoid idioms and culturally specific references. Many readers use English as
  a second language.

## Review checklist

Run through this before you open a merge request. The merge request template
repeats it.

- [ ] The page is one type and follows its template.
- [ ] The first paragraph says what this is, who it is for, and what the reader
      gets.
- [ ] Feature pages carry an `availability` block with the right plans,
      platforms, and permission. Gated sections use the inline component.
- [ ] Every plan limit matches `src/data/plans.json`, and prices appear only on
      the Plans and limits page.
- [ ] Every UI label is quoted exactly and in bold, checked against the
      console.
- [ ] No em dashes or en dashes anywhere.
- [ ] US spellings throughout: color, behavior, organization, license,
      enroll, canceled, labeled, while, among.
- [ ] No banned words, no marketing language, no promises.
- [ ] Terms match the terminology table.
- [ ] Internal links are root relative with a trailing slash.
- [ ] Every command is one you have run.
- [ ] `npm run lint` and `npm run build` pass.

## Check your work

```bash
npm run lint
npm test
npm run build
node scripts/check-dist.mjs
```

The first is fast and catches style. The second checks the scripts and the
plan data. The third catches broken links, invalid frontmatter, and heading
anchors that no longer exist. The fourth checks the finished HTML for the
things that must never ship.
