Article Body Elements
This is the golden standard for how article body content is authored, rendered, and styled on id86.net. Any AI or author creating or editing a .md file in ID86-instant-documentation must read this document first and follow the contract below.
Pipeline Overview
Markdown is converted by sync.py using markdown2 with these extras:
fenced-code-blocks, tables, strike, header-ids, footnotes, highlightjs-lang
The generated HTML is serialized into Gutenberg block markup by tools/blockify.py and stored as post_content, so posts open in the block editor as real blocks (headings, tables, lists, admonitions, and Code Block Pro blocks) — no "Classic" block or manual Convert-to-blocks step. Styling and behavior are applied at render time:
css/article-content-v2.css— all article body element styles (child theme).js/article-content.js— table scroll wrapper, heading anchors, task checklists (child theme).opshell-docusaurus-admonitions— rendersopshell/admonitionblocks server-side.- Code Block Pro (plugin) — code blocks are pre-rendered by Shiki (VS Code engine,
github-dark) intowp:kevinbatdorf/code-block-problocks; the plugin'sfront.jsadds the copy button.
See 4. WP Ops → Gutenberg Block Reference for the exact block serialization formats and the markdown→block mapping.
Element Contract
This table is the authoritative mapping. Follow it exactly when authoring.
| Element | Markdown syntax | Serialized as (Gutenberg block) | Rendered HTML | Styled by | JS |
|---|---|---|---|---|---|
| Page title | Frontmatter title | — (rendered by #Single Post Title) | H1 | Brand H1 | — |
| Post meta line | none (auto) | — (rendered by [id86_modified_date]) | updated M j, Y · N min read | .id86-post-meta | — |
| H2 section | ## Heading | core/heading (anchor) | <h2 id class="wp-block-heading"> | article-content-v2.css h2 | anchor link |
| H3 | ### Heading | core/heading (level+anchor) | <h3 id class="wp-block-heading"> | h3 | anchor link |
| H4 | #### Heading | core/heading (level+anchor) | <h4 id class="wp-block-heading"> | h4 | anchor link |
| Paragraph | blank-line separated text | core/paragraph | <p> | p | — |
| Bold | **text** | inline in paragraph | <strong> | strong | — |
| Italic | *text* | inline in paragraph | <em> | inherited | — |
| Inline code | `code` | inline in paragraph | <code> | :not(pre) > code | — |
| Strikethrough | ~~text~~ | inline in paragraph | <del> | inherited | — |
| Link | [text](url) | inline in paragraph | <a href> | a | — |
| Unordered list | - item | core/list + core/list-item | <ul class="wp-block-list"><li> | ul/ol | — |
| Ordered list | 1. item | core/list (ordered) + core/list-item | <ol class="wp-block-list"><li> | ul/ol | — |
| Task checklist | - [ ] item / - [x] item | core/list + core/list-item (literal [ ]/[x] kept in <li> text) | <ul><li>[ ] item</li></ul> | article-content-v2.css | article-content.js → interactive checkbox |
| Code block | ```lang fenced | kevinbatdorf/code-block-pro block (Shiki pre-rendered) | <div class="wp-block-kevinbatdorf-code-block-pro"> | plugin CSS | CBP copy button |
| Table | pipe table | core/table | <figure class="wp-block-table"><table class="has-fixed-layout"> | table | scroll wrapper |
| Blockquote | > text | core/quote | <blockquote class="wp-block-quote"> | blockquote | — |
| Admonition | :::type title | opshell/admonition | <aside class="opshell-admonition"> | plugin CSS | — |
| Footnote | [^1] + definition | inline <sup> in paragraph + .footnotes in core/html | <sup class="footnote-ref"> / .footnotes | footnotes | — |
| Image |  | core/image | <figure class="wp-block-image"><img> | img | — |
| Horizontal rule | --- | core/separator | <hr class="wp-block-separator has-alpha-opacity"/> | hr | — |
Every element is wrapped in <!-- wp:<name> … --> … <!-- /wp:<name> --> block comments (serialized blocks), so the stored post_content is editor-ready block markup. See 4. WP Ops → Gutenberg Block Reference for every serialization format verbatim.
Authoring Rules
Heading hierarchy
The single-post template renders the title as H1. Article bodies must start at H2. Never use an H1 in the body — it duplicates the template title.
---
title: Git Quick Reference
---
## Start a repository ✅ correct — H2 is the first heading
Code blocks
Always use a fenced code block with a language tag. The tag drives Shiki highlighting and the language label:
```bash
sudo apt install plocate
```
markdown2 with the highlightjs-lang extra emits class="bash language-bash", which the sync pipeline converts into a Code Block Pro Gutenberg block (wp:kevinbatdorf/code-block-pro) pre-rendered with Shiki (VS Code engine) using the github-dark theme. The rendered block includes a built-in copy button, line numbers are off by default, and highlighting is baked into the saved HTML (no client-side tokenizer).
Tables
Use pipe tables. A header row is required:
| Task | Command |
|------|---------|
| Commit | `git commit -m "msg"` |
Wide tables are wrapped in a horizontal-scroll container by JS; keep cells concise.
Admonitions
Use Docusaurus ::: syntax. Supported types: note, tip, info, warning, danger. A custom title is optional.
:::note
Documentation posts do not require a featured image.
:::
:::warning[Custom title]
Removing a `.md` file does not delete its WordPress post.
:::
Admonitions are converted to <aside class="opshell-admonition opshell-admonition--note"> by the opshell-docusaurus-admonitions plugin (active on production).
Styling is a disclosure card — the child theme overrides the plugin stylesheet (css/article-content-v2.css) so admonitions match the .id86-affiliate-disclosure box on the Recommendations page (CSS-only, no icons, no JS):
- Card: solid tinted surface,
1pxborder + 4px left accent,border-radius: 6px, no gradient, no box-shadow; full column width,padding: 14px 16px. - No icon: the plugin's SVG badge (
.opshell-admonition__badge) is hidden withdisplay: none. - Body:
0.92rem/line-height 1.6; title is bold, accent-colored (1rem). - Per-type accents (light / dark): note violet
#7c5cbf/#a78bfa, tip green#2f9e44/#4cc46a, info teal#0d9488/#2fc3b3, warning amber#b7791f/#e0a83c, danger red#c24141/#e05a5a. Dark mode uses solid dark surfaces. - Palette changes belong in
css/article-content-v2.css(theme--id86-admonition-*custom properties); bump the themeVersionheader so the?ver=cache-bust updates.
Task checklists
Use task-list bullets for sequential setup/checklist steps. The marker renders as a clickable, Notion-style checkbox on the live site — state is persisted per visitor in localStorage, so progress survives reloads. Each checklist group (<ul>) with two or more items shows a "X of Y done" progress badge + bar above it that updates live. Theme v1.20 adds a per-group Reset button, a green completion checkmark on full completion, and a Checklist hint pill for single-item lists. See Task Checklists for the full contract.
- [ ] Install tmux from your package manager.
Debian/Ubuntu and macOS (Homebrew) are both supported.
sudo apt install tmux
brew install tmux
Layout contract:
- Checkbox + title inline on the bullet line — the checkbox always leads.
- Content goes below the title, never before the checkbox: an optional short description can be indented (4 spaces) directly under the bullet (renders as a muted sub-line); commands go in a separate fenced code block below.
- [ ]= pending,- [x](or- [X]) = already done (renders pre-checked and struck through).- Do not nest checkbox lists deeper than one level; sub-commands belong in code blocks.
- Use checklists for step-by-step flows (setup, verification, migration). Don't use them for ordinary prose lists.
Prefer multi-item groups
A checklist group only earns its full UX — the "X of Y done" progress bar, the completion checkmark, and the per-group Reset — when the group holds two or more contiguous - [ ] items. Design checklists so each section has at least 2–3 steps in one block; a lone - [ ] item still becomes a checkbox but renders only a small Checklist hint pill and no progress.
Keep the group contiguous. The items of one group must sit in the same block with nothing between them — no fenced code blocks, no blank-line paragraphs, no headings, and no nested lists. Any of those breaks the <ul> in HTML, silently splitting the group into single-item lists, so the progress header disappears for that section even though the checkboxes still work.
To keep groups contiguous when a step needs commands:
-
Write the full group of
- [ ]items first, then put the fenced code block(s) after the whole group:- [ ] Install tmux from your package manager.- [ ] Confirm the version with `tmux -V`.- [ ] Reload the config inside a running session.```bashsudo apt install tmuxtmux -Vtmux source-file ~/.tmux.conf -
Or keep the code block inside one item's indented description (4 spaces) so it stays within that item and does not separate siblings:
- [ ] Install tmux from your package manager.```bashsudo apt install tmuxbrew install tmux- Confirm the version.
Rule of thumb: if you can visually draw one box around the whole section's checkboxes, the group is contiguous. If a code block or paragraph sits between two checkboxes, split it into its own group or move it after the list.
Visual contract (design rules — see Task Checklists):
- Rows are card-style (light
#fcfefffill, thin border, 3px left accent rail, 10px radius, soft shadow). - Idle → hover
#f4faff; checked (is-done) →#e8f3fb; checked + hover →#dceefa. Dark mode has its own palette. - The checklist is flush against the left edge of the article column (list indent removed).
- Checked rows strike through and mute the text; each group's
Resetbutton clears only that group, and a finalReset checklistbutton clears the visitor's whole-post progress.
The stored HTML keeps the literal [ ] marker; js/article-content.js converts it to a styled <input type="checkbox"> at render time, adds id86-task-list to the parent <ul>, groups items by parent <ul>, and injects the per-group progress header (CSS in css/article-content-v2.css).
End-to-end: Markdown to live checkboxes
-
Author the checklist in the
.mdsource with literal- [ ]/- [x]bullets (see Task checklists above). Keep each group's items contiguous — a fenced code block between items splits the group in HTML, so no "X of Y done" progress header renders for that group. -
Sync the repo to WordPress with the standard wrapper:
cd /home/rezriz/github/ID86-instant-documentation./tools/id86-sync.sh --dry-run # validate markdown only, no WordPress changes./tools/id86-sync.sh # real sync: render → WP-CLI bridge → WordPressid86-sync.shrunssync.py, which converts the body withmarkdown2, renders code blocks with Shiki, SCPs the payload + bridge to the origin host, and runswp eval-filethrough WP-CLI. Only changed documents (by source hash) are updated. -
Post-sync automation runs automatically: the Fuse.js search index is rebuilt, and LiteSpeed (origin-direct) + Cloudflare caches are purged for the changed posts (plus the homepage).
-
Verify on the live post: checkboxes render clickable, a multi-item group shows the live progress header with a per-group
Resetbutton and a green ✓ on full completion, single-item lists show theChecklisthint pill, and the finalReset checklistbutton clears the post'slocalStoragestate. The score-90 reference post isdemo/checklist-ux-demo.md(https://id86.net/demo/checklist-ux-demo/).
The checklist transform happens entirely at render time in js/article-content.js — nothing in the stored HTML changes beyond the literal [ ] marker, so re-syncing an unchanged file is a no-op.
Glossary
A glossary post (content type: glossary) is one term per H2, never a bold list under a single Terms heading. This gives every term a heading anchor and makes each term a scannable section that answers what is X?.
## Pane
A rectangular split region inside a window. Panes share the window's size and can be
resized, zoomed, and rearranged.
## Session
A named collection of windows. Sessions survive detach and are the unit you attach
to with `tmux attach`.
Layout contract:
- Each term =
## Term— sentence case, no trailing period in the heading. - Definition-first: sentence 1 answers "what is it"; sentence 2 (optional) adds usage, a command, or a relevant cross-link.
- No
## Termswrapper heading — it becomes empty once terms are H2s. Add an optional lead-in paragraph before the first term instead. - Keep 8–15 terms, roughly 250–450 words, so every heading carries real definition content rather than a heading dump.
- Cross-link each term to the deepest existing post on that concept — descriptive anchor text, one target per term, no dead-end terms. This is what lets a glossary feed per-term rankings; see Glossary SEO.
- The heading hierarchy rule still applies — the template title is H1, so
## Termis the correct starting level.
The reference post content/demo/DEM-000005-tmux-glossary.md (https://id86.net/demo/tmux-glossary/) is the verification fixture for this format.
Footnotes
Define the note anywhere below the reference:
A reference here.[^1]
[^1]: The footnote definition text.
Where Styling Lives
| Concern | Location |
|---|---|
| Article CSS | id86/css/article-content-v2.css |
| Article JS | id86/js/article-content.js |
| Admonition CSS | plugin opshell-docusaurus-admonitions/assets/css/admonitions-v2.css, overridden by id86/css/article-content-v2.css (disclosure card, no icon) |
| Code blocks | Code Block Pro plugin (code-block-pro free + cbp-theme-pack), pre-rendered by Shiki in ID86-instant-documentation/tools/code_block_pro/ during sync |
| Syntax theme | Shiki github-dark (VS Code engine) |
| Enqueue | functions.php — article CSS/JS loaded only on is_single(); CBP block assets auto-enqueued when a block is present |
All CSS uses the brand tokens from the brand system (--id86-navy, --id86-blue, --id86-sky, --id86-ink, --id86-mist).
Verified Sample
The live reference post demo/styling-sample.md (https://id86.net/demo/styling-sample/) exercises every element above and is the verification fixture for this standard. Re-run the sync and inspect that post after any styling change.