Markup Cheatsheet
A one-page reference for the Micropage .page markup. Emit one element per line, don't nest tags, and stay inside the closed vocabulary below. There is also a machine-readable version at docs.micropage.sh/llms.txt for agents.
File shape
A typical .page file:
[site]block — title, description, logo, colors, lang- Optional
[nav]and[footer] - One or more page blocks:
[Home -> /],[About -> /about] - Sections inside each page:
/// hero,/// section, optional/// html
Site keys
Set inside the [site] block, one per line:
titledescriptionlogofaviconlangkeywordscolors.primarytheme_colorog_imageog_type
Nav
Inside a [nav] block:
Label -> /pathbtn: Label -> urlbtn-outline: Label -> url
Page header
[Name -> /path]starts a page- Optional
meta:line, followed by indenteddescription,og_type,canonical,keywords,lang,translation lang: rosets the page language (default: the sitelang, elseen);translation: en -> /aboutlinks a translated version and can repeat. See Multilingual Sites
Sections
/// hero— optional modifiersalign:centerandbg:primary|secondary|muted|success|info/// section— same optional modifiers/// html— raw HTML; avoid unless you specifically need it
Elements
h1:h2:h3:h4:h5:p:— the rest of the line is literal textsmall:- item— unordered list item;1. item— ordered list item (starts at the first number)table: Caption(optional), then| A | B |rows; the first row is the headericon: bi bi-name(Bootstrap Icons)img: alt: text <- filename.pngorimg: <- filename.pngbutton: Label -> urlbtn-secondary: Label -> urlbtn-outline: Label -> urllink: Label -> urllink: Label <- file.pdforlink: <- file.pdf— links to a file uploaded to the projectcol:starts a column; following element lines stay at column scope until the nextcol:or sectionform: nameinput: Labelorinput: Label*text:/textarea:select: Label [A, B, C]checkboxes: Label [A, B]radios: Label [A, B]submit: Labelsuccess: Messagenewsletter: trueornewsletter: false
A * at the end of a field label marks it required. It renders as a red asterisk after the label, and a form with at least one required field also renders a * indicates a required field key above its fields. Images written as <- filename resolve a file uploaded to the project.
Consecutive list lines form one list; a blank line or switching between - and 1. starts a new one. Lists don't nest. To write a paragraph that starts with - or 2024. , use p:. In tables the |---| separator row is optional, \| writes a literal pipe, and cells are plain text. See Lists & tables.
success: sets the confirmation shown after a successful submission; without it a form shows Thank you. Your message was sent. and a newsletter form shows Thank you. You're subscribed.. newsletter: only picks between those two wordings (and hides the Submit again button) — subscriber capture is turned on per form in the editor, never from markup.
Example
A complete minimal page:
[site]
title: Harbor
description: A waitlist
[nav]
Pricing -> /pricing
btn: Join -> /#waitlist
[Home -> /]
/// hero
h1: Launch the waitlist tonight
p: Edit this file. Publish. Collect email.
button: Join the list -> /#waitlist
/// section
form: waitlist
input: Email*
submit: Get early access
What not to do
- Don't invent element names or section types — stick to the vocabulary above.
- Don't use inline colors; configure color via
colors.primaryandbg:modifiers. - Avoid
/// htmlunless you actually need raw HTML. - Don't wrap the whole file in Markdown code fences when saving it.
- Don't emit React, Tailwind class soup, or custom components.
Further reading
- Your First Page — a gentler walkthrough
- Components & Aliases — the full element reference
- Designing markup for AI agents — why the grammar is shaped this way