# Rich content (MD2)

Posts aren't walls of text. baas writes **MD2** — Markdown plus a directive
layer — so articles come with real document structure. This page is
rendered by the same engine your posts use, so every example below is live.

:::callout{severity=info title="Why it matters"}
Structured posts read better, keep visitors on the page longer, and give
search engines and AI assistants clean semantics to cite. It's the visible
difference between generated filler and content you're proud to put your
name on.
:::

## What your posts can contain

**Callouts** — asides with a severity, like the ones on this page.

**Step-by-step guides:**

::::steps

:::step[Structure appears where it helps]
The drafter is instructed to use components only when they serve the
reader — never decoratively.
:::

:::step[Everything degrades gracefully]{status=current}
If a component can't render, the content still reads as clean Markdown.
:::

::::

**Comparisons:**

::::compare{title="Structured vs plain articles"}

:::option[MD2 post]{key=A severity=success}

- Scannable: steps, callouts, tables
- Charts and diagrams where words are slow
- Code with inline annotations

:::

:::option[Plain article]{key=B severity=warning}

- One long column of paragraphs
- Data described instead of shown
- Reads like every other AI blog

:::

::::

**Charts** from inline data:

:::chart{type=bar title="Time on page (illustrative)"}
structured post: 74
plain article: 41
:::

**Timelines, annotated code, file trees, tabs, badges** — see the full
gallery on a real article: the showcase post demonstrates every component
in one place (your dashboard's demo blog includes it).

## Featured images

Every generated post can also carry a **featured image**: a wide `16:9` hero,
generated with the article and drawn in your blog's own palette.

:::callout{severity=info title="No text in the picture, on purpose"}
The art direction forbids letters, labels and logos. Model-rendered text is
usually misspelled, it can't be edited without paying for a new picture, and
one image is shared by every translation of a post — a caption baked into
the pixels would be wrong in every locale but one.
:::

**What it looks like: whatever your site looks like.** Before the picture is
drawn, two things happen.

First, once per site, we **look at your website** — its real colours in the
proportions you actually use them, its typography and shapes, and the images
you already publish. That produces a written description of your brand's
look: your palette by role, the mood, and crucially the *kind* of pictures
you run (photography? flat illustration? 3D? none at all?) and how they are
finished. You can read it, and correct the scan by re-running it, on your
site's settings page.

Then, for **each article**, an art director reads the finished piece — not
just its title — along with your industry, audience and products, that
visual identity, and the last few heroes this blog already published. It
decides what this specific article's picture should be, including which
medium fits, and writes the brief the image model renders.

That is why two articles on the same blog get different pictures, and why a
picture of yours does not look like a picture of somebody else's. There is
no house style being applied on top of your brand — the only things fixed
for everyone are the frame and the no-text rule below.

:::callout{severity=warning title="Scan your site first"}
Without the visual scan there is no evidence of what your brand looks like,
so art direction falls back to your industry and audience alone — accurate,
but generic. Press **Refresh from site** on your site's settings page once;
it also refreshes your content profile.
:::

**Where it shows up**, everywhere at once, with no work on your side:

| Surface | What you get |
|---|---|
| Article page | A hero `<img>` above the headline, with intrinsic width and height so the text never reflows around it |
| Social sharing | `og:image`, `og:image:alt`, dimensions, and `twitter:card: summary_large_image` |
| JS SDK | `hero_image_url` in the fragment JSON; the SDK sets the social tags and clears them when you navigate to a post without one |
| Sitemap | A Google [image sitemap](/docs/delivery-api) entry per post |
| RSS | An `<enclosure>` with the image's real byte length and type |
| [Webhooks](/docs/webhooks) | An `image` object on the post payload |

**Where it is served from.** Your own API, at `https://api.dailysmith.com/v1/media/{id}`
— a permanent, immutable, CDN-friendly URL, not an expiring storage link.
It is public by id (an `<img>` is fetched by browsers and crawlers that hold
none of your credentials) and the id is a random UUID nobody can guess.

**Turning it on and off.** Featured images are **on by default**, per blog,
on the blog's settings page. Each image costs about $0.13, plus roughly
$0.01 for the art-direction step, billed with the post that it belongs to
and shown in that post's generation trace next to what the writing cost —
art direction has its own row there, so you can always read what the picture
was asked for.

:::callout{severity=success title="It can never cost you an article"}
Image generation is best-effort, exactly like the rich-content renderer: if
the model refuses, the request times out, or storage is unavailable, the
failure is recorded in the post's generation trace and **the article is
published without a picture**. Nothing about your content depends on it.
:::

**Not the picture you wanted?** Each post's page has a **Regenerate image**
button. It buys a different picture — the art director is told what the
current one shows, so it will not hand you the same idea again — and points
the post at the new one everywhere it appears. The old image keeps its URL
and keeps resolving, so a social card someone already shared, or a crawler
that indexed it, never breaks. It costs the same as the first one.

**Existing posts.** A post written before you turned images on has a
**Generate image** button on its page in the dashboard. It runs in the
background and attaches the result. A post that already has an image keeps
it — regenerating is deliberately not offered, so a picture you have already
approved never changes under you.

## Theming

Every component reads fifteen color tokens, so the whole system re-skins to
match your site — manually or from an [AI scan of your site's design](/docs/theming).

## For the curious: the syntax

Directives are fenced with `:::` and nest with `::::`:

```
:::callout{severity=info title="Heads up"}
One-paragraph aside.
:::

::::steps
:::step[First]
Do the thing.
:::
::::
```

You never need to write this yourself — the drafter produces it — but the
raw source of every post is kept (`body_markdown`), so your content is
portable, re-renderable, and never locked into HTML.
