Skip to content

Write, build, check, and ship

Content formats, frontmatter, site checks, packaging, documentation maintenance, and troubleshooting.

Browse Docs pages

First install and initialize Rotkeeper. Run the commands below from the repository root. Paths use the default crypt layout; bash rotkeeper.sh status shows the active paths for other layouts.

Write content

Create a new page, then edit the source file:

bash rotkeeper.sh new notes.md --subdir journal --title "Notes" --tags "journal,example"

This creates home/content/journal/notes.md. Bare filenames get .md. Nested filenames and --subdir must stay inside the content root.

Frontmatter and Markdown

---
title: "Notes"
description: "A short summary."
template: rotkeeper-doc.html
tags:
  - journal
---

# Notes

Write a paragraph, then link to [another page](../my-page.md).

Oliver renders the body and the template wraps it. Internal .md, .textile, and .cook links become .html. A source's directory and basename determine its output path; slug does not move it. template overrides the site default. Sidecar frontmatter wins over source frontmatter. Use CommonMark headings, lists, links, and fenced code. Oliver supports pipe tables; do not assume every extension from another Markdown renderer is supported.

Textile and Cooklang

bash rotkeeper.sh new notes.textile --subdir journal --title "Textile notes"
bash rotkeeper.sh new soup.cook --subdir recipes --title "Soup"

A .textile file always selects Textile; a .cook file always selects Cooklang. A .md file uses the site's input_format, which defaults to Markdown. Keep different basenames in the same directory: notes.md and notes.textile both map to notes.html and cause a collision.

See the Textile guide for syntax. A Cooklang source may contain Add @water{250%ml} to a #pot{}. Heat for ~{5%minutes}. The new-source scaffold supplies a sample recipe that you can replace. Cooklang recipes may keep the title in frontmatter rather than a Markdown heading. The Oliver contract defines all three input formats.

Sidecars

bash rotkeeper.sh new notes.md --subdir journal --soul also creates bones/meta/journal/notes.soul.md if it is absent. Use a new filename when trying this example if journal/notes.md already exists.

The scaffold's null review fields and unfinished notes are not reviewed documentation. Replace the notes and record the review date and version. The lookup path is content-relative; target_file inside the sidecar is repository-relative. Directory sidecars describe sections, while core-file sidecars feed DIP references. See the sidecar contract before adding or changing one.

Choose a theme

List templates with bash rotkeeper.sh new --list. Choose a per-page template, or change theme_registry.default in bones/config/rotkeeper.yaml for the site. The theme guide covers palettes and the theme development guide covers wrappers and CSS.

bash rotkeeper.sh showcase
bash rotkeeper.sh render

Showcase generates comparison sources, which render like other content. The XHTML guide explains how to pair render_profile: xhtml with an XHTML-compatible wrapper.

Build and check

bash rotkeeper.sh preflight
bash rotkeeper.sh glue --dry-run
bash rotkeeper.sh glue
bash rotkeeper.sh render
bash rotkeeper.sh links
bash rotkeeper.sh a11y
bash rotkeeper.sh scan
bash rotkeeper.sh status

render --dry-run previews output changes. Most dry-runs still create bootstrap logs. Consult each command reference for supported flags and exceptions.

To omit product documentation from your own site, set render_system_docs: false in bones/config/rotkeeper.yaml. It excludes Docs, Help, and messages/. Replace the repository homepage and remove links to those omitted pages before disabling them.

Archive the site

bash rotkeeper.sh pack --dry-run
bash rotkeeper.sh pack

Default packing archives the generated site, embeds metadata.json, and exports Markdown sources to JSON under bones/archive/. Archive names contain a timestamp and random tag, not the framework version. pack --content archives sources but excludes help/; pack --self bundles the system, sources, and output. Neither mode deploys a website. Do not publish source exports unintentionally.

Use the publishing guide to upload the generated output directory. Do not commit or hand-edit output/.

Package a framework release

Site publication does not require a version bump or framework release. For an intentional framework release:

bash rotkeeper.sh test
bash rotkeeper.sh bump --patch -m "Describe the release" --dry-run

Review the preview. When ready, run the same bump without --dry-run, then bash rotkeeper.sh release. bump requires exactly one version selector and a message. It updates bones/config/version, CHANGELOG, and the build log. --commit is optional and can stage unrelated work, so do not use it without reviewing the tree.

release builds bones/archive/releases/rotkeeper-VERSION.zip. It validates the distribution's root allowlist, required files, exclusions, and embedded release manifest. This distributes Rotkeeper, not just your rendered site.

Maintain documentation

bash rotkeeper.sh book --fsbook
bash rotkeeper.sh autopsy --all
bash rotkeeper.sh dip --dry-run
bash rotkeeper.sh dip
bash rotkeeper.sh render
bash rotkeeper.sh links

The filesystem book supplies DIP's core inventory. Autopsy reads static help and output annotations. DIP rebuilds owned references, refreshes the marked command index, and reports missing sections, placeholders, sidecar coverage, and ownership. Fix generated reference information in the script or sidecar, not the rendered page.

Task guides declare doc_type: guide and a reviewed: YYYY-MM-DD date. They have no core target_file and remain author-owned. DIP reports them separately, including missing/older review dates and unfinished prose; it does not require command-reference sections or suppress their findings. Review a guide whenever its instructions change.

Enforced site gates

bash rotkeeper.sh test --site

This builds the current checkout through preflight, book --fsbook, autopsy --all, dip, and render, then checks:

  1. No unfinished placeholder text in rendered Help or Docs, including code examples.
  2. No broken local links, fragments, or assets anywhere in the rendered site.
  3. Every stylesheet used by Help or Docs has a passing static accessibility audit.
  4. Every non-exempt DIP target has an existing sidecar, with no unreachable sidecars.
  5. Every script-backed dispatcher command, including aliases, has a generated reference and a link in the marked, generated Docs command index. Manual command rows outside that block fail.
  6. Every Help and Docs source is rendered; each rendered page has exactly one H1 and a nav landmark. Missing or disabled documentation fails.

Help and Docs are the product-documentation scope, recursively, including directory indexes, authored guides, references, Textile pages, and the DIP matrix. Other site content is outside the page-structure and placeholder checks, but not the whole-site link check. DIP exceptions apply to reference and sidecar generation only; they do not exempt a rendered page from checks. Both core-reference rows and the separate authored-guide report are consumed. Guides must be reviewed and placeholder-free; missing generation inputs or ambiguous ownership also fail.

The full test runs these same gates on a disposable copy of the tracked working site, plus negative regressions for each gate. test --site checks the actual output artifact in the current checkout. CI and the publishing workflow both enforce this mode before accepting or uploading that output. There is no warn-only switch. Neither mode publishes content.

DIP's aggregate Stub, Stale, and Unowned counts are not interchangeable with site defects. The gate prints section gaps, unowned paths, staleness, and authored-guide states rather than silently dropping them. The inherited 19 stub rows include template pages still marked status: stub despite populated sections, missing overview sections for .agentignore and the version file, internal libraries without CLI help, and scripts with no annotated side effects. These are not missing sidecars or rendered placeholders. Six unowned pages are four fixture directory indexes, daisyui-map.md, and textile-showcase.textile, not orphaned sidecars. Git staleness is a review signal; it is unknown in copies without history. The gates independently check actual sidecar files, command-reference contracts/usage, rendered text, structure, links, and audited stylesheets.

Optional binders include book --docbook, book --scriptbook-full, and book --configbook. They write retrieval aids under bones/book-reports/, not authoritative policy or files to deploy.

To extend the CLI, follow the command development guide and contribution rules. Configuration shapes are in the schema reference.

Troubleshoot

Message or symptom What to check
Missing required dependency Install the named tool. Confirm mikefarah yq v4, GNU gawk, and Bash 4+ are on PATH.
Oliver missing or rendering fails before page discovery Run preflight; fix PATH or RK_OLIVER_BIN, then rerun it.
YAML configuration is malformed Validate bones/config/rotkeeper.yaml with yq eval '.'; repair YAML rather than removing validation.
Cached paths do not match the current repository Run init to rewrite path mappings. Do not copy a serialized paths block from another checkout.
File already exists Edit that source, or choose another filename. new does not overwrite it.
Source basename collision Keep only one source format for a directory/basename pair.
RawHtmlNotXmlWellFormed Remove incompatible raw HTML or use the HTML profile with an HTML wrapper.
No templates found Provide templates in the active layout's template directory.
Broken links Repair the source link or create the intended target, render again, then rerun links.
realpath: illegal option -- m on macOS Install Homebrew coreutils and put its libexec/gnubin directory on PATH. Do not weaken canonical-path checks.
Site returns 200 but deployment's uploaded-byte check fails Ensure the host does not inject analytics or otherwise rewrite HTML. This repository disables Cloudflare RUM only for rot.filed.fyi.

Release-day checklist

On a fresh checkout, follow installation, run preflight, init, new, render, links, pack, and the publishing steps. Then run the full test harness and inspect/extract the framework release if that is the intended deliverable. The separate site-level quality work records this clean-clone walkthrough; the checklist alone is not evidence that it passed.

Back to: Help ยท Command reference