# arthub authoring conventions
The publish API rejects violations with 400. Read `findings` in the response,
fix them, and call again.
## Format
Markdown is the default. The theme renders prose well on its own; move only the
interactive parts into live blocks. Reach for whole-document HTML only when a
piece needs to own the entire layout, like a slide.
Publish articles and reports as Markdown (format: md). Wrap only self-contained interactive components in ```html render blocks inside the same Markdown body. Reserve format: html for full-page dashboards, prototypes, or slides that must own the entire layout — never for an article.
### What Markdown already supports
- Headings, paragraphs, lists, blockquotes, tables, links, images, footnotes[^1], task lists - [ ]
- Callouts: > [!NOTE] > [!TIP] > [!WARNING] > [!CAUTION] > [!IMPORTANT]
- Code fences with a language and an optional title: ```ts title="src/app.ts"; change markers // [!code ++] // [!code --] // [!code highlight] // [!code focus]
- Mermaid diagrams: ```mermaid fences render as diagrams
- Charts from data: ```chart preset (column, bar, line, area, pie, radial, polar, radar)
- Layout components: ::: grid / card / stat / compare / timeline / figure / details
- Live components for anything interactive: self-contained ```html render blocks
Before reaching for whole-document HTML, check this list — most "I need HTML"
cases are one of the blocks above.
**Do not write your own styles.** Color, type, and spacing belong to the theme.
Express structure with the components below, and use a live block only for what
components cannot express.
## Rules (publishing fails if you break these)
1. No raw HTML in the body.
,
,
,
— all rejected.
The parser swallows them as one opaque node, and a person can no longer edit
that part on the web. Use Markdown for emphasis, ::: components for layout,
and live blocks for anything interactive.
2. Exactly one # heading per document. Split sections with ##.
3. When nesting ::: components, make the outer marker longer.
:::card inside ::::grid. Equal-length markers close at the first one and the
document breaks silently.
4. A live block must be self-contained. Each one runs as its own document, so
blocks cannot share variables and cannot reach the parent page
(window.parent, top.).
5. Build charts only with the ```chart preset. Never hand-write a Charts.css
— label-collision handling only runs on the preset path.
## Components
Available: grid, card, stat, compare, timeline, figure, details
::::grid{cols=2}
:::card{title="Throughput"}
1,200 requests per second.
:::
:::card{title="Latency"}
p99 240ms.
:::
::::
:::stat{label="MAU" value="12.4k" delta="+8%" trend="up"}
:::
:::details{summary="Raw log"}
Collapsed content.
:::
:::figure{caption="Request flow"}

:::
## Charts
```chart
type: column
caption: Signups by month
x: [Jan, Feb, Mar, Apr]
series:
- { name: Signups, data: [120, 180, 240, 310] }
- { name: Churn, data: [20, 24, 31, 28] }
```
- type: column, bar, line, area, pie, radial, polar, radar
- Give it data only. Palette, dark mode, and label collisions are handled for you
- Long labels or nine-plus categories switch to horizontal bars automatically
- Past 30 data points a table reads better
## Live blocks
```html render
```
- The info string must be exactly `html render`. Without `render` it stays a code listing
- Height is measured for you. position:fixed is not allowed
- External scripts may load only from: cdn.jsdelivr.net, unpkg.com, cdnjs.cloudflare.com
- Limits: 20 blocks per document, 64KB per block
- Use var(--ah-c1)–var(--ah-c6) for color and set no font — theme tokens are already injected
## Also available
- Callouts: > [!NOTE] > [!TIP] > [!WARNING] > [!CAUTION] > [!IMPORTANT]
- Code: ```ts title="src/app.ts"
Change markers: // [!code ++] // [!code --] // [!code highlight]
- Tables, footnotes[^1], task lists - [ ], mermaid diagrams
## Habits
- Put list-shaped data in a table, not bullets
- Put caveats in a callout
- Draw structure and flow with mermaid
- Call list_artifacts before creating anything, to see if it already exists
- To revise, call update_artifact with the same slug instead of publishing a new
document — the link keeps working
- To move a document between projects without changing its body or version, call
move_artifact with its stable id and current version
- Call get_draft before updating. If a person has an unpublished draft open, stop
and report the conflict to the user instead of calling update_artifact
## Publishing
Remote MCP: https://artifact.sharosoo.com/mcp (OAuth by default; tools: publish_artifact, update_artifact, move_artifact, get_draft, list_artifacts, read_artifact, delete_artifact)
Optional personal tokens: https://artifact.sharosoo.com/settings/tokens
Local files and images: the arthub CLI