Authoring documentation
How to add a resource, an example, or a guide to this site — and the one rule that keeps the pages consistent.
The rule #
Structure is data. Narrative is content.
A resource’s machine-readable schema lives in data/schemas/. Its prose lives in
content/resources/. The schema drives the explorer, the property reference, the
return values, the generated templates, the IAM policy, the search index and the
cross-reference graph — from one source, so they cannot disagree.
Prose adds only what a schema cannot: why the resource exists, what it is commonly paired with, and what will bite you.
If you find yourself writing a property’s type or requiredness in prose, it belongs in the schema instead.
Adding a resource #
Two files.
1. The schema #
data/schemas/<provider>/<service>/<name>.yaml. The directory layout is free —
the only rule is that a schema document is any map carrying a typeName key.
typeName: Updraft::Example::Thing
provider: updraft # aws | updraft — drives the catalogue facets
providerTitle: Updraft Extensions
service: Example
serviceTitle: Updraft Example
category: Configuration
status: stable # stable | preview | deprecated
identifier: ThingId
tagProperty: Tags # omit if the type is not taggable
summary: >-
One sentence. Appears in the hero, the catalogue card, and the search index.
related:
- AWS::S3::Bucket # resolved by type name, not by path
properties:
Name:
type: string # string integer number boolean object array map json
required: true # true | false | conditional
order: 1 # tie-break within the requiredness band
updates: none # none | some | replacement | na
createOnly: true # adds the lock icon
summary: One line, shown on the collapsed row.
description: |
Markdown. Shown when the row is expanded.
constraints:
minLength: 1
maxLength: 64
pattern: '^[a-z-]+$'
patternNote: Explain the pattern in words. Regexes are not documentation.
enum: [A, B]
default: A
examples: ["a-real-looking-value"]
notes:
- kind: gotcha # note tip important warning caution gotcha remarks
title: Optional heading
text: |
Markdown.
definitions:
NestedType:
title: NestedType
summary: One line.
properties: {} # same shape as above, recursively
attributes:
Arn:
type: string
summary: What it is.
example: "arn:aws:…"
ref:
short: Thing ID # shown in the fact strip
returns: |
Markdown, shown in the return-values section.
example: thing-2f8a1c94
permissions:
create: [service:Action]
read: [] # an explicit empty list means "no calls", and
update: [] # renders differently from an absent key
delete: []
Referencing a nested type uses ref: against a key in definitions:
Source:
type: object
ref: S3Location # a plain object
Rules:
type: array
items:
ref: LifecycleRule # an array of them
Labels:
type: map
values:
type: string # a map of scalars
Recursive definitions are safe — the renderer tracks which definitions are open on the current path and renders a link back instead of looping.
2. The page #
content/resources/<provider>/<service>/<name>/_index.md. It must be _index.md
(a branch bundle) so that examples can live underneath it.
---
title: Updraft::Example::Thing # the full type name
linkTitle: Thing # short form, for the nav tree
type: resource # selects the resource layout
schema: Updraft::Example::Thing # links the page to its schema
weight: 10
---
Everything after the front matter is the narrative slot, rendered between the
minimal template and the property explorer. Write an ## Overview, then
whatever remarks and worked snippets belong there.
Adding an example #
A markdown file beside the resource’s _index.md:
---
title: A sentence describing the scenario
linkTitle: Short form for the nav
type: example
weight: 10
level: Intermediate # Beginner | Intermediate | Advanced
time: 15 min
diagram: true
uses: # type names; rendered as links where documented
- AWS::S3::Bucket
lede: >-
Two sentences on what this shows and why it is not the obvious approach.
---
An example earns its own page when it has a diagram, more than one resource, or something to say about failure modes and teardown. Anything smaller belongs inline on the resource page.
The shortcode vocabulary #
Callouts #
{{< note >}} … {{< /note >}}
{{< tip >}} {{< important >}} {{< warning >}} {{< caution >}}
{{< gotcha title="Optional heading" >}} … {{< /gotcha >}}
{{< remarks >}} … {{< /remarks >}}
See documentation conventions
for when
each is appropriate. gotcha is the valuable one — reserve it.
Code tabs #
{{< tabs group="lang" default="yaml" >}}
{{< tab label="YAML" key="yaml" >}}
```yaml
…
{{< /tab >}} {{< tab label=“CDK (TypeScript)” key=“cdk-ts” >}} … {{< /tab >}} {{< /tabs >}}
Use the standard keys — `yaml`, `json`, `cdk-ts`, `cdk-py` — so a reader's choice
follows them across every tab set on the site and across visits.
### Input and result
```text
{{< io split="true" inLabel="Template" outLabel="Result" >}}
{{< io-in >}} … {{< /io-in >}}
{{< io-out >}} … {{< /io-out >}}
{{< /io >}}
And the one-liner, for showing what an expression resolves to:
{{< resolves in="!Ref AppConfig" out="doc-2f8a1c94" note="a handle" >}}
Cross-references #
{{< type "AWS::S3::Bucket" >}} links to the resource page
{{< prop "BucketEncryption" >}} links to a property on this page
{{< prop "BucketEncryption.ServerSideEncryptionConfiguration" >}}
Diagrams #
Diagrams are hand-authored inline SVG using the dg-* class vocabulary. They
are theme-aware, selectable, searchable, and need no renderer.
{{< diagram caption="What the reader should take away." alt="Description for screen readers." >}}
<svg class="dg" viewBox="0 0 760 200" role="img">
<rect class="dg-node dg-node--accent" x="12" y="40" width="120" height="52" rx="6"/>
<text class="dg-title" x="72" y="64" text-anchor="middle">Client</text>
<text class="dg-sub" x="72" y="80" text-anchor="middle">https://</text>
<path class="dg-edge dg-edge--accent" d="M136 66 H200"/>
</svg>
{{< /diagram >}}
The vocabulary:
| Class | Use |
|---|---|
dg-node | A box. --alt for a secondary fill, --accent for emphasis, --ghost for something outside the system. |
dg-zone | A dashed boundary — a VPC, an account, a trust boundary. --solid for a hard one. |
dg-edge | A line with an arrowhead. --accent, --dashed, --plain (no head). |
dg-title / dg-sub / dg-label | Text at three weights. dg-sub is monospaced, for identifiers. |
dg-zonelabel | Small caps label for a zone. |
dg-step / dg-stepnum | A numbered circle, for ordered flows. |
Checking your work #
make serve # live reload at http://localhost:1313
make build # production build, fails on a broken reference
make check # link and markup checks
The build fails — it does not warn — when a page names a schema that does not
exist, when a property references an undefined nested type, or when a tabs
block has no children. A resource page that renders blank is worse than one that
does not render at all.