Open source TypeScript · 2024 – now
Handwritten notes, inside a plain-text vault.
An Obsidian plugin that makes Xournal++ notebooks feel native: draw by hand, and the PDF shows up in your notes the moment you save. I built it for my own maths lectures. Now thousands of people use it, and I maintain it.
- role
- Author & maintainer
- timeline
- May 2024 – now
- stack
- TypeScript, Obsidian API, GitHub Actions
- links
- source
plugin page
Notebooks show up as PDFs labelled X++. One click opens the original in Xournal++.
01Problem
Maths lectures need handwriting. My notes live in Obsidian, which is plain
Markdown files on disk. I'm on Linux, so the usual tablet note apps were out.
Xournal++ is great for writing by hand and annotating PDFs, but Obsidian
ignores its .xopp files completely. I couldn't link them, preview
them or embed them.
I wanted handwritten pages to be first-class notes, not attachments I had to export by hand.
So my notes ended up split in two: typed notes in the vault, handwriting in a separate folder, and a manual "export to PDF" step that I kept forgetting.
02How it works
The core idea is a corresponding PDF: every Xournal++ notebook gets a PDF with the same name, in the same folder. Obsidian already knows how to render PDFs, so the plugin's job is to keep that pair in sync. It hides the plumbing and adds the actions you'd expect.
The PDF is just a rendered copy. The .xopp file stays the source of truth.
What you get in Obsidian
- Auto-export: each time a notebook changes, its PDF is regenerated.
- Create new notebooks from the ribbon, file explorer, folder menu or command palette.
- Edit in Xournal++ from the PDF preview, the file explorer's
X++label, or a command. - Rename and delete the notebook and its PDF together, so the pair never drifts apart.
03Decisions
Most of the design came down to staying out of the way of two apps I don't control.
Render with what's already there
No custom handwriting viewer. Obsidian already renders PDFs well, so the plugin only produces PDFs and adds actions around them.
One file in the explorer, not two
The PDF is shown with an X++ label rather than listing both files. That way the vault reads like one note per notebook.
Paired file operations
Rename and delete go through the plugin, so a notebook never ends up without its PDF, or with a stale one.
Beta channel before releases
Bigger changes go out as betas first. Early adopters catch platform-specific problems before everyone else updates.
04Maintaining it
After the first release, the work changed. It became less about writing features and more about running a small open-source project: triaging issues, reviewing outside pull requests, writing docs and shipping regularly without breaking people's vaults.
# .github/workflows/ci.yml — on every push & PR npm run lint ✓ eslint npm run format:check ✓ prettier npm run test ✓ unit tests npm run build ✓ plugin bundle # release.yml — tag → build → GitHub release # deploy-docs.yml — wiki → docs site
A contribution can only be merged once lint, formatting, tests and the build all pass.
- 1.0.0May 2024
First public release in the Obsidian community plugin directory.
- 1.0.1 – 1.0.11May 2024 – Jan 2025
Eleven patch releases, mostly driven by issues from new users.
- 1.1.0Apr 2025
First minor release. Afterwards, a beta channel for testing changes early.
- 1.2.0-beta.1Dec 2025
A longer beta period for the next feature release.
- 1.2.1Aug 2026
Current version. 21 releases in total.
05Outcome
Something I built for one lecture now has over 11,000 downloads, a Discord community, a docs site and contributors who aren't me. 17 community pull requests have been merged so far.
It's also where I learned what I enjoy most: the work around the code. That means CI that makes reviewing a pull request from a stranger safe, releases that are boring, and docs good enough that the same question doesn't come up twice.