Skip to content

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.

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

ReaderWhat they need from a page
IT department managersWhat a feature does, which plan includes it, what it costs in effort, and what it means for security and compliance.
MSP ownersThe same, plus how it works across many clients, what it does for billing and margins, and what their clients see.
Technicians at bothThe 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.

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.

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:

AvoidWrite instead
please (in an instruction)The instruction on its own
note thatNothing, or a :::note aside
should (when you mean does)does
click, click onselect
hit (a key or button)press, select
viathrough, by, using
e.g., i.e., etc.for example, that is, and so on
utilizeuse
in order toto
allows you tolets you, or rewrite with you as the subject
leverageuse
whitelist, blacklistallowlist, blocklist
master (for a primary copy)primary, main
abortstop, cancel
kill (except a literal console label such as Kill process)stop, end

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.

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 forUse
An aside in the middle of a sentenceCommas, or parentheses
An explanation or a list that followsA colon
A sharp change of thoughtA 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.

  • 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.
Write thisNot this
OutpostAny earlier product name
Outpost Business Solutions, PBC (legal contexts only)Outpost Inc, Outpost PBC
the console, or the Outpost consolethe dashboard, the web app, the portal
the Outpost portalthe billing site, the account site
Depotthe server, the tenant server
Agent, or the Outpost agentthe client, the endpoint software
Tray, or the Outpost tray appthe desktop client
Remote Outpostoffline Outpost, the air gapped build
Outpost Syncsync, the sync feature
Outpost Cloud StorageOutpost storage, the cloud bucket
Pioneer AIthe 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”.

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.

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. 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.

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

TermMeaning
endpointA computer with the Outpost agent installed. Also “managed endpoint”. Not “device”, “machine”, “asset”, or “node” in prose.
unmanaged deviceA device Outpost tracks without an agent, such as a switch, printer, or camera found by network discovery.
active endpointAn endpoint online for four hours or more in a billing period. It is what Enterprise and MSP bill for.
clientOne organization an MSP manages. On Essentials and Enterprise, the single organization. Not “tenant” or “customer” in prose.
siteA physical location that groups endpoints.
device groupA named group of endpoints by function.
tagA label a technician applies to endpoints.
profileA named bundle of settings assigned to endpoints.
policyThe settings an endpoint ends up with after every profile that applies to it is resolved.
baselineA built-in profile that implements a compliance framework.
technicianAnyone on your team who signs in to the console.
ownerThe console role with full control, including billing.
end userThe person who uses an endpoint day to day.
enroll, enrollmentConnecting an endpoint to your Outpost. Not “register”, “onboard”, or “add”.
retireRemoving 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.

  • 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: Ctrl+C.

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.

availability:
plans: [enterprise, msp]
platforms: [windows, linux, macos]
permission: remote:initiate
FieldValuesWhen to set it
planshome-lab, essentials, enterprise, mspAlways, on a feature page. List every plan that includes the feature, in that order. All four renders as “All plans”.
platformswindows, linux, macos, freebsd, openbsdWhen the feature runs on the endpoint and does not work on every platform the agent supports.
permissionA permission code such as script:approveWhen a technician needs a specific permission. Use the most specific one for the page’s main task.
previewtrueWhen 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.

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.

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.

When a limit changes what a reader can do, state it where they will hit it, and link to Plans and limits:

:::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.

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.

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

typeAnswersTemplate
conceptWhat is this, how does it work, and when would I use it?templates/concept.md
how-toHow do I do one specific thing?templates/how-to.md
referenceWhat are all the values, options, or limits?templates/reference.md
troubleshootingWhy is this not working, and how do I fix it?templates/troubleshooting.md
release-noteWhat changed in this version?templates/release-note.md
landingWhere 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.

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.

  • 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.
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.

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.

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.

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

---
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.
  • 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}.
  • 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, …

Every fence names its language, which MD040 checks:

```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.
  • 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”. 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 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.

Four kinds, and no others:

:::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.

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.

  • 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.
  • 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.
  • 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.

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.
Terminal window
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.

Content is licensed CC BY 4.0. Code samples are MIT. Outpost and the Outpost mark are trademarks of Outpost Business Solutions, PBC and are not covered by either license.