Pandoc Pack

Convert Markdown to ASW-styled HTML — task lists, callouts, and wikilinks become data-attributes automatically.

The site-builder story

ASW is not just a CSS file you link. It is a complete pipeline: an agent writes Markdown, the pandoc pack converts it to HTML, and the output is a fully styled page using ASW semantics — with zero classes required, zero manual HTML authoring.

content/note.md  ──(pandoc + asw.lua + asw.html5)──▶  docs/note.html

The pack is what makes the vault a CMS. Write in Obsidian, publish with ./build.sh site.

Semantic mapping

The Lua filter converts GFM Markdown constructs to ASW data-attribute HTML:

Markdown ASW output
- [ ] task <li data-task="todo">task</li>
- [x] done <li data-task="done">done</li>
> [!NOTE] <div data-callout="note">
> [!WARNING] <div data-callout="warning">
> [!TIP] <div data-callout="tip">
> [!ERROR] <div data-callout="error">
[[target]] <a data-wikilink href="#target">target</a>
[[target|label]] <a data-wikilink href="#target">label</a>

Callout aliases: [!CAUTION] → warning, [!IMPORTANT] / [!INFO] → note, [!DANGER] → error.

Task lists

- [x] Build the CSS framework
- [x] Wire pandoc pack into build.sh
- [ ] Write the docs
- [ ] Publish to npm

Callouts

> [!NOTE]
> The pack requires pandoc 3.x. Earlier versions may handle GFM differently.

> [!WARNING]
> Wikilinks generate `href="#slug"` anchors. Link resolution is a build-time concern — the pack does not validate whether the target exists.

Note

The pack requires pandoc 3.x. Earlier versions may handle GFM differently.

Warning

Wikilinks generate href="#slug" anchors. Link resolution is a build-time concern — the pack does not validate whether the target exists.

See [[philosophy]] for why ASW chose this approach.
The [[pandoc pack|pack]] converts vault notes to web pages.

See philosophy for why ASW chose this approach. The pack converts vault notes to web pages.

Frontmatter → page metadata

YAML frontmatter maps to page-level properties via the asw.html5 template:

---
title: "Session Report — 2026-04-02"
description: "Summary of what happened"
layout: prose          # → data-layout on <main> (default: prose)
status: done           # → data-status badge in header
date: 2026-04-02       # → <time datetime="...">
section: "Sessions"    # → eyebrow text above <h1>
tags:
  - session
  - autonomous
# Agent authorship (optional):
agent: vigilio
model: claude-sonnet-4-6
mode: autonomous       # → <span data-mode="autonomous">
session: 10
---

Unset keys produce no output — no empty elements in the rendered HTML.

Command-line usage

Standalone, without build.sh:

pandoc input.md \
  --from gfm+yaml_metadata_block \
  --lua-filter packs/pandoc/asw.lua \
  --template packs/pandoc/asw.html5 \
  --to html5 \
  -o output.html

The +yaml_metadata_block extension enables YAML frontmatter parsing.

With build.sh

build.sh site processes content/docs/**/*.md and content/examples/**/*.md automatically. The template is selected from the frontmatter template: field (default: page).

./build.sh site    # compile all content/ → docs/
./build.sh all     # CSS + site in one pass
./build.sh watch   # rebuild on file change (requires inotify-tools)

Source lives in content/. Built output lands in docs/. Never edit docs/*.html directly — edits will be overwritten on the next build.

Files

packs/pandoc/
├── asw.lua      Lua filter — task lists, callouts, wikilinks
├── asw.html5    Pandoc HTML5 template — page structure, frontmatter vars
└── README.md    Reference documentation

The vault-as-CMS model

The pandoc pack is what enables the vault-as-CMS workflow:

  1. Agent writes a note in ~/.napkin/knowledge/ — standard Markdown with wikilinks, tasks, callouts
  2. The note is synced or copied to content/docs/
  3. build.sh site converts it to a styled HTML page
  4. nginx serves it from docs/

No CMS. No database. No admin interface. The vault IS the content management system. The pack is the bridge between how agents write and how the web renders.

Tip

The pandoc pack is what makes the zero-class rule achievable at the writing level. An agent writing Markdown never needs to think about data-task, data-callout, or data-wikilink. It writes naturally; the pack handles the translation.