Rules and almanac: a Zensical site and a Pandoc PDF¶
Exercise zensical-site-pandoc-pdf-annex.pdf · PDF
It is your turn in a board game, and you want to build a road. Which booklet do you open? The rules: how do I do this? Now somebody plays a card and you all argue about what exactly it allows. Which one now? The almanac: what exactly is this? Two questions, two documents.
Your app needs the same pair. A user manual answers "how do I...?". A reference guide answers "what is...?". Mix them and the page answers neither. On this page you write both in Markdown, publish them as a website, and turn the same text into a PDF without copying a single line.
What you will learn
- Create a documentation site with
zensical new,zensical serveandzensical build - Control the menu with the
navofzensical.toml - Tell a user manual from a reference guide and write a page of each
- Write steps a stranger can follow
- Generate a PDF from the same Markdown with Pandoc and Typst
- The trap: why a tip box that looks perfect on the site turns into
!!!in the PDF
Get the tools¶
You need three commands working. Zensical is a Python program, so it needs Python 3.11 or later, installed inside a virtual environment: a private folder of Python packages for this project.
Pandoc comes from the installer at pandoc.org/installing.html. Typst is already on your PC from Unit 6. Check all three:
A site in three commands¶
Go to the root of your project, next to package.json:
zensical new . # creates zensical.toml, docs/index.md and docs/markdown.md
zensical serve # preview at http://localhost:8000, reloads on save
zensical build # writes the finished site into site/
zensical new also creates .github/workflows/docs.yml, a ready-made recipe for publishing on GitHub Pages. Delete it if you do not publish there.
A clean build ends with the words No issues found. Add site/ to your .gitignore: it is output, just like build/.
Careful: this is not your app's website
It is a separate site that lives in the same repository. npm run dev serves the app on port 5173. zensical serve serves the documentation on port 8000. Different audiences, different tools, same commit. Zensical has nothing to do with npm, and both can share a folder.
Also, zensical serve publishes nothing: it is a preview on your PC. zensical build produces site/, and that folder is what gets published.
The menu is your map¶
Open zensical.toml. It is long and full of comments, but only two settings matter now: site_name, and nav, the menu. Replace the generated nav with the docs map you drew, one line per card:
[project]
site_name = "NoteBox docs"
nav = [
{ "Home" = "index.md" },
{ "User manual" = "user-manual.md" },
{ "Reference guide" = "reference.md" },
]
Create the two empty files in docs/, save, and watch the menu appear. A page missing from nav does not appear in the menu.
Keep docs/markdown.md open for now: it is a generated cheat sheet of everything the theme can do, such as admonitions, tabs and diagrams. Before you hand in, remove it from nav and delete the file. Leaving it out of nav only hides it from the menu: Zensical still builds the page into site/.
Manual or reference?¶
| User manual (the rules) | Reference guide (the almanac) | |
|---|---|---|
| Answers | "How do I...?" | "What is...? What does it accept?" |
| Organised by | Task: one section per thing the user wants to do | Screen: every control, in the order they appear |
| Read | From the first step to the last, while doing it | One row, then closed again |
| Written as | Numbered steps in the imperative: "Press Add." | Tables: control, type, values, default, effect |
| Complete? | No: only the tasks people really do | Yes: every control, even the obvious ones |
This split comes from Diátaxis, a documentation framework by Daniele Procida. It calls the first kind of page a how-to guide (task-oriented) and the second reference (information-oriented).
Writing a manual page¶
A manual page has six parts. Each one has a rule:
- The title is the task. What did the reader type into the search box to get here? "Export a report as PDF", not "Reports".
- One sentence of purpose. What the reader gets. No history, no architecture.
- Numbered steps, one action each. If a step has "and then", it is two steps. Use the imperative, and use the words on the screen: if the button says Add, the manual says Add, in bold, not "the create button".
- End with what you should see. "Then it works" is not something anybody can see. A step list with no result is a recipe with no photo.
- Pictures only where words are slower. Each one has a caption and a file name that says what it shows. Never write "the picture above": it breaks when the page is printed or reordered.
- "If something goes wrong". The problem the reader sees, and what to do.
Here is a task from the NoteBox manual:
## Delete a note, and get it back
Remove a note you no longer need. You have a few seconds to change your mind.
1. Press the cross on the note's row. The note disappears at once.
2. A bar appears at the bottom: *"Shopping list" deleted · Undo*.
3. Press **Undo** to get the note back.
The bar stays for 6 seconds. After that the note cannot be recovered.
Do not write from memory. Do the task in the app, one click at a time, and write each click. The step you forget is the one the user gets stuck on. And ban "simply", "obviously" and "very easy". They help nobody, and they insult the person who is stuck.
Writing a reference page¶
One screen, complete. One row per control, with the same five columns every time. Icons count. Messages count. Here is the Settings screen of NoteBox:
| Control | Type | Values | Default | What it does |
|---|---|---|---|---|
| Sort notes by | List | Last change · Title | Last change | Order of the note list. Pinned notes always come first. |
| Show tags in the list | Checkbox | On · Off | On | Shows the tags under each title. |
| Seconds the Undo bar stays visible | Number | 3 to 30 | 6 | Time you have to undo a delete. |
| Export backup | Button | — | — | Downloads notebox-backup.json with all notes and settings. |
| Import backup | Button | A backup file | — | Replaces all current notes with the file's. |
| Delete all data | Button | — | — | Deletes everything and restores the two example notes. |
Is a control too obvious to include? Obvious to whom? The reference is the one place that must be complete. And keep explanations out of the manual's steps: the user with a task does not care that your app uses localStorage. Move that here, or delete it.
The same text, as a PDF¶
Who still needs a PDF? The client who wants "the manual" attached to the delivery. The administrator in a server room with no internet. The person who prints. Pandoc converts your Markdown and Typst typesets it:
flowchart LR
M["<b>user-manual.md</b><br>the source"] --> P["<b>Pandoc</b><br>converts it to Typst"]
P --> T["<b>Typst</b><br>typesets the pages"]
T --> F["<b>user-manual.pdf</b><br>one file to attach"]
Give the page one # heading for its title and use ## for each task. Then, from the project root:
mkdir manual
cd docs
pandoc user-manual.md -o ../manual/user-manual.pdf --pdf-engine=typst --shift-heading-level-by=-1 -V mainfont="Libertinus Serif" -V papersize=a4 -V section-numbering=1.1 --toc
Open the PDF. It is your Markdown, typeset: title, table of contents, numbered sections, lists and tables. Every option has a job:
| Option | What it does |
|---|---|
--pdf-engine=typst |
Makes the PDF with Typst |
--shift-heading-level-by=-1 |
Moves every heading up one level. Your # becomes the document's title, and each ## becomes a section numbered 1, 2, 3 |
-V mainfont="Libertinus Serif" |
Sets the text font. Some Pandoc versions fail without it, with font fallback list must not be empty. This font is embedded in Typst, so it exists on every PC |
-V papersize=a4 |
A4 instead of US Letter |
-V section-numbering=1.1 |
Numbers the sections |
--toc |
Adds a table of contents built from your headings |
Careful: -N depends on your Pandoc
Pandoc's own switch for numbering is -N. With a recent version (3.13) it works in Typst. With an older one (3.7) it silently does nothing. -V section-numbering=1.1 works in both, so use that.
Two traps with paths¶
Run Pandoc from inside docs/. Run it from the project root on a page with an image and you get file not found: Typst looks for assets/... starting from where you ran the command. That is why the command starts with cd docs.
Create the output folder. Pandoc 3.7 fails with does not exist when manual/ is missing. Pandoc 3.13 creates it for you. mkdir manual is safe either way, once.
What does not survive the trip¶
Add a tip box and a diagram to your page, then rebuild:
On the site they look perfect. In the PDF, the tip is a plain paragraph starting with !!! tip, its text is a code block, and the diagram is its source code. Pandoc reads standard Markdown. Admonitions, tabs, icons and Mermaid are Zensical's extensions.
| Survives the trip | Stays on the site |
|---|---|
| Headings, lists, tables | Admonitions (!!!) |
| Images, links | Content tabs (===) |
| Code blocks | Icons, Mermaid diagrams |
Careful: a single source still needs thought
It means you choose, page by page. A page that must also be a PDF is written in portable Markdown: a tip becomes a sentence starting with Careful:. A tutorial that is web-only on your map can use everything Zensical offers.
A table too wide for the page is a different problem with the same answer: fewer columns, shorter cells. It was too wide for the reader as well.
Save the commands¶
Nobody should have to remember that line. Put both commands in package.json. Inside a JSON string, the inner quotes are written \":
"scripts": {
"docs:site": "zensical build --clean",
"docs:pdf": "cd docs && pandoc user-manual.md -o ../manual/user-manual.pdf --pdf-engine=typst --shift-heading-level-by=-1 -V mainfont=\"Libertinus Serif\" -V papersize=a4 -V section-numbering=1.1 --toc"
}
Keep the other scripts your project already has. Now npm run docs:site builds the site and npm run docs:pdf builds the PDF.
Two extensions when you are ready:
- Several files, one PDF. Pandoc takes them in order:
pandoc user-manual.md reference.md -o ../manual/manual.pdf, plus the same options. With the shift, only the first file's#becomes the title. The others turn into a plain line, so remove them from the PDF's source or accept it. - Your own styling. Replace
-o ../manual/user-manual.pdf --pdf-engine=typstwith-s -o manual.typto get the Typst source, then style it as you did in Unit 6.
The PDF is one output, never the source. Nobody edits it: correct the Markdown and rebuild.
The stranger test¶
You cannot judge your own steps. You know the app too well to notice what is missing. So borrow a stranger:
- Your partner sits at your app with your PDF open. Not the site: no searching.
- They do one task from your manual. They do exactly what it says and nothing it does not say.
- You watch. You may not speak or point.
- Each time they stop, hesitate or do something else, write down the step number.
- Fix the worst step.
Watching somebody fail on a step you thought was obvious teaches more than any rule on this page. That is why "obviously" has no place in a manual.
Key takeaways¶
zensical new .,zensical serveandzensical buildcreate, preview and build a site.navinzensical.tomlis your menu.- A user manual is organised by task and read in order. A reference guide is organised by screen and looked up one row at a time.
- Manual steps carry one action each, use the words on the screen, and end with what you should see.
- Pandoc + Typst turn the same Markdown into a PDF. Run Pandoc from inside
docs/. - Pandoc reads standard Markdown: admonitions, tabs, icons and Mermaid do not reach the PDF.
- The stranger test finds the steps you cannot see for yourself.
Quick check¶
1. Which command writes the finished website into the site/ folder?
-
zensical build -
zensical serve -
zensical new . -
pandoc --toc
zensical build produces site/, the folder that gets published. zensical serve only previews on your PC at localhost:8000, and zensical new . creates the project.
2. You add docs/faq.md but it does not show in the site's menu. What is the most likely reason?
- The page is not listed in
nav - The file needs a
.htmlextension - The site must run on port 5173
- The page has no images in it
When zensical.toml has a nav, it decides the menu. Add { "FAQ" = "faq.md" } to it. The same setting is also why taking a page out of nav hides it from the menu without removing the page from site/.
3. Which reader is a reference guide written for?
- Someone looking up exactly what one control accepts
- Someone following a task from start to finish
- Someone trying the app for the very first time
- Someone deciding whether to buy the application
A reference guide is the almanac: organised by screen, complete, and read one row at a time. Following a task from start to finish is what the user manual is for.
4. Which step follows the rules for a manual page?
- Press Add. The new note appears in the list.
- The note can be created by the user with the button.
- Fill in the form and then save it and open the list.
- Obviously, simply click on the create button below.
A good step is an imperative with one action, uses the exact label on the screen, and says what you should see. The others are passive, hide several actions, or use an invented name.
5. You run Pandoc from the project root and it stops with file not found for an image at assets/editor.png. What do you do?
- Run the command from inside the
docs/folder - Convert the image from PNG into a JPEG file
- Add the image to the
navofzensical.toml - Rebuild the website before you run Pandoc
Typst looks for the image starting from where you ran the command. The path assets/editor.png is relative to docs/, so cd docs first.
6. A page has a !!! warning box and it must also be delivered as a PDF. What is the right fix?
- Rewrite the box as a plain sentence starting with Careful:
- Keep the box and add
--tocto the Pandoc command - Edit the generated PDF by hand after each build
- Keep two copies of the page, one for each format
Admonitions are a Zensical extension, so Pandoc does not understand them. On a page that goes to PDF, write portable Markdown. Editing the PDF or keeping two copies destroys the single source.
7. You test your manual on a partner. They stop at step 4 and look at you. What should you do?
- Say nothing and write down the number of that step
- Point at the right button on the screen for them
- Explain what you really meant by that step
- Skip that step and move straight to step 5
In the stranger test the author stays silent. The hesitation is the result you came for: it marks the step to rewrite. Any help from you hides the problem.
8. A cinema app's manual has a page called \"Tickets screen\" that lists each field, its allowed values and its default. How would you classify that page?
- A reference page, organised by screen and complete
- A user-manual page, organised by the reader's tasks
- A tutorial, built around one guided example
- An administration page, about keeping the app alive
It is organised by screen and describes every control, so it is a reference page. A manual page for the same screen would be titled with a task, such as "Buy a ticket for tonight", and made of numbered steps.
Your manual still has holes where the pictures should go, and your app still explains nothing on its own screens. The next lesson, Context help and screenshots, fixes both.