1. Introduction
CompMD is Markdown with components. A writer puts a box, a chart or an input in a document with a line of its own, and the document still reads well as text, on GitHub or in any Markdown viewer. Your application renders it as a page.
---
read: 12
pages: 3480
md:
inputs:
goal: number = 20
---
::: grid {min=12rem gap=m}
::: box {padding=m border=subtle border-radius=m}
**{{md.doc.read}}** books read this year
::: /box
::: box {padding=m border=subtle border-radius=m}
**:value[3,480]{of=(md.number(md.doc.pages, 0))}** pages
::: /box
::: /grid
:: number-input[Goal: 20 books] {bind=goal}
This guide is for developers who put CompMD in an application: a notes app, a documentation site, a dashboard whose pages people write, an editor with a live preview. It shows how to render documents, give them components of your own and from packs, and write packs others can use. How to write the documents themselves is the Author's Guide.
What CompMD gives your application#
- Documents your users write as text. Markdown, which they know, with components, data, inputs and layout, which they can learn a line at a time. A document is a file they own: it diffs, it merges, it reads in any editor.
- Pages you control. The look of a page is yours: its stylesheet, its tokens, its components. The document says what is on the page; your application says how it looks.
- Documents from anyone, safe to open. Components written in CompMD run no code. Components written in JavaScript, React or Svelte run in a sandbox that sees only its own params, with no network, no storage and no way out of its box. A document from a stranger can't reach your page, your session or your data.
- Diagnostics with fixes. Every mistake has a code, a place and, where one is clear, the edit that fixes it; an editor can show them as the writer types, with hints at the caret.
The packages#
| Package | What it does |
|---|---|
@compmd/processor |
Reads a document, with everything it needs, and gives its trees, its diagnostics and its components. The processor in Rust, as WebAssembly. |
@compmd/render |
Renders the expanded tree as a live page, and updates it in place as the document changes. |
@compmd/sandbox |
Runs components at the trust their pack is given: in frames with no network, or your own in your page. |
@compmd/vite |
Reads compmd.config.json, gives the processor your packs, and serves the sandbox and the packs' files from your app. |
@compmd/registry |
Gets the packs a document imports that your app doesn't install, from npm or another registry, checked against their integrity. |
@compmd/devtools |
The Developer Tools: a document's text, its page and what the processor and the sandbox make of it, as a part a page embeds. |
@compmd/pack |
compmd-pack, which builds a pack, checks it before it is published, runs its tests and serves its test page. |
@compmd/create-pack |
Writes a new pack: a component as one built module, its signature, and a test page. |
An app that shows documents uses the first four, and @compmd/registry when it fetches packs it doesn't install (chapter 9). The quick start installs @compmd/processor, @compmd/sandbox and @compmd/vite; @compmd/render comes with the sandbox. The last two are for writing packs, in Part IV.
A document goes through them like this:
notes.comp.md ──► @compmd/processor ──► expanded tree ──► @compmd/sandbox ──► the page
▲ + components └ @compmd/render
│
@compmd/vite: your packs, compmd.config.json, the sandbox's files
The processor does no I/O of its own: your application gives it the document, the files it reads, its packs and its data, and gets back everything the page needs. That's what lets the same processor run in a browser, in a worker, in a build, or natively in Rust.
Words this guide uses#
| Word | Means |
|---|---|
| document | a CompMD file, .comp.md, or any Markdown file with an md key in its frontmatter |
| frontmatter | the YAML between --- lines at the top: CompMD's settings under md, the author's own values beside them |
| component | a named piece of a page: a container (::: box … ::: /box), a leaf (:: chart[…] {…}) or an inline one (:value[…]{…}) |
| params | a component's settings, in braces: {padding=m} |
| fallback | what shows where a component can't: a leaf's or inline component's text in brackets, a container's body |
| signature | the params and slots a component takes, which the processor checks every use against |
| pack | a document that exports components, published on npm or kept in a folder of your app |
| expanded tree | the processor's result: the document's content, with every value computed, ready to render |
| diagnostic | a mistake the processor found, with a code (F… an error, W… a warning), a place and a message |
| host | your application: what gives the processor its request and shows the page |
| trust level | how far a pack's code is trusted: strict, permissive or trusted, set by your configuration (chapter 3) |
The glossary has the rest, linked to the spec.
How to read this guide#
Part I gets you from nothing to a page in a few minutes, then explains what runs where. The parts after it each take one side of building with CompMD, and can be read in any order. Each chapter's code is a working example in examples/, and a document with a Try it link opens in the playground, where you can change it and watch the page.
Next: the quick start.