This guide governs the writing and formatting of pages on wiki.apolloautomation.com. It is the single source of truth for tone, language, and structural conventions. Contributors, maintainers, and AI tools (Claude, Copilot, Cursor, and others) all read from this file.
Who the wiki is for. Smart-home owners and tinkerers who want to know what an Apollo device does, how to set it up, and how to make it work inside their Home Assistant or Homey setup. They range from first-time Home Assistant users to ESPHome contributors. The docs need to land for both ends without patronizing the first or boring the second.
Why these rules exist. Without them, every contributor (human or AI) reinvents tone, terminology, and structure on every page. Readers feel the inconsistency even when they can't name it. The rules below are the result of decisions already made across the existing pages, codified so the next contributor doesn't have to make them again.
For workflow (how to fork, branch, preview, and open a PR), and for the file layout of the repo, see CONTRIBUTING.md.
A note for contributors: this guide gives prescriptive rules to keep the docs consistent. The "avoid" lists below apply to user-facing prose, not to this style guide or other internal documents. Telling a contributor "never use em dashes" is a rule, not a violation of the rule.
| Aim for | Avoid |
|---|---|
| Respectful | Patronizing |
| Confident | Boastful |
| Enthusiastic | Breathless |
| Direct | Corporate |
| Empowering | Instructional |
The "empowering, not instructional" line is the one most contributors trip over. Numbered steps are unavoidable in technical docs, but a wall of imperatives reads as bossy. Wrap procedures with framing copy that explains what the reader is about to unlock (see Numbered steps and framing below).
Use these phrases consistently. They are part of the Apollo voice.
- Build, learn, automate: the organizing framework
- Your home, your way: ownership and personalization
- On your own terms: independence and choice
- Real, working device: tangible outcome
- Just the beginning: opens up possibility without overpromising
- Local control: an HA-audience touchstone that signals values
- Open standards: credibility and trust
- Step by step: structured, guided
- ESPHome ecosystem: positions the kit within a bigger world
When using open standards or local control for the first time on a page, follow with the canonical plain-language explanation below. Readers new to the space need the translation, and using the same line across the wiki reinforces the message.
- Local control: your home runs on your own network. Your devices keep working even if your internet goes down or Apollo goes away.
- Open standards: Apollo builds on public protocols like ESPHome and OpenThread, so your kit is never locked to one vendor.
| Don't say | Why | Use instead |
|---|---|---|
| Beginner, basic | Patronizing | "Getting started", "First boot" |
| Easy on its own | Vague | Qualify: "easy if you already have X" |
| Simply, just | Dismissive | Drop the word entirely |
| Powerful | Cliché | Describe what it actually does |
| Seamlessly | Cliché | Describe the specific behavior |
| Genuinely, honestly | Undermines credibility | Drop the word entirely |
| "Coding without context" | Intimidating | Say what's actually required |
| Excessive "no" framing | Negative tone | Rephrase positively |
Write in US English spelling: color, center, meter, behavior, organize, toward. Quote an on-screen label exactly as the app shows it, and if the app itself uses a non-US spelling, flag it so the label can be fixed at the source.
Product IDs are always uppercase with a hyphen: AIR-1, MTR-1, MSR-2, BTN-1, PLT-1, TEMP-1, LED-1, M-1, PUMP-1.
Never Air-1, air1, or AIR1 in body copy. mkdocs.yml is the source
of truth for the canonical form.
R PRO-1 is the one exception: its name has a space after the R, not
a hyphen. Write R PRO-1 in titles, headings, nav labels, and body
copy, never R-PRO-1. The hyphenated and underscored forms survive
only where a space isn't allowed or where you quote the device
literally, and those must not be changed:
- File and folder names and URLs:
rpro1/,r-pro-1-zone-mapper-tool.md - Hostnames:
apollo-r-pro-1-w-xxxxxx.local - The firmware repo and installer:
ApolloAutomation/R_PRO-1 - The device name Home Assistant and Homey show: Apollo R_PRO-1
- The setup hotspot: Apollo R PRO 1 Hotspot
On the first mention of a product in body copy, use the full brand name: Apollo AIR-1. After that, the short form AIR-1 is fine for the rest of the page. Very short pages (a single intro paragraph, an FAQ entry) may use the short form throughout.
Two different things share the same word and they are not interchangeable:
- Apollo addons are physical hardware modules (the CO2 sensor for AIR-1, etc.). Write addon or addons, lowercase, no hyphen.
- Home Assistant apps are the software formerly called add-ons. Home Assistant renamed them to apps in 2025. Write app or App Store.
A page about installing the CO2 hardware addon AND configuring it via a Home Assistant app will use both terms. Each is correct in its own context.
The forms add-on, Add-on, and Addon should not appear in
user-facing copy unless quoting upstream documentation.
Always capitalized exactly ESPHome. Never esphome, ESPhome,
Esphome, or ESPHOME. This matches the upstream project's own brand.
When introducing the broader project, prefer ESPHome ecosystem over "the ESPHome project" or "ESPHome firmware".
Flash is the preferred verb for putting firmware on a device:
Flash your AIR-1 with the latest firmware.
Install firmware is acceptable when "flash" would be confusing context (for example, when the audience may not recognize the term). Avoid burn and load.
Link firmware installs to the product's own page on the Apollo
installer, https://install.apolloautomation.com/#/<product> (for
example #/air-1 or #/r-pro-1), not the older
apolloautomation.github.io/<PRODUCT>/ installers. Name buttons the way
the installer shows them: the variant (USB Power, Battery Power,
WiFi, Ethernet, Smart (Wi-Fi), Basic (No Wi-Fi)) and
then Connect & Install, and the firmware option in the next dialog
exactly as listed (for example Install ApolloAutomation.AIR-1). The
B models use their parent's page with Battery Power (TEMP-1B on
#/temp-1, PLT-1B on #/plt-1). Keep the older installer link only
where the Apollo installer has no equivalent: TEMP-1 Revision 1
firmware. The LED-1 uses the official WLED installer at
https://install.wled.me/.
Boot mode with two buttons. When a step uses both the boot and reset
buttons, write the order as three bullets (press and hold boot; while
still holding it, press and release reset; let go of boot), then a
warning admonition titled "Keep holding boot the whole time" that says
pressing reset alone only restarts the device. Put both before the
photo or clip. Clips of the sequence carry step captions ("1 Press and hold
BOOT", "2 Keep holding BOOT. Tap RESET.", "3 Let go of BOOT") so a reader
who only watches still holds boot. A customer once watched an uncaptioned
clip, saw a finger resting on the board, and pressed reset alone.
Default to second person addressed to the reader, with imperative verbs in action copy.
Click Save. Plug in your AIR-1. Open the ESPHome Device Builder app from your sidebar.
Avoid:
- First person plural: "we'll now configure..."
- Hedging modal: "you should click..."
- Passive: "the device is plugged in..."
Every page has exactly one H1, written as the first line of the body
(# Adding the button module). mkdocs-material renders this as the
page heading. The front matter title: is used by the nav, browser
tab, and search snippets, and should match the H1.
All headings use sentence case. The first word is capitalized, and proper nouns are capitalized. Everything else is lowercase.
| Yes | No |
|---|---|
| Connecting through hotspot | Connecting Through Hotspot |
| Your first automation | Your First Automation |
| Getting started with AIR-1 | Getting Started With Air-1 |
mkdocs-material integrates each page's TOC into the left sidebar, and
toc_depth is set to 3 in mkdocs.yml. That means only H2 and H3
headings appear in the sidebar. Plan your headings with that in mind:
- H1: the page title, written as the first line of the body and
mirrored in the front matter
title:. Exactly one per page. - H2: major sections. Each H2 becomes a sidebar entry, so use them for things a reader might jump to ("Connecting through hotspot", "Troubleshooting").
- H3: subsections that still deserve a sidebar entry. Use sparingly. A page with a dozen H3s under one H2 floods the sidebar.
- H4 and below: in-page detail only. They render in the body but stay out of the sidebar.
If you find yourself wanting an H4 to show up in the sidebar, the right move is usually to promote it to H3, or split the page.
Any sequence of three or more actions becomes a numbered list. Each step starts with an imperative verb.
1. Plug your AIR-1 into power. The LED turns blue.
2. Open the **Home Assistant** app on your phone.
3. Tap **Settings → Devices & services → Add integration**.Sub-steps nest as bullets under the parent number. Do not use "Step 1:", "Step 2:" headings.
Frame the steps. A bare list of imperatives reads as instructional. Lead with a sentence or two on what the reader is about to unlock, and follow with a quick success check.
Adding your AIR-1 to Home Assistant
Once your sensor is on Wi-Fi, Home Assistant will discover it automatically. This is where your AIR-1 becomes a real, working device in your dashboard.
- ...
- ...
- ...
Your AIR-1 now shows up under Settings → Devices. From here, every reading the sensor takes flows into Home Assistant in real time.
Banned softeners inside steps: simply, just, easy. These either patronize the reader or pad the sentence.
Every page has YAML front matter with at minimum a title and a
description:
---
title: Adding a CO2 addon to your AIR-1
description: Step-by-step guide to installing the CO2 sensor module and seeing readings in Home Assistant.
---titleshows in the browser tab, the nav, and the H1.descriptionis used by mkdocs for search snippets and social card previews. Skipping it hurts both.
Buttons, menu items, tabs, and other on-screen labels are formatted in
bold. Multi-step navigation uses the Unicode right arrow →.
Open Settings → Devices & services → Add integration and search for Apollo.
Do not use backticks, quotes, or italics for UI elements.
Anything the reader types literally or sees in a code-shaped context goes in backticks. This includes:
- Entity IDs:
sensor.air1_co2 - YAML keys and paths:
wifi.ssid,esphome.name - File paths:
/config/configuration.yaml - Shell commands:
esphome run - Config values:
power_save_mode: none
The distinction matters: bold means a thing on the screen,
backticks means a literal string.
Every fenced code block must declare a language for syntax highlighting:
```yaml
wifi:
ssid: !secret wifi_ssid
```When the snippet belongs to a specific file, add a title:
```yaml title="configuration.yaml"
homeassistant:
name: My Home
```- Stored under
docs/assets/. - Filenames in kebab-case:
air1-boot-button.jpg. - Every image has descriptive alt text. Alt text describes what the image shows, not what the file is called. Screen readers and broken images both depend on it.
- Keep source images under 750px wide where possible. CI auto-resizes, but smaller sources render faster.
My Home Assistant buttons are the official badges from my.home-assistant.io. Each one opens a screen in the reader's own Home Assistant, whatever address they reach it on, so "go to Settings → Devices & services → ESPHome" becomes one click. Add one wherever a step sends the reader to a Home Assistant screen:
- Installing or adding something: a HACS repository
(
hacs_repository), an integration's setup dialog (config_flow_start), a Home Assistant app (supervisor_app), an app from another repository (supervisor_appwithrepository_url, which offers to add the repository), or a blueprint (blueprint_import). - Opening the screen a step works in: an integration's page
(
integration), a Settings page (integrations,automations,helpers,lovelace_dashboards,logs, and so on), or Settings → Tools (tools_actions,tools_states,tools_perform_action). Home Assistant 2026.8 moved these from Developer tools, and the same buttons open them in older versions. - Restarting Home Assistant:
system_dashboardopens Settings → System, where the power icon is.
Put the button on its own line right after the step it helps, as its own paragraph:
1. Go to **Settings → Devices & services** and click **Add integration**.
[](https://my.home-assistant.io/redirect/config_flow_start/?domain=esphome)
2. Search for **ESPHome** and select it.- Indent it with the step. Inside a numbered or bulleted list,
indent the button 4 spaces so it stays inside the step and the
numbering continues. Inside an admonition or a content tab, add 4
more. Steps written as
1\.are plain paragraphs, so their buttons start at the left margin. - One button for several steps. When one button replaces several steps, put it under the first of them and say which steps it covers, for example "The button under step 1 covers steps 1 to 5."
- Alt text is "Open your Home Assistant instance and" followed by the redirect's description from the redirect list and a period, as in the example above.
- Use current redirect names:
supervisor_appwithapp=, notsupervisor_addonwithaddon=, andtools_actions, notdeveloper_services. Current names work on every Home Assistant version. Build links with the My Home Assistant link creator, URL-encode parameter values, and skip hidden redirects such assupervisor_ingress. Confirm the redirect is also in the Home Assistant frontend's list (src/panels/my/ha-panel-my.tsin the frontend repository), because a few names in the redirect list are missing there, such asactivity. - Check every parameter: the integration domain from its
manifest.json, the HACS owner and repository (categorypluginfor a dashboard card), the app slug from itsconfig.yamlwith the repository prefix (ESPHome Device Builder is5c53de3b_esphome), and a blueprint URL that serves the raw YAML. - Keep the written path in the step. The button is a shortcut, and some readers reach Home Assistant through an address My Home Assistant doesn't know.
- One button per destination per section. Don't turn every mention of Settings into a button; add one where a step sends the reader there.
- Home Assistant only. No buttons for Homey, phone apps, a device's
own web page, or a screen the reader is already on. Snippets and
included pages carry their buttons to every page that includes them,
so check the includers with
git grep -- '--8<--'first. Content that a Homey page includes gets no Home Assistant buttons. - No
homeassistant.local:8123links. They only work for readers on that address. Use the button and the written path instead.
Use short MP4 clips instead of GIFs. A looping MP4 is a fraction of the size of the same GIF and stays sharper, so pages load faster. CI only shrinks PNGs, so compress video before committing it.
- Short loops (a few seconds to about 30) that show one step sit
right after that step and play on their own, silently:
autoplay loop muted playsinline. - A full walkthrough goes in its own Video walkthrough section
with
controlsand aposterimage, and does not autoplay. Long or narrated videos belong on YouTube, embedded with thecms-embedmarkup. - Phone recordings (portrait) take
class="phone-media", which caps them at phone width and centers them. The class lives indocs/stylesheets/extra.css; never size media inline. - Trim personal details and secrets (names, email addresses, home
names, notifications, Wi-Fi passwords, API keys) out of every recording
and screenshot before it's published. Compile and install logs print
the device's full configuration, so end a recording before the log
scrolls through it, and check YAML editor shots for an
api: encryption: key:value. - Strip location data from photos. Phones save the GPS location in
every photo. Remove it before committing:
exiftool -gps:all= -overwrite_original docs/assets/<file>. The PR checks fail on any photo that still has it. - Compress with H.264, no audio track, and fast start, scaled to 540px wide for clips and 720px for a full phone walkthrough. Aim for under 1 MB per clip and a few MB for a walkthrough:
ffmpeg -ss 3 -to 26 -i recording.mp4 -an -vf "scale=540:-2,fps=30" -c:v libx264 -preset slow -crf 23 -pix_fmt yuv420p -movflags +faststart docs/assets/product-step-name.mp4<video class="phone-media" src="/assets/homey-radar-regions-add-widget.mp4" autoplay loop muted playsinline></video>Readers skim. Put anything they must not miss in an admonition instead of burying it in a paragraph, and pick the type by what the box does:
| Type | Use it for | Example title |
|---|---|---|
note |
Prerequisites at the top of a guide | "Before you start" |
tip |
A shortcut, or why something works the way it does | "Why taps instead of drags" |
warning |
Something that breaks a setup or loses data if ignored | "Install both parts" |
danger |
Risk of damaging hardware | "Unplug before opening" |
success |
The next step once the reader has finished this one | "Next step: build your first region flow" |
Keep each box to one idea and a few sentences. A page where every paragraph is a box has no emphasis left; if a section has more than two or three, fold the minor ones back into the text.
Link guides into a progression. When one guide naturally leads to
another (draw a zone, then build a flow with it), close the relevant
section with a success box: one sentence on what the reader unlocks
next, then a primary button to the follow-on guide. The follow-on guide
links back from its "Before you start" note.
!!! success "Next step: build your first region flow"
Your regions are drawn. Now make one do something: the step-by-step
guide walks you through a flow that turns a light on when someone
enters a region.
[Turn on a light when someone enters a region](../../../general/tutorials/region-light-flow-example/){ .md-button .md-button--primary }Internal links use site-relative paths in wiki-URL form (trailing
slash, no .md extension), not absolute
https://wiki.apolloautomation.com/... URLs:
See [getting started](../setup/getting-started/) for first-boot setup.Relative links work in PR previews and survive a future domain change. Links to external sites (home-assistant.io, esphome.io) stay absolute.
Always use the Oxford comma in lists of three or more items.
AIR-1 supports Wi-Fi, MQTT, and Bluetooth.
Do not use em dashes (—) anywhere in user-facing copy. Replace with
commas, periods, parentheses, or "X to Y" for ranges.
| Don't write | Write instead |
|---|---|
The AIR-1 — once flashed — connects automatically. |
The AIR-1, once flashed, connects automatically. |
Three sensors — CO2, VOC, and PM2.5 — ship in the kit. |
Three sensors (CO2, VOC, and PM2.5) ship in the kit. |
Run the test for 5 — 10 minutes. |
Run the test for 5 to 10 minutes. |
List items that are complete sentences end with a period. Fragments do not.
Features:
- Real-time CO2 readings
- Onboard temperature compensation
- USB-C power
Setup steps:
- Plug in the device.
- Wait for the LED to turn green.
- Open the companion app.All markdown filenames are kebab-case: adding-co2-to-air-1.md. No
camelCase, no snake_case, no spaces, no capital letters.
Pages live under per-product subdirectories, mirrored across platform trees:
docs/
├── products/ Home Assistant tree
│ └── air1/
│ ├── setup/
│ ├── addons/
│ └── troubleshooting/
└── homey/products/ Homey tree
└── air1/
├── setup/
├── addons/
└── troubleshooting/
When a topic exists on both Home Assistant and Homey, use the same filename in both trees. This makes cross-platform consistency obvious to anyone editing the docs.
When you edit a page in one tree, check the mirror in the other tree and update it too if the change applies. Cross-tree drift, where the HA version of a page describes the current product behavior and the Homey version still describes how it worked a year ago, is the biggest source of stale content on the wiki. If a change is platform-specific and genuinely doesn't apply to the other tree, leave a one-line note in the PR description explaining why so reviewers don't flag it.
For the full repo layout (where mkdocs.yml lives, where redirects go,
how docs/assets/ is organized), see
CONTRIBUTING.md.
Every automation page carries a difficulty pill directly under the H1 so readers can gauge how involved the setup is. The rating is about setup difficulty and skill (steps, helpers, templating, integrations), not runtime load.
| Level | Use it when the automation... |
|---|---|
| 1 | is plug-and-play, or needs only a helper or two and a few guided steps. |
| 2 | combines several entities, conditions, or a template. |
| 3 | needs templating, blueprints, multi-device logic, or is heavily custom. |
Add the pill as the first line under the title. The lvl-N class sets the
color (green at 1, amber at 2, red at 3):
# Build a Button-Controlled RGB Light
<span class="difficulty lvl-1">Difficulty: Level 1</span>On a harder page, point newcomers at one to three easier automations from the same product. Add it under the pill at your discretion (Level 2 and up is a good rule of thumb). Use relative links so previews work:
<p class="automation-steps-heading">🌱 New here? Try these first:</p>
<div class="automation-steps">
<div class="step">
<a class="step-title" href="../motion-activated-light/">Turn On a Light with Motion</a>
<span class="difficulty lvl-1">Difficulty: Level 1</span>
</div>
<div class="step">
<a class="step-title" href="../button-controlled-leds/">Build a Button-Controlled RGB Light</a>
<span class="difficulty lvl-1">Difficulty: Level 1</span>
</div>
</div>The pill and box styles live in docs/stylesheets/extra.css; never inline
colors on the page.
Every page under the ESPHome Starter Kit product carries the same community call-to-action at the bottom: a friendly note admonition titled "New to ESPHome? We're here to help." with links to Discord and the Community Forum. The copy and buttons live in a single snippet so the CTA stays consistent across the product and only needs one edit to update.
Source of truth: docs/_snippets/community-help.md
Where to include it: at the very bottom of any starter-kit page (after any existing "Try it in an automation" buttons, "Next Steps" buttons, or closing success admonition). One blank line of separation from the content above is enough.
How to include it:
--8<-- "_snippets/community-help.md"When you add a new starter-kit page, end it with this include before opening the PR. When you edit the CTA copy (adding a new channel, rewording the prompt, swapping button labels), edit the snippet file itself, never the include line on a page.
The snippet uses the standard note admonition flavor for visual
consistency with the kit's other admonitions ("Before you start", tips,
warnings); don't swap it for tip or info on a per-page basis.
If a rule above conflicts with clarity for the reader, clarity wins. Open an issue or PR proposing the rule change so the guide stays honest.