Start editing¶
This page covers the day-to-day cycle of working on your document: previewing your changes locally, syncing them to GitLab or GitHub, viewing the published website, building the PDF, working with branches and issues, troubleshooting common problems, and finally releasing your report. It assumes no prior experience with the command line, Git, or software development - each step includes the exact commands to type. For one-time setup (installing Python, Git, and Zensical itself), see Install tooling first if you haven't already.
Viewing documentation locally¶
Zensical renders your Markdown into a live, locally hosted website as you write, without you needing to push anything - so you can check headings, links, images, diagrams, and PDF-only/web-only content render correctly before anyone else sees them.
Open a terminal¶
A terminal (also called a command line, console, or shell) is a text-based way to give your computer instructions by typing commands, instead of clicking buttons. It can look intimidating at first, but this whole workflow only needs a handful of commands, and they're all given below.
The easiest way to open one is Visual Studio Code's own integrated terminal:
- Open your project folder in Visual Studio Code, if it isn't already open (File > Open Folder...).
- Open the integrated terminal, whichever way is quickest for you:
- Menu: View > Terminal.
- Keyboard shortcut:
Ctrl+`on Windows/Linux,Cmd+`on macOS. - Command Palette (
Ctrl+Shift+P/Cmd+Shift+P) > View: Toggle Terminal.
- A panel opens at the bottom of the window, already sitting in your project folder - defaulting to PowerShell on Windows, or your shell of choice (bash/zsh) on macOS and Linux.
This integrated terminal also activates your Python virtual environment automatically (a self-contained folder holding just this project's Python packages, kept separate from everything else on your computer), as long as you've selected the .venv interpreter once - see Install Python and Zensical. That's the recommended path, since it needs no further steps below.
If you'd rather use your system's own terminal application instead of Visual Studio Code's, you need to navigate to your project folder and activate the virtual environment yourself:
-
Activate the virtual environment manually
- Open a terminal application: press
Cmd+Spaceto open Spotlight, typeTerminal, and pressEnter. -
Navigate to your project folder using the
cd(change directory) command - replace the path below with wherever you cloned your project: -
Activate the virtual environment:
Your prompt now starts with
(.venv), confirming it's active.
- Open PowerShell: press the
Windowskey, typePowerShell, and pressEnter. -
Navigate to your project folder using the
cdcommand: -
Activate the virtual environment:
Your prompt now starts with
(.venv), confirming it's active.
- Open a terminal application: look for Terminal in your applications menu.
-
Navigate to your project folder using the
cd(change directory) command - replace the path below with wherever you cloned your project: -
Activate the virtual environment:
Your prompt now starts with
(.venv), confirming it's active.
- Open a terminal application: press
Start the preview server¶
-
In your terminal (with the virtual environment active), start the local preview server:
-
Wait for it to finish starting - you'll see some log messages ending with a local web address.
- Open that address (typically http://127.0.0.1:8000) in your browser to view your documentation.
Leave zensical serve running in its terminal while you write - it watches your files and automatically rebuilds and refreshes the browser whenever you save a change, so you don't need to restart it after every edit. To stop it, click back into its terminal and press Ctrl+C.
Tip
zensical serve only builds the website - it doesn't touch docs/site_documentation.pdf. See Build the PDF below to preview the PDF output.
Generate the Source and PDF documents¶
You may notice there is no Source or PDF document for download. The two buttons are on
the front page, but clicking either one gets you nothing - the documents they point at
are generated rather than stored, so a fresh clone doesn't have them yet. They are also
deliberately excluded from Git (see .gitignore), which keeps large binary files out of
your repository and stops every rebuild showing up as a change.
You can generate these two documents by running the following commands:
prodockit pdf # the report itself
prodockit source-bundle # your Markdown content and zensical.toml, one file per page
prodockit pdf writes the report to docs/site_documentation.pdf, which the PDF
button already points at. prodockit source-bundle writes docs/source_bundle.pdf the
same way, which the Source button points at - both land directly in docs/, so
there's nothing to copy anywhere before the preview can serve them.
Only your Markdown and config, not your whole repository
prodockit source-bundle bundles every .md file plus zensical.toml - your
documentation's own source, not the template's build tooling. See
Source-code bundling if your submission needs
the whole repository bundled instead.
Refresh your browser and both buttons will work.
Re-run it after changes you want reflected
Neither document rebuilds itself as you write - unlike the website, which
zensical serve refreshes automatically. Run prodockit pdf again whenever you
want the PDF to catch up. See Build the PDF for more on the
command, including what it needs installed and how the automated builds use it.
Synchronise your updates¶
Whenever you've made a change you want to keep, there are three things to do: save the file, commit it (record a labelled snapshot of the change in your project's history), and push it (upload that snapshot to GitLab or GitHub, where it's backed up and, once it reaches your default branch, published). You can do all three either through Visual Studio Code's Source Control view, or by typing Git commands directly - both do exactly the same thing, so use whichever feels more comfortable.
-
Commit and push your changes
- Make sure you've saved your changed files (a filled circle next to a file name in the Explorer tab means it has unsaved changes - select the file and press
Ctrl+S/Cmd+S). -
Click the Source Control icon in the left-hand sidebar. You'll see a list of every changed and new file.
1. Initial commit
-
Type a short, descriptive message in the message box (for example, "Add section 2 draft") - this is the label future-you (or a marker) will see when looking back through the history.
-
Press the Commit button and select Save All and Commit Changes. This records the snapshot on your computer only - you haven't sent anything anywhere yet.
2. Commit changes
-
Press Sync Changes to push your commit to GitLab or GitHub (and pull down anyone else's changes too).
3. Sync changes
-
Check what's changed - this lists every file you've added, edited, or deleted since your last commit:
-
Stage the files you want to commit - "staging" means marking them so Git includes them in the next commit (use
git add .to stage everything shown bygit statusin one go): -
Commit the staged changes with a short, descriptive message:
This records the snapshot on your computer only - you haven't sent anything anywhere yet.
-
Push your commit to your GitLab or GitHub remote, uploading it so it's backed up and visible online:
- Make sure you've saved your changed files (a filled circle next to a file name in the Explorer tab means it has unsaved changes - select the file and press
Note
Commit little and often. Small, clearly described commits are easier to review, easier to revert if something goes wrong, and give you a much more useful history to look back on than one huge commit at the deadline.
Viewing online website¶
Once your commit reaches the default branch, the CI/CD pipeline rebuilds and republishes the website (and the PDF) automatically - there's nothing extra to trigger.
The first build takes longer than you'd expect
Every build installs the whole toolchain from scratch - Node.js, Chrome, Pandoc, the Python environment - so even a routine rebuild takes several minutes, and the very first one on a fresh project can easily run into the mid-teens. A blank page or a 404 on your first visit almost always means the build simply hasn't finished yet, not that something is broken.
Check first, rather than refreshing a page that hasn't been built yet: Build > Pipelines in the sidebar on GitLab, or the Actions tab on GitHub. A running pipeline or workflow shows a spinner or a yellow dot; wait for it to turn green.
-
Find your published site
The simplest way to find your site is from the project itself, rather than working out the URL by hand: open your project on the GitLab website and look for the GitLab Pages link, shown on the project overview page once Pages has deployed at least once (also always available under Deploy > Pages in the sidebar). Click it.
-
The first time you visit, GitLab prompts you to authorise GitLab Pages access to your project:
4. Authorise GitLab Pages
-
Your browser redirects to a URL with an extra, unique key added, such as https://prodockit-template-4f75ad.pages.surrey.ac.uk/. This confirms that you (specifically, someone with access to the underlying GitLab project) can view the page - GitLab Pages sites aren't public by default.
This works the same way on the University of Surrey GitLab and on gitlab.com or another self-hosted instance.
Working out the address yourself
If you'd rather not click through, most GitLab Pages addresses follow the form
https://namespace.gitlab.io/repository-name, though a self-hosted instance may use its own domain - check Settings > Pages on your project for the exact one.- Go to your GitHub Pages address, in the form
https://username.github.io/repository-name. This template's own site is at https://buckwem.github.io/prodockit-template. - Unlike GitLab Pages, GitHub Pages sites are publicly accessible by default, even when the source repository is private - so no separate authorisation step is normally needed to view a GitHub Pages site once it's built.
- If your organisation has restricted Pages visibility (available on GitHub Enterprise), GitHub will ask you to sign in with an account that has access to the repository before the site loads.
-
Build the PDF¶
docs/site_documentation.pdf isn't built by zensical serve or zensical build - it has its own build command, prodockit pdf, provided by the prodockit package on top of Zensical (see Customise PDF generation for how to customise its output, and Customise build for how the two builds fit together; this section just covers running it).
Building it manually¶
- Make sure you've installed the PDF build's dependencies - see Install Python and Zensical for
requirements.txt, and Additional tooling if your document uses Mermaid diagrams or maths and you need the optionaltools/mermaid/tools/mathjaxNode packages too. - Open a terminal with your virtual environment active, in your project's root directory.
-
Run the build command:
This can take a little while, especially the first time - it's converting every page into a single PDF, rendering any diagrams and maths along the way.
-
If your project wants a source bundle too - see Source-code bundling - build it with a second command:
This writes
docs/source_bundle.pdfdirectly - nothing to copy anywhere, and refreshing your browser is enough for the website's own Source download button to find it in your local preview. -
Once it finishes, open
docs/site_documentation.pdf(in thedocsfolder) to check the result - anddocs/source_bundle.pdf, if you built one.
Run this again after any change you want reflected in the PDF - it always rebuilds the whole document from scratch, so there's no separate "clean" step needed for it, unlike the website build below.
Automated builds¶
Both .gitlab-ci.yml and .github/workflows/docs.yml run this exact sequence automatically on every push to your default branch:
prodockit pdf runs first so docs/site_documentation.pdf exists before Zensical builds the site - that's what makes the "Download PDF" button on the cover page work, since the published website includes the PDF as part of itself. zensical build --clean --strict then builds the site into the public/ directory (set by site_dir in zensical.toml), which GitLab Pages or GitHub Pages then publishes. --strict turns validation warnings such as broken internal links or missing anchors into build failures, so a faulty site is not published. See Clean build in Troubleshooting if you need to force a fresh website build locally.
Managing branches and issues¶
Once you're comfortable with the basic commit-and-push cycle, branches and issues give you two extra tools for organising bigger or shared pieces of work: a branch isolates a change until it's ready, and an issue records what needs doing, with the two linked together.
Working with branches¶
A branch is a parallel, isolated copy of your files where you can work without affecting the "real", published version until you're ready. For anything more than a small tweak - a new section, a bigger restructure - it's worth developing it on its own branch rather than directly on your default branch (usually main). That keeps main (and therefore the published website and PDF) stable while you're mid-change, and makes an unfinished idea easy to abandon without cleaning up half-done edits.
-
Create a new branch
- Click the branch name in the bottom-left of the status bar (it normally reads
main). - Select Create new branch... and give it a short, descriptive name (for example,
add-section-3). - Visual Studio Code switches you onto the new branch. Edit, save, and commit as usual (see Synchronise your updates) - your commits go onto this branch, not
main. - The first time you press Sync Changes, Visual Studio Code offers to Publish Branch instead - accept this to push the new branch to GitLab or GitHub.
-
Create and switch to a new branch in one step:
-
Commit as usual (see Synchronise your updates) - your commits go onto this branch, not
main. -
Push it, telling Git to track this new branch on the remote the first time:
After that first push, a plain
git pushis enough.
- Click the branch name in the bottom-left of the status bar (it normally reads
Merging your branch back¶
Once you're happy with the branch, bring it into your default branch so it's published.
-
Merge your branch
- Open your project on GitLab or GitHub in a browser.
- Open a merge request (GitLab) or pull request (GitHub) from your branch into
main- both platforms show a prompt for this as soon as you push a new branch, or you can start one from the Merge requests/Pull requests section of the sidebar. - This gives you, or a collaborator, a chance to review the diff before it goes live.
- Once you're happy, click the Merge button on the merge/pull request page - GitLab or GitHub does the rest.
Either way, once the merge reaches main, the CI/CD pipeline rebuilds and republishes the website and PDF automatically, the same as any other push to main.
Tip
Delete the branch once you've merged it - neither GitLab nor GitHub need it anymore, and it keeps your branch list tidy. Both offer a Delete branch button right after you merge a merge request or pull request.
Recording issues and linking them to a branch¶
Issues are GitLab's and GitHub's built-in way to track things to do - a missing section, a diagram to add, a typo to fix - separately from the writing itself. They're especially useful once more than one person is working on the same report, or if you just want a running to-do list attached to the project instead of a separate document.
- Open the Issues section in the left-hand sidebar of your project on the website, and select New issue.
- Give it a short title (for example, "Add diagram to section 2") and, optionally, a longer description of what's needed.
Both platforms let you create a branch directly from an issue, which links the two together from the start:
- On GitLab, open the issue and use the Create merge request button (or the dropdown next to it, for Create branch only). This creates a branch named after the issue (for example
12-add-diagram-to-section-2) and links it back to the issue automatically. - On GitHub, open the issue and, in the right-hand sidebar under Development, select Create a branch. This creates a branch linked to the issue, and offers to check it out for you.
If you've already created your branch by hand instead (see Working with branches), you can still link it to an issue by mentioning the issue number in a commit message:
Using Closes #12, Fixes #12, or Resolves #12 instead of just #12 - in the commit message, or in the merge/pull request description - automatically closes that issue as soon as the commit reaches your default branch.
Trouble shooting¶
Common problems you might hit while working on your document, and how to fix them.
prodockit or zensical is not recognized¶
prodockit : The term 'prodockit' is not recognized as the name of a cmdlet,
function, script file, or operable program.
Both commands are installed inside the virtual environment, not system-wide, so they only exist in a terminal where it is active. A new terminal window never has it - activation lasts for that window only.
-
Activate the virtual environment
The prompt gains a (.venv) prefix when it works. This bites most often after a step that told you to close and reopen your terminal to pick up a PATH change - the new window has lost the virtual environment as well.
If activating makes no difference, the virtual environment itself may be in the wrong place: .venv created somewhere other than your project folder still activates perfectly happily. pwd tells you where you are.
Local preview isn't updating¶
If you save a change and the browser doesn't refresh, or the page looks stuck:
- Do a hard refresh in the browser first (
Ctrl+Shift+Ron Windows/Linux,Cmd+Shift+Ron macOS) - this bypasses the browser's own cache, which is a more common culprit than Zensical itself. -
If that doesn't help, stop the server (
Ctrl+Cin its terminal) and start it again: -
Still stuck? Check the terminal
zensical serveis running in - a build error there (for example, invalid TOML inzensical.toml, or a broken link) stops it rebuilding, and it'll usually tell you exactly which file and line to look at.
Clean build¶
The --clean flag on zensical build --clean --strict deletes the previous contents of public/ before rebuilding, so pages you've since renamed or removed don't linger in the published site. --strict also makes validation warnings fail the build. Both CI pipelines use both flags.
To do the same locally - useful if the local public/ folder looks out of date or you suspect a stale file is causing an issue - delete it yourself first:
Numbered lists reset to "1."¶
If a numbered list in your Markdown restarts at "1." partway through instead of continuing (for example after a code block, admonition, or tab), it's almost always an indentation problem - Zensical (and Pandoc, for the PDF) only treat content as continuing the list item if it's indented to match. See Lists within lists for the exact rule to follow.
PDF build fails¶
If prodockit pdf errors out or produces a PDF missing content:
- Check the error message in the terminal - it usually names the file and the problem directly, and anything the underlying tool printed appears beneath it.
- Make sure you've installed the dependencies from
requirements.txtin your active virtual environment (see Install Python and Zensical). - If your document uses Mermaid diagrams or maths, make sure you've installed the optional Node tooling too (see Additional tooling) - without it, the build silently skips those elements rather than raising an error.
WeasyPrint cannot start (status 43)¶
A specific case of the above, worth its own entry because the number is the only clue and it points somewhere unexpected:
Building PDF from zensical.toml...
Error: pandoc exited with status 43 building 'docs/site_documentation.pdf' (only pass)
Status 43 means Pandoc ran perfectly well, then handed your document to WeasyPrint, which could not start. It is not a problem with your document. Nothing you write in Markdown causes it, and no amount of editing your content will clear it.
WeasyPrint is not a pure Python package. It draws every page through Pango and a few related graphics libraries, and pip install -r requirements.txt cannot install those - they belong to your operating system rather than to Python. If they are missing, WeasyPrint stops before laying out a single page.
The give-away is in the output beneath the error, which contains a line like:
Install the libraries for your platform, following the per-OS instructions already in Install Python and Zensical - brew install pango plus the pinned pandoc download on macOS, the MSYS2 pacman step on Windows, or the apt install line plus the pinned pandoc .deb on Linux. If you followed that page when setting up, you already ran this and something else is missing; re-running it is harmless either way.
Then check before building again:
A version number means you are ready. The same long error means the libraries still are not being found.
On macOS, if it still fails after installing Pango
macOS only looks in Homebrew's folder for libraries if the Python you are using was itself installed by Homebrew. That is why Install tooling has you create the virtual environment with the full path /opt/homebrew/bin/python3 rather than a plain python3. If you created it another way, the quickest fix is to delete .venv and make it again, following those steps exactly.
Mermaid render fails with a browser process error¶
Another specific case of "PDF build fails" above, this one on Linux:
⚠️ Mermaid render failed for diagram 1:
Error: Failed to launch the browser process: Code: 2
stderr:
.../chrome-headless-shell: 1: ELF: not found
.../chrome-headless-shell: 3: Syntax error: Unterminated quoted string
That garbled output is the giveaway: it's a binary being misread as a shell script. npm ci --prefix tools/mermaid downloads Chrome for whichever architecture Puppeteer defaults to, and on some Linux setups - most often ARM64 (an Apple Silicon Linux VM, an AWS Graviton instance, a Raspberry Pi) - that does not match your CPU. Linux can't execute a binary built for the wrong architecture, falls back to interpreting it as a script, and the first few bytes of a Chrome binary aren't valid shell - hence ELF: not found and an "unterminated quoted string" a few lines further down.
Install a native Chromium and point Puppeteer at it instead of its own download, following the Linux step in Install the two toolchains. If you followed that page when setting up, you already ran this and something else is wrong; re-running it is harmless either way. Then run prodockit pdf again.
Published site shows old content or a 404¶
- Check the pipeline (GitLab CI/CD > Pipelines) or workflow (GitHub Actions tab) actually ran, and succeeded, for your latest commit - if it's still running, or failed, the old version stays published.
- Confirm your change actually reached the default branch (
main) - a commit sitting on a feature branch, or a merge/pull request you haven't merged yet, never triggers a rebuild. See Managing branches and issues. - Hard refresh the published page (
Ctrl+Shift+R/Cmd+Shift+R) - your browser can cache the old version just as easily as it caches the local preview. - On GitHub specifically, if the workflow fails with
Get Pages site failed... Not Found, GitHub Pages hasn't been switched on for the repository yet. Go to Settings > Pages and change Build and deployment > Source from Deploy from a branch to GitHub Actions, then re-run the failed workflow. This is a one-off step after cloning a fresh copy of the repository into a new GitHub account - see the GitHub Pages step in Cloning the prodockit-template in Install tooling. - On GitLab specifically, if the pipeline succeeds but no Pages site ever appears, check that the Pages feature itself hasn't been disabled for the project: Settings > General > Visibility, project features, permissions, and make sure Pages is toggled on. Unlike GitHub, GitLab doesn't need a separate "source" setting - Pages deploys automatically from the
pagesjob in.gitlab-ci.ymlonce the feature is enabled, which it is by default.
Release your report¶
Before you submit your report, remove the "Start Here" stub page so it isn't part of what you hand in - see Start here in your own copy of the template for exactly what to comment out in zensical.toml and what to delete.
Info
Once you've removed the stub from your own report, you can still come back to this guidance any time on the independent prodockit User Guide site.
Where to go next¶
Continue to Markdown basics and Zensical basics to learn the syntax you'll actually use to write your document. Once you're comfortable writing content, come back to these later chapters when you need them:
- Customisation - branding, the cover page, PDF layout, and the document's directory structure.
- Additional tooling - GitLab/GitHub VS Code extensions, and Vale for spelling/grammar/style checking.



