Structure and formatting skill

7.

by wondelai·MIT license·★ 2,235 Stars on the repo·GitHub ↗

Use now

Files of Structure and formatting

wondelai/main1 file
structure-and-formatting.md
Show the full text331 lines

Structure and Formatting

  1. Headings (S1, S2, S3)
  2. Lists (S4, S5)
  3. Tables (S6)
  4. Notices (S7)
  5. Cross-references (S8)
  6. Link text (S9)
  7. Images and alt text (S10)
  8. Numbers, dates, and units (S11)
  9. Text formatting summary (S12)
  10. Worked example

This file deepens Framework section 4 (Structure: Headings, Lists, Tables, Notices) with the full rule text, more before/after pairs, and the numbers, dates, and text-formatting rules that section only summarizes. It owns S1–S12. Code-font specifics, placeholders, and UI-element bold live in procedures-and-code.md (P6, P8, P5); paragraph rules live in document-types.md (R6).

Headings (S1, S2, S3)

Headings are the reader's table of contents before they read a word of body text — a reader scans the heading list, finds their task, and jumps there. A heading that doesn't say what the section does, or that breaks case or level conventions, breaks the scan.

S1 — Sentence case

Capitalize the first word and proper nouns only; leave common nouns lowercase even when a UI element shows them capitalized. Proper nouns, product and brand names, and code stay exactly as written: Google Cloud, Cascade, README.md.

  • "Configuring The Database Connection" → "Configure the database connection"
  • "API Reference For The Webhooks Endpoint" → "API reference for the Webhooks endpoint"
S2 — Task headings vs. concept headings

A task heading is a bare imperative — the verb the reader performs: "Create a webhook". A concept heading is a noun phrase — the thing the reader is learning about: "Webhook lifecycle". Neither ever ends in "-ing"; an "-ing" heading hides which of the two it is.

  • "Creating a Webhook" (task, disguised as a gerund) → "Create a webhook"
  • "Troubleshooting Deploy Failures" (task) → "Troubleshoot deploy failures"
  • "Webhook Payload Format" (concept, wrong case) → "Webhook payload format"
S3 — Levels, endings, and adjacency

Don't skip heading levels (H2 straight to H4 with no H3 in between) — screen readers announce level jumps as broken structure. Headings never end with a period. And (inferred) avoid a heading immediately followed by another heading with no body text between them — a reader lands on the child heading with no idea what the parent section covers.

Full outline, before:

# Cascade CLI Reference.

### Installing Cascade
#### Prerequisites
##### Supported platforms
### Deploying An App
### Troubleshooting Common Errors

Problems: trailing period on the title; the outline jumps from H1 to H3 (no H2); "Prerequisites" is immediately followed by "Supported platforms" with nothing said in between; every heading is "-ing" and title case.

After:

# Cascade CLI reference

## Install Cascade

### Prerequisites

Before you install Cascade, confirm you have Node.js 18 or later.

### Supported platforms

## Deploy an app

## Troubleshoot common errors

Source: headings

Lists (S4, S5)

S4 — Intro sentences and parallelism

Every list needs an intro sentence that is grammatically complete on its own, ending in a colon. A sentence that only works once you mentally append the first bullet — "Use the --format flag to:" — breaks the moment an item doesn't start with a verb. Every item in a list takes the same grammatical form as the others: all imperatives, all nouns, all noun phrases.

Before (fragment intro, mixed forms):

Use the --format flag to:
- Print JSON
- Print YAML
- Print a table

After (complete intro, parallel nouns):

The --format flag supports the following output types:
- JSON
- YAML
- Table

Before (non-parallel steps):

Before you deploy, complete these steps:
- Installing the CLI
- You need an API key
- Configure the project

After:

Before you deploy, complete these steps:
- Install the CLI
- Get an API key
- Configure the project
S5 — Numbered vs. bulleted vs. description lists

Number a list only when order matters — the reader must do item 1 before item 2. Everything else is bulleted, including options, flags, and requirements that stand independently of each other.

Before (numbered, but the items aren't a sequence):

1. Enable verbose logging
2. Enable colorized output
3. Enable strict mode

After:

- Enable verbose logging
- Enable colorized output
- Enable strict mode

For term-and-definition pairs, a description list beats a two-column table — the term reads as a heading, not a table cell, and there's no header row to skip. Markdown has no universal native syntax for this, but the widely supported Markdown Extra / Pandoc form is:

`--dry-run`
:   Previews changes without applying them.

`--verbose`
:   Prints each step as it runs.

Punctuation [EN] (inferred): capitalize the first word of every item regardless of form. A complete sentence ends with a period; a fragment doesn't.

  • Fragment, no period: "- Verbose output"
  • Complete sentence, period: "- Verbose output is enabled by default."

Source: lists

Tables (S6)

A table needs a header row and an intro sentence that states what it lists — "The following table lists the cascade deploy flags:" — so a reader (and a screen reader) knows what they're about to scan before they hit the grid. Never merge cells and never leave one empty: an empty cell reads to assistive tech as if nothing is there at all, not as "not applicable". Write "None" or "Not applicable" instead (convention). Keep cell phrasing parallel down a column — if one description is a sentence, they all are.

Reach for a bulleted or description list instead of a table when there's only one dimension of comparison (a plain list of flags with no second attribute) or when most cells would carry long prose — tables earn their header row only when the data is genuinely tabular across two or more attributes.

Before:

| Flag | |
|------|--|
| --verbose | |
| --dry-run | Preview changes |

After:

The following table lists the `cascade deploy` flags:

| Flag | Description |
|------|-------------|
| `--verbose` | Prints each step as it runs. |
| `--dry-run` | Previews changes without applying them. |

Source: tables, accessibility

Notices (S7)

A notice interrupts the reader's flow, so it earns that interruption only when the information changes what they do next.

  • Note — useful, optional information the reader can act on or skip: "Cascade caches build artifacts in .cascade/cache. Delete this directory to force a clean build."
  • Caution — proceed carefully; the mistake is recoverable but costly: "Changing the region after deployment migrates your database and can take up to 30 minutes."
  • Warning — serious harm or irreversible loss: "Running cascade reset --hard permanently deletes all environments and can't be undone."

Don't stack them. (Inferred) one notice per section is a practical ceiling — three boxes in a row train the reader to skip all three, including the one that matters.

Fold a notice into body text whenever it doesn't change the reader's next action — a plain sentence in the paragraph carries the same information without the visual interruption.

Before:

Run `cascade deploy` to publish your app.

> **Note:** This command requires an active internet connection.

After:

Run `cascade deploy` to publish your app. This command requires an internet connection.

Source: notices

Cross-references (S8)

Point to other content with "see", never "refer to" or "check out". Never say "above" or "below" — pages reflow, get translated into languages that reorder content, and get read out of order by screen readers and search results. Use "the following" for what comes immediately after in the same page, "the preceding" for what came immediately before, and a named link for anything farther away.

Link when the referenced material lives on another page, or is optional depth the current task doesn't require. Inline the fact instead — repeat the one sentence the reader needs — when sending them away would interrupt a procedure they're mid-way through.

  • "For more info, check out the docs above." → "For more information, see Configure authentication."
  • "As mentioned below, you'll need an API key." → "You need an API key; see Get an API key."
  • "Refer to the table above for exit codes." → "See the preceding table for exit codes."

Source: cross-references

Link text should read as the destination's title, or a close description of it, so it makes sense pulled out of the sentence — many screen readers list a page's links with no surrounding text at all. Never link "click here", "this link", or a bare pasted URL. Put the link on the words that name the target, not on a filler verb.

Source: link-text, accessibility

Images and alt text (S10)

Alt text states what the image communicates in this context, not what it literally shows — skip "Image of" and "Screenshot of"; the screen reader already announces that it's an image. Keep it to one concise phrase or sentence, not a full transcription of every pixel.

Information must never live only in an image: if a diagram is the sole place a required value, flag, or step appears, the doc is broken for anyone who can't see it and for anyone who needs to copy that value. This is a shippability gate (Blocking) — put the same fact in the surrounding text.

Use a screenshot to show where something sits in a UI or to confirm a visual result — a filled-in form, a chart the reader compares theirs against. Use text or a code block for anything the reader types, copies, or runs: text is copyable, searchable, and translates; a screenshot of a command is none of those. Write the caption first — naming the figure's one idea before you draw or crop it keeps the image on message (tech-writing/two) — and never let the caption alone carry a detail that's missing from the alt text.

Before:

![Screenshot of the dashboard](dashboard.png)

Click the button to deploy.

After:

![The Deploy button in the top-right corner of the Cascade dashboard, next to the environment selector](dashboard.png)

Click **Deploy** in the top-right corner of the dashboard.

Source: images, accessibility

Numbers, dates, and units (S11) [EN]

Spell out zero through nine; use numerals for 10 and up. Always use numerals with units, versions, and measurements, no matter how small the number: "3 MB", "version 2 of the API", "5 retries". Dates must be unambiguous — "2026-08-29" or "August 29, 2026" — never "08/29/26" or "29/08/26", which read as different dates depending on the reader's locale. Include a time zone whenever a time matters across regions: "2:00 PM UTC", not "2:00 PM". Units get a space and the standard symbol, never a spelled-out or invented abbreviation: "10 MB", not "10MB" or "10 megs". The time-zone and unit-spacing forms are inferred — the sourced pages cover number and date formats.

  • "The free tier includes 3 projects and up to 100mb of storage." → "The free tier includes three projects and up to 100 MB of storage."
  • "The migration finished on 08/09/26 at 2pm." → "The migration finished on 2026-08-09 at 2:00 PM UTC."
  • "This feature requires SDK version two." → "This feature requires SDK version 2."

Source: numbers, dates-times

Text formatting summary (S12)

Format Use for Example
Bold UI element names, matching on-screen casing (P5) Click Deploy.
Code font Commands, flags, filenames, code, values (P6) Run cascade deploy --dry-run.
Italics A new term on its first use; emphasis, used sparingly A webhook is an HTTP callback that Cascade sends when an event occurs.

Don't format product names — plain text, matching the vendor's own capitalization (P6). See procedures-and-code.md for the full code-font, placeholder, and UI-element rules behind P5 and P6.

Source: text-formatting

Worked example

Before — headings break case and nest wrong, the list has a fragment intro and non-parallel items, the table has no intro sentence and empty cells, and two notices stack back to back:

# Configuring Webhooks.

## Setting Up

To set up webhooks you can:
- signing secret
- Choose a delivery URL
- pick which events to send

## The Payload

Below is a table of fields you might get back:

| Field | |
|-------|--|
| event | |
| id | The event's ID |

Note: Webhook retries happen automatically.
Caution: If your endpoint returns a non-2xx status the delivery is marked failed and won't retry.

After — sentence-case imperative headings, one parallel bulleted list with a complete intro, a table with a header row and no empty cells, the routine fact folded into body text, and a single notice:

# Configure webhooks

## Set up a webhook

To set up a webhook, complete these steps:

- Generate a signing secret.
- Choose a delivery URL.
- Select which events to send.

## Webhook payload fields

The following table lists the fields in every webhook payload:

| Field | Description |
|-------|-------------|
| `event` | The event type, for example `payment.succeeded`. |
| `id` | The event's unique ID. |

Cascade retries a failed delivery up to five times before it gives up.

**Caution:** Changing the delivery URL cancels any retries already queued for the old URL.
1# Structure and Formatting
2 
31. [Headings (S1, S2, S3)](#headings-s1-s2-s3)
42. [Lists (S4, S5)](#lists-s4-s5)
53. [Tables (S6)](#tables-s6)
64. [Notices (S7)](#notices-s7)
75. [Cross-references (S8)](#cross-references-s8)
86. [Link text (S9)](#link-text-s9)
97. [Images and alt text (S10)](#images-and-alt-text-s10)
108. [Numbers, dates, and units (S11)](#numbers-dates-and-units-s11-en)
119. [Text formatting summary (S12)](#text-formatting-summary-s12)
1210. [Worked example](#worked-example)
13 
14This file deepens Framework section 4 (Structure: Headings, Lists, Tables, Notices) with the full rule text, more before/after pairs, and the numbers, dates, and text-formatting rules that section only summarizes. It owns **S1–S12**. Code-font specifics, placeholders, and UI-element bold live in `procedures-and-code.md` (P6, P8, P5); paragraph rules live in `document-types.md` (R6).
15 
16## Headings (S1, S2, S3)
17 
18Headings are the reader's table of contents before they read a word of body text — a reader scans the heading list, finds their task, and jumps there. A heading that doesn't say what the section does, or that breaks case or level conventions, breaks the scan.
19 
20### S1 — Sentence case
21 
22Capitalize the first word and proper nouns only; leave common nouns lowercase even when a UI element shows them capitalized. Proper nouns, product and brand names, and code stay exactly as written: Google Cloud, Cascade, `README.md`.
23 
24- "Configuring The Database Connection" → "Configure the database connection"
25- "API Reference For The Webhooks Endpoint" → "API reference for the Webhooks endpoint"
26 
27### S2 — Task headings vs. concept headings
28 
29A task heading is a bare imperative — the verb the reader performs: "Create a webhook". A concept heading is a noun phrase — the thing the reader is learning about: "Webhook lifecycle". Neither ever ends in "-ing"; an "-ing" heading hides which of the two it is.
30 
31- "Creating a Webhook" (task, disguised as a gerund) → "Create a webhook"
32- "Troubleshooting Deploy Failures" (task) → "Troubleshoot deploy failures"
33- "Webhook Payload Format" (concept, wrong case) → "Webhook payload format"
34 
35### S3 — Levels, endings, and adjacency
36 
37Don't skip heading levels (H2 straight to H4 with no H3 in between) — screen readers announce level jumps as broken structure. Headings never end with a period. And (inferred) avoid a heading immediately followed by another heading with no body text between them — a reader lands on the child heading with no idea what the parent section covers.
38 
39**Full outline, before:**
40 
41```markdown
42# Cascade CLI Reference.
43 
44### Installing Cascade
45#### Prerequisites
46##### Supported platforms
47### Deploying An App
48### Troubleshooting Common Errors
49```
50 
51Problems: trailing period on the title; the outline jumps from H1 to H3 (no H2); "Prerequisites" is immediately followed by "Supported platforms" with nothing said in between; every heading is "-ing" and title case.
52 
53**After:**
54 
55```markdown
56# Cascade CLI reference
57 
58## Install Cascade
59 
60### Prerequisites
61 
62Before you install Cascade, confirm you have Node.js 18 or later.
63 
64### Supported platforms
65 
66## Deploy an app
67 
68## Troubleshoot common errors
69```
70 
71Source: headings
72 
73## Lists (S4, S5)
74 
75### S4 — Intro sentences and parallelism
76 
77Every list needs an intro sentence that is grammatically complete on its own, ending in a colon. A sentence that only works once you mentally append the first bullet — "Use the `--format` flag to:" — breaks the moment an item doesn't start with a verb. Every item in a list takes the same grammatical form as the others: all imperatives, all nouns, all noun phrases.
78 
79**Before (fragment intro, mixed forms):**
80 
81```markdown
82Use the --format flag to:
83- Print JSON
84- Print YAML
85- Print a table
86```
87 
88**After (complete intro, parallel nouns):**
89 
90```markdown
91The --format flag supports the following output types:
92- JSON
93- YAML
94- Table
95```
96 
97**Before (non-parallel steps):**
98 
99```markdown
100Before you deploy, complete these steps:
101- Installing the CLI
102- You need an API key
103- Configure the project
104```
105 
106**After:**
107 
108```markdown
109Before you deploy, complete these steps:
110- Install the CLI
111- Get an API key
112- Configure the project
113```
114 
115### S5 — Numbered vs. bulleted vs. description lists
116 
117Number a list only when order matters — the reader must do item 1 before item 2. Everything else is bulleted, including options, flags, and requirements that stand independently of each other.
118 
119**Before (numbered, but the items aren't a sequence):**
120 
121```markdown
1221. Enable verbose logging
1232. Enable colorized output
1243. Enable strict mode
125```
126 
127**After:**
128 
129```markdown
130- Enable verbose logging
131- Enable colorized output
132- Enable strict mode
133```
134 
135For term-and-definition pairs, a description list beats a two-column table — the term reads as a heading, not a table cell, and there's no header row to skip. Markdown has no universal native syntax for this, but the widely supported Markdown Extra / Pandoc form is:
136 
137```markdown
138`--dry-run`
139: Previews changes without applying them.
140 
141`--verbose`
142: Prints each step as it runs.
143```
144 
145**Punctuation** `[EN]` (inferred): capitalize the first word of every item regardless of form. A complete sentence ends with a period; a fragment doesn't.
146 
147- Fragment, no period: "- Verbose output"
148- Complete sentence, period: "- Verbose output is enabled by default."
149 
150Source: lists
151 
152## Tables (S6)
153 
154A table needs a header row and an intro sentence that states what it lists — "The following table lists the `cascade deploy` flags:" — so a reader (and a screen reader) knows what they're about to scan before they hit the grid. Never merge cells and never leave one empty: an empty cell reads to assistive tech as if nothing is there at all, not as "not applicable". Write "None" or "Not applicable" instead (convention). Keep cell phrasing parallel down a column — if one description is a sentence, they all are.
155 
156Reach for a bulleted or description list instead of a table when there's only one dimension of comparison (a plain list of flags with no second attribute) or when most cells would carry long prose — tables earn their header row only when the data is genuinely tabular across two or more attributes.
157 
158**Before:**
159 
160```markdown
161| Flag | |
162|------|--|
163| --verbose | |
164| --dry-run | Preview changes |
165```
166 
167**After:**
168 
169```markdown
170The following table lists the `cascade deploy` flags:
171 
172| Flag | Description |
173|------|-------------|
174| `--verbose` | Prints each step as it runs. |
175| `--dry-run` | Previews changes without applying them. |
176```
177 
178Source: tables, accessibility
179 
180## Notices (S7)
181 
182A notice interrupts the reader's flow, so it earns that interruption only when the information changes what they do next.
183 
184- **Note** — useful, optional information the reader can act on or skip: "Cascade caches build artifacts in `.cascade/cache`. Delete this directory to force a clean build."
185- **Caution** — proceed carefully; the mistake is recoverable but costly: "Changing the region after deployment migrates your database and can take up to 30 minutes."
186- **Warning** — serious harm or irreversible loss: "Running `cascade reset --hard` permanently deletes all environments and can't be undone."
187 
188Don't stack them. (Inferred) one notice per section is a practical ceiling — three boxes in a row train the reader to skip all three, including the one that matters.
189 
190Fold a notice into body text whenever it doesn't change the reader's next action — a plain sentence in the paragraph carries the same information without the visual interruption.
191 
192**Before:**
193 
194```markdown
195Run `cascade deploy` to publish your app.
196 
197> **Note:** This command requires an active internet connection.
198```
199 
200**After:**
201 
202```markdown
203Run `cascade deploy` to publish your app. This command requires an internet connection.
204```
205 
206Source: notices
207 
208## Cross-references (S8)
209 
210Point to other content with "see", never "refer to" or "check out". Never say "above" or "below" — pages reflow, get translated into languages that reorder content, and get read out of order by screen readers and search results. Use "the following" for what comes immediately after in the same page, "the preceding" for what came immediately before, and a named link for anything farther away.
211 
212Link when the referenced material lives on another page, or is optional depth the current task doesn't require. Inline the fact instead — repeat the one sentence the reader needs — when sending them away would interrupt a procedure they're mid-way through.
213 
214- "For more info, check out the docs above." → "For more information, see Configure authentication."
215- "As mentioned below, you'll need an API key." → "You need an API key; see Get an API key."
216- "Refer to the table above for exit codes." → "See the preceding table for exit codes."
217 
218Source: cross-references
219 
220## Link text (S9)
221 
222Link text should read as the destination's title, or a close description of it, so it makes sense pulled out of the sentence — many screen readers list a page's links with no surrounding text at all. Never link "click here", "this link", or a bare pasted URL. Put the link on the words that name the target, not on a filler verb.
223 
224- "To learn about rate limits, click here." → "For rate limit details, see [Rate limits](#)."
225- "Read more at https://docs.cascade.dev/webhooks." → "For webhook payload formats, see [Webhook payloads](#)."
226- "This link explains how authentication works." → "See [How authentication works](#) for the full flow."
227 
228Source: link-text, accessibility
229 
230## Images and alt text (S10)
231 
232Alt text states what the image communicates in this context, not what it literally shows — skip "Image of" and "Screenshot of"; the screen reader already announces that it's an image. Keep it to one concise phrase or sentence, not a full transcription of every pixel.
233 
234Information must never live only in an image: if a diagram is the sole place a required value, flag, or step appears, the doc is broken for anyone who can't see it and for anyone who needs to copy that value. This is a shippability gate (Blocking) — put the same fact in the surrounding text.
235 
236Use a screenshot to show where something sits in a UI or to confirm a visual result — a filled-in form, a chart the reader compares theirs against. Use text or a code block for anything the reader types, copies, or runs: text is copyable, searchable, and translates; a screenshot of a command is none of those. Write the caption first — naming the figure's one idea before you draw or crop it keeps the image on message (tech-writing/two) — and never let the caption alone carry a detail that's missing from the alt text.
237 
238**Before:**
239 
240```markdown
241![Screenshot of the dashboard](dashboard.png)
242 
243Click the button to deploy.
244```
245 
246**After:**
247 
248```markdown
249![The Deploy button in the top-right corner of the Cascade dashboard, next to the environment selector](dashboard.png)
250 
251Click **Deploy** in the top-right corner of the dashboard.
252```
253 
254Source: images, accessibility
255 
256## Numbers, dates, and units (S11) `[EN]`
257 
258Spell out zero through nine; use numerals for 10 and up. Always use numerals with units, versions, and measurements, no matter how small the number: "3 MB", "version 2 of the API", "5 retries". Dates must be unambiguous — "2026-08-29" or "August 29, 2026" — never "08/29/26" or "29/08/26", which read as different dates depending on the reader's locale. Include a time zone whenever a time matters across regions: "2:00 PM UTC", not "2:00 PM". Units get a space and the standard symbol, never a spelled-out or invented abbreviation: "10 MB", not "10MB" or "10 megs". The time-zone and unit-spacing forms are inferred — the sourced pages cover number and date formats.
259 
260- "The free tier includes 3 projects and up to 100mb of storage." → "The free tier includes three projects and up to 100 MB of storage."
261- "The migration finished on 08/09/26 at 2pm." → "The migration finished on 2026-08-09 at 2:00 PM UTC."
262- "This feature requires SDK version two." → "This feature requires SDK version 2."
263 
264Source: numbers, dates-times
265 
266## Text formatting summary (S12)
267 
268| Format | Use for | Example |
269|--------|---------|---------|
270| **Bold** | UI element names, matching on-screen casing (P5) | Click **Deploy**. |
271| `Code font` | Commands, flags, filenames, code, values (P6) | Run `cascade deploy --dry-run`. |
272| *Italics* | A new term on its first use; emphasis, used sparingly | A *webhook* is an HTTP callback that Cascade sends when an event occurs. |
273 
274Don't format product names — plain text, matching the vendor's own capitalization (P6). See `procedures-and-code.md` for the full code-font, placeholder, and UI-element rules behind P5 and P6.
275 
276Source: text-formatting
277 
278## Worked example
279 
280**Before** — headings break case and nest wrong, the list has a fragment intro and non-parallel items, the table has no intro sentence and empty cells, and two notices stack back to back:
281 
282```markdown
283# Configuring Webhooks.
284 
285## Setting Up
286 
287To set up webhooks you can:
288- signing secret
289- Choose a delivery URL
290- pick which events to send
291 
292## The Payload
293 
294Below is a table of fields you might get back:
295 
296| Field | |
297|-------|--|
298| event | |
299| id | The event's ID |
300 
301Note: Webhook retries happen automatically.
302Caution: If your endpoint returns a non-2xx status the delivery is marked failed and won't retry.
303```
304 
305**After** — sentence-case imperative headings, one parallel bulleted list with a complete intro, a table with a header row and no empty cells, the routine fact folded into body text, and a single notice:
306 
307```markdown
308# Configure webhooks
309 
310## Set up a webhook
311 
312To set up a webhook, complete these steps:
313 
314- Generate a signing secret.
315- Choose a delivery URL.
316- Select which events to send.
317 
318## Webhook payload fields
319 
320The following table lists the fields in every webhook payload:
321 
322| Field | Description |
323|-------|-------------|
324| `event` | The event type, for example `payment.succeeded`. |
325| `id` | The event's unique ID. |
326 
327Cascade retries a failed delivery up to five times before it gives up.
328 
329**Caution:** Changing the delivery URL cancels any retries already queued for the old URL.
330```
331 

Discussion

Alternatives