Skip to content

How to Build a Multi-Page Website from One File

A route in Micropage is a block, not a file. This header starts one:

[Pricing -> /pricing]

Everything after it belongs to that page until the next line that starts with [ in column 0. The label on the left isn’t decoration — it becomes the page title, and the rendered <title> is Pricing - Your Site Title. Drop the arrow and the path is derived from the label instead: [Case Studies] publishes at /case-studies.

One consequence of splitting on [: a body line that begins with a bracket also starts a new block, and since it isn’t a valid header, that chunk is dropped from the build. Indent it or rewrite the line.

The nav is a separate list

[nav] is not derived from your page blocks. It’s its own list of links:

[nav]
Home -> /
Tour -> /tour
Pricing -> /pricing
Docs -> https://docs.micropage.sh
btn: Generate a page -> https://app.micropage.sh

Three things follow from that. Each line needs an -> (or a link: / btn: prefix); lines without one are skipped silently. Nothing cross-checks nav targets against the pages you defined, so a typo’d path compiles happily into a link to a route that doesn’t exist. And the nav is attached to each page as the parser reaches it — a [nav] block placed halfway down the file only reaches the pages below it.

So put [site], [nav], and [footer] at the top, before any page block, and every page inherits them. Indent a link two spaces under another to turn the parent into a dropdown; one level of nesting, no more. [footer] behaves the same way: one block, shared by every page.

Per-page meta

Each page can override the site’s SEO defaults with an indented meta: block. It has to come before the first /// section separator:

[Privacy -> /privacy]
meta:
  description: Privacy policy for Micropage — how we collect, use, and protect information across micropage.sh and customer sites.

/// section
h1: Privacy Policy

Accepted keys are description, keywords, canonical, og_image, og_type, and noindex. The page value wins over the [site] value; anything the page leaves out falls back to the site default. Keys outside that list are ignored without an error, which is forgiving until you misspell one.

Splitting across several files

The markup doesn’t care whether all of this lives in one file — the CLI concatenates before anything is parsed. landing.page goes first, then every other top-level *.page file in alphabetical order, joined with a blank line. Subdirectories are skipped, so the starter templates in examples/ never reach a build.

A site can therefore be:

landing.page    [site], [nav], [footer], [Home -> /]
pricing.page    [Pricing -> /pricing]
privacy.page    [Privacy -> /privacy]

Keep [site] and [nav] in landing.page. It merges first, which is exactly the ordering the nav rule above needs.

One sharp edge: micropage projects pull writes the published build’s entire merged source into landing.page and leaves your other .page files untouched. Pull into a split project and the next push defines every page twice. Treat pull as a single-file operation, or don’t split.

The web editor is a single markup buffer, so file splitting is a CLI concern only. The compiled result is identical either way — this marketing site is eight page blocks, one [nav], and one [footer] in a single file.

What ends up in the sitemap

/sitemap.xml is generated from the page blocks — one <url> each, with lastmod set to the deploy timestamp. Two exclusions: pages with noindex: true, and pages whose canonical points at a different hostname, since those belong to another site. If the project has a posts archive, its index and every listed post are appended. noindex: true at the [site] level empties the file entirely.

There’s nothing to configure. The absolute URLs come from your custom domain, or from the *.micropage.sh host if you haven’t attached one.

Next steps