Skip to main content

Dairo docs style guide

Read this before editing any page. It is the single source of truth for voice and for the one rule we never break: the docs explain how to USE Dairo, never how Dairo is built. Write like Stripe, Resend, and Linear: premium, warm, confident, never academic.

The two tests every page must pass

The tone test. A founder who just wants to send one email should finish your intro paragraph thinking “I can do this in two minutes” — not “I need to understand the response envelope and JWKS first.” The leakage test. A reader should never be able to tell what runs Dairo under the hood. If a competitor could screenshot your page to learn our stack, rewrite it.

Voice

Lead with the benefit. Open every page with ONE plain-English sentence about what the reader achieves. Then how.
  • Good: “Send your first email in two minutes.”
  • Good: “Give an inbox an extraction schema and incoming mail arrives as clean fields.”
  • Bad: “The /v1/messages noun is the one channel-agnostic surface that merges the old send-email, outbound-emails, and outbound-events paths.”
Use “you” and the active voice. Short sentences. Get to a runnable example within the first screen. Be scannable. Tight 1–2 sentence intro, then headings, then code. No wall-of-text paragraphs. Describe capabilities from the user’s side. “Dairo authenticates your mail and handles retries, bounces, and complaints for you” — not a description of the machinery that does it. Use concrete nouns the reader already knows (inbox, domain, reply, bounce, spam complaint) before any Dairo-specific term. One callout per risky thing. Untrusted attachments, complaint suppression, secret-shown-once — say it once, clearly, and link to it from elsewhere instead of repeating it.

Don’t

  • No “In this section, we shall describe…”, no “The X noun is the one surface that merges the old…”.
  • No changelog or migration prose in onboarding pages. Cut every “this replaces the old X”, “renamed from audiences”, “no longer borrows messages:read”, “that drift is gone”, “one source of truth in the backend”. If history matters, it lives in a changelog — never in a reference or onboarding page.
  • Don’t open a page with a scope sentence, an envelope shape, or an HTTP-status table. Lead with the outcome; push contract details lower or into Foundations.
  • Don’t dump all 24 scopes, every error code, or every field table above the first example. Show the happy path, then the reference.
  • No emoji. No exclamation-heavy hype. Confident, not loud.
  • Avoid stiff hedging and passive constructions. “A request that returns one resource returns…” becomes “When you fetch one thing, you get that thing back, with an object field naming its type.”

Absolute rule: never expose internals

The docs say what Dairo does, never how it is built. Never name, hint at, or imply any of these — in prose, field descriptions, example values, or asides:
Amazon SES · AWS · Lambda · S3 · SQS · Bedrock · Nemotron · Cloudflare · Supabase · Postgres · PostgREST · rustls · CloudWatch · VPC · IAM · “our backend” · “the backend” · “behind the scenes” · “under the hood” · which model, cloud, or framework powers anything.
When a page currently leaks the stack, rewrite it from the user’s side:

Example values must be provider-neutral

Opaque IDs only. Never leak a vendor through a sample value.
  • providerMessageId: use an opaque value like "msg_pm_9f8c2a1b4e7d" — never "0110…@amazonses.com".
  • Deletion/erasure tallies: use neutral field names like storedFiles — never s3Objects.
  • Regions: present as "EU" in user-facing copy where possible. A raw region code is acceptable only when it is a real value Dairo returns in that exact field (e.g. an audit-export manifest) — and even then, prefer the friendly framing.

Two things that legitimately stay

  • Real DNS values users must actually publish. A DKIM CNAME like abc123.dkim.amazonses.com is a real record the reader copies into their DNS — keep it, but verify it matches live output; never invent one.
  • Subprocessor disclosures. The published subprocessor register (e.g. the third-party names in Data residency) is a legally-required disclosure. Keep the names, but present them as a formal, versioned subprocessor list — not as a casual aside, and never alongside internal architecture (VPC, IAM, storage encryption, region wiring: all of that gets scrubbed).
A third-party tool named as the reader’s own option is fine (e.g. “store your key in your own secret manager — Vault, Doppler, AWS Secrets Manager”). That’s a suggestion for them, not a claim about our stack.

Code examples

  • Keep them correct and runnable against https://api.dairo.app. Improve them; never delete them.
  • Lead with curl or one SDK on intro pages — not all nine at once. Show the full language set on deep reference pages where it helps.
  • Show the happy path first. Put exhaustive field tables and edge cases below the first working example.

Some explanations live in exactly one canonical place. Reference them; don’t repeat them.
  • Metadata-first webhooks (events carry IDs and metadata; you fetch bodies on demand) → canonical home is Webhooks.
  • Untrusted inbound attachments → one shared callout, referenced from Attachments and Messages & threads.
  • Reply & threading → canonical home is Messages & threads.
  • The response envelope, scopes, errors, idempotency, pagination → Foundations.

Audience order

Normal developers first; AI-agent and advanced material is a clearly-labeled, optional layer later. The journey is: get a key → send → receive → verify a domain → deliverability. Keep that path unobstructed. Don’t make a first-time reader pass through provenance, JWKS, or the event ledger to send one email.