Roads

A road is a path that draws itself as the reader scrolls. Each milestone on the path is a link from your post. Use roads for roadmaps, release histories, onboarding paths, project timelines, or any sequence that readers walk through.

Roads are built in to the default theme. You need no template, config, or plugin. Write a Markdown container named road, and put a list of links inside it.

Quick start

::: road

- [Install markata-go](/docs/getting-started/) Step one
- [Configure your site](/docs/guides/configuration/) Step two
- [Pick a theme](/docs/guides/themes/) Step three
- [Publish feeds](/docs/guides/feeds/) Step four
:::

That renders as:

::: road

Each list item is one milestone:

Wikilinks work too. A milestone written as my-post uses that post's title, and its hover card shows the post's description.

Choose a style

Put the style name after road. The default style is winding.

Style Good for
winding Journeys, reading paths, story arcs
timeline Dated events, changelogs, history
steps Short processes of three to six steps
snake Long ordered sequences, such as courses or series
cycle Processes that repeat, such as sprints or seasons
constellation Loosely related ideas or a "see also" map
git Branching work, such as release trains or experiments
editorial Timelines where each entry has paragraphs, lists, or images

Timeline

::: road timeline

- [Project announced](/blog/announcement/) Jan 2026
- [Public beta](/blog/beta/) Apr 2026
- [Version 1.0](/blog/v1/) Jul 2026
- [Plugin marketplace](/blog/plugins/) Oct 2026
:::

::: road timeline

Steps

Steps read from left to right. On narrow screens they change to a timeline.

::: road steps

- [Draft](/handbook/draft/) write
- [Review](/handbook/review/) edit
- [Publish](/handbook/publish/) ship
- [Share](/handbook/share/) promote
:::

::: road steps

Snake

The snake style wraps a long list back and forth across rows, like a board game.

::: road snake

- [Variables](/course/variables/) 1
- [Functions](/course/functions/) 2
- [Loops](/course/loops/) 3
- [Structs](/course/structs/) 4
- [Interfaces](/course/interfaces/) 5
- [Errors](/course/errors/) 6
- [Testing](/course/testing/) 7
- [Concurrency](/course/concurrency/) 8
:::

Cycle

::: road cycle

- [Plan](/process/plan/) week 1
- [Build](/process/build/) week 2
- [Review](/process/review/) week 3
- [Retro](/process/retro/) week 4
:::

::: road cycle

Constellation

The points sit in fixed, scattered positions joined by fine lines. The layout is the same on every visit.

::: road constellation

- on-writing-clearly essay
- notes-on-focus note
- a-reading-list list
- why-plain-text essay
:::

Git

The git style draws a commit graph with branches and merges. List the commits in order, and write the branch after each link:

After the link Meaning
main A commit on main. A new branch name starts a branch from the first branch (the trunk).
fix/typo from feat/search Starts fix/typo from the latest commit on feat/search.
main <- feat/search Merges feat/search into main. You can also write ←.
::: road git

- [Initial commit](/changelog/#init) main
- [Add search index](/changelog/#search) feat/search
- [Update README](/changelog/#readme) main
- [Search results page](/changelog/#results) feat/search
- [Dark mode](/changelog/#dark) feat/dark-mode
- [Merge search](/changelog/#merge-search) main <- feat/search
- [Try a new palette](/changelog/#palette) spike/palette from feat/dark-mode
- [Dark mode polish](/changelog/#polish) feat/dark-mode
- [Keep the palette](/changelog/#keep) feat/dark-mode <- spike/palette
- [Release 1.0](/changelog/#v1) main <- feat/dark-mode
:::

The first commit's branch is the trunk. Each branch gets its own lane and color. A merged branch frees its lane for the next branch.

Editorial

Use the editorial style when each entry needs more than a title. Write a heading for each entry, then any Markdown under it: paragraphs, lists, checklists, quotes, images, or code.

::: road editorial

### [Discovery](/projects/redesign/discovery/) March

We interviewed twelve readers and found three common problems.

- [x] interviews
- [x] survey
- [ ] analytics review

### [Prototype](/projects/redesign/prototype/) May

> Smaller pages, bigger type, fewer clicks.

### [Launch](/projects/redesign/launch/) August
:::

::: road editorial

Markdown Write

Write posts in Markdown with frontmatter.

Templates Shape

Change the layout with templates, or keep the defaults.

Deployment Ship

Build static HTML and host it anywhere. :::

How editorial entries work:

Editorial stories, icons, and reveal

::: road editorial story reveal

### :lucide-key-round: RSA migration and faster job views
*2026 Q3*

A lead paragraph explaining what changed and why it matters.

- Faster job views
- Simpler key rotation
- Clearer audit trails
- Fewer manual steps

### A quieter milestone without an icon
*2026 Q4*

The ordinary rail dot still works.
:::

A leading :lucide-name: icon becomes a badge on the rail, muted until the entry is active. An emphasis-only paragraph immediately after a heading becomes the eyebrow above its title. Both work on all editorial roads, without story. If the heading already has a beside-link label, it takes precedence and the emphasis paragraph stays in the body. Mixed-content paragraphs are not labels.

Add story for larger balanced titles, a larger opening paragraph, generous spacing, and a prose measure of about 64 characters. Direct unordered lists without task checkboxes become diamond-bullet highlights with a top rule. Lists of four or more items use two columns at viewport widths of 1100px or more. Cards, stats, and figures can use the wider entry body. Without story, existing editorial typography stays unchanged.

Add reveal independently for scroll-triggered entry fades and gentle upward motion. It works with or without story, respects reduced motion, and does not animate print, anchor targets, or keyboard-focused entries. Entries stay readable without JavaScript or IntersectionObserver, even if the enhancement fails: reveal animates arriving content rather than hiding it until a callback runs.

More than one road

A post can have any number of roads, in any mix of styles. Each road draws on its own as it scrolls into view.

Options

Use the container attribute block for options:

::: road {data-road="timeline" data-road-spacing="80"}

- [Alpha](/releases/alpha/) v0.1
- [Beta](/releases/beta/) v0.5
:::
Option Description
data-road="STYLE" Selects the style. This is the same as ::: road STYLE.
data-road-spacing="N" Sets the vertical space for each milestone, in pixels.

To change the colors, set CSS custom properties in your site CSS:

.road {
  --road-accent: #3fb68b;  /* progress line, active dots, labels */
  --road-muted: #4a4f5a;   /* the path before it is drawn */
}

The defaults come from your palette's --color-primary and --color-border-strong.

Using HTML instead of a container

A raw HTML <div> also works. Leave a blank line after the opening tag and before the closing tag, so the list inside is parsed as Markdown:

<div class="road" data-road="timeline">

- [Kickoff](/notes/kickoff/) Jan 2026
- [Launch](/notes/launch/) Jun 2026

</div>

Accessibility and fallbacks

How roads load

The road CSS and JavaScript load only on pages that contain a road. markata-go finds roads when it renders the post. CSS purge keeps the road styles in production builds, with no extra configuration.

Troubleshooting

The road shows as a plain list. Check that the container closes with a line that contains only colons (:::). For a raw <div>, check for the blank lines around the list. After you change shared CSS or templates, do a clean rebuild.

Some list items are missing. Only list items that contain a link become milestones.

The git graph joins the wrong branches. Branch names must match exactly. A merge (main <- feat/x) must come after at least one commit on both branches.

See also