SheafJournal: A Developer’s Journal App Built the Way I Wanted It

I’ve been using note-taking and journalling apps for years. Like most developers I’ve tried most of them. For a while I settled on a combination of Obsidian and Zim, but neither was quite right Obsidian for is powerful but complex, Zim is simple and has file-based storag but is old.

So I built my own. This is the story of why, what I built, and what’s coming next.


The Problem With the Alternatives

Obsidian is genuinely impressive software. The plugin ecosystem is vast, the graph view is beautiful, and the community is active. But the more I used it, the more it felt like I was managing the tool rather than using it. Plugin configuration stacks up. And critically Obsidian uses its own filesystem abstraction. Your notes live in a vault that Obsidian controls. Integrating other file types, or building tools that work alongside your notes, is harder than it should be.

Zim took the opposite approach, It uses plain files, simple structure, no abstraction between you and your data. I loved that. But Zim is old. The interface shows its age, and it doesn’t autosave. For a journal, not autosaving is a dealbreaker. I lost notes. Everyone who uses Zim probably loses notes eventually.

What I wanted was something in between: file-based like Zim, more capable than Zim, but focused and opinionated rather than trying to be everything like Obsidian.


What SheafJournal Is (And Isn’t)

SheafJournal is a journal app first. It’s not a general knowledge management system. It’s not trying to replace Obsidian. It has a clear opinion about what it does:

  • A daily journal with calendar navigation
  • Notes sections for reference material
  • A knowledge base for things you want to keep
  • Everything autosaved, always

Because it’s focused, it can be opinionated. The interface is designed around journalling workflows rather than trying to accommodate every possible use case. That makes it simpler and faster to use for what it’s actually for.

Your data is just files. Markdown on disk, in a folder structure you can see and understand. Open your notes in any editor. Search them with any tool. Back them up with any backup system. No export step, no vendor lock-in, no company that could change its pricing model or shut down and take your notes with it.


The Stack: SvelteKit, Bun, TypeScript

SheafJournal is built with SvelteKit on the frontend, Bun as the runtime, and TypeScript throughout. For someone who is primarily a backend developer, this appears an interesting choice. But I do full stack work sometimes.

The honest reason: I wanted to build something fast, and modern web tooling has become genuinely good. SvelteKit’s file-based routing means pages and API endpoints live side by side in a structure that makes sense. Bun’s startup time is fast enough that the app feels responsive in a way that heavier runtimes don’t.

The TypeScript/Kotlin parallel once surprised me. When I first started using TypeScript I expected TypeScript to feel like JavaScript with types bolted on. Instead and particularly for the kind of data-manipulation code a backend developer writes, it feels remarkably like Kotlin. Type inference, null safety, interface-based design. Add a library like Radash and you get collection operations that feel like Kotlin’s standard library: map, filter, groupBy, sortBy working naturally on typed data. The mental model transfers more than I expected.

There are differences. TypeScript has no coroutines, but for a local desktop app that’s not a constraint. And the tooling, while improving rapidly, doesn’t yet match IntelliJ for a Kotlin project. But the gap is smaller than you might expect, and the iteration speed with Bun is genuinely faster than a Spring Boot development cycle.


How the Data Model Works

The knowledge base is a folder on your filesystem:

Journal/
  2026/
    01/
      15/
        note-2026-01-15-09-30-00-000.md
Notes/
  java/
    concurrency.md
Knowledge/
  architecture/
    patterns.md

That’s it. Real files, real folders, no abstraction.

SQLite sits alongside the files but contains only derived metadata — tags, word counts, last viewed timestamps, cached markdown conversions. If the database is deleted, it rebuilds from the files on next startup. The files are the truth. The database is just an index.

This matters for a reason I find important: your notes should survive the app. If SheafJournal stopped working tomorrow, your data would still be there, readable in any text editor, searchable with any tool. That’s not true of apps that store data in proprietary formats or databases you can’t open.


Features Worth Knowing About

Autosave. Everything saves as you type. No save button, no lost notes.

Journal / Notes / Knowledge split. The three sections have different mental models. The journal is chronological — you navigate by date. Notes and Knowledge are organised by section, more like a wiki. You choose which section fits each piece of information.

Frontmatter tags. Notes can have YAML frontmatter:

---
tags: [java, concurrency, quick-note]
---

Notes from reading the JEP on virtual threads...

New notes are stamped with quick-note by default — an inbox pattern. You review your quick notes, replace the tag with something meaningful, and they move out of the inbox. It’s a lightweight capture-first workflow that doesn’t require you to organise before you write.

Full-text search. Search across all your journal entries, notes and knowledge in one place. Filter by tag with tag:java. Results show the matching snippet in context so you can see immediately whether it’s what you’re looking for.

The search is implemented as a pure JavaScript file walker — no grep, no external tools, works on Windows, Mac and Linux without any dependencies.

Journal-style todos. Both the day summary view and individual daily notes support inline tasks. These work differently from a calendar or task manager, and the distinction matters.

A calendar todo is about the future — something scheduled, something to complete. It carries forward until it’s done. A journal todo is about the past — a record of what you worked on that day. If you spent Tuesday afternoon on a database migration, you mark it in Tuesday’s journal. Whether the migration is finished is irrelevant; what’s recorded is that you worked on it that day. It doesn’t carry over, because the journal isn’t asking “what do I still need to do?” It’s asking “what did I actually do?”

This makes journal todos useful in a way calendar todos aren’t for retrospective work — daily standups, weekly reviews, timesheet reconstruction, understanding where your time actually went rather than where you intended it to go.

Syntax highlighting and Mermaid diagrams. Code blocks are highlighted. Mermaid diagram blocks render as diagrams. For a developer’s journal these are the two things you reach for most often when documenting something technical.

Markdown rendered in real time. The editor and preview update as you type. The conversion is cached in SQLite so switching between notes is instant even for long documents.


What’s Coming

The most important upcoming feature is additional file type support. Right now SheafJournal works with markdown. The plan is to add support for other file types alongside markdown — documents, spreadsheets, and other formats that a developer’s knowledge base accumulates over time. Rather than trying to convert everything to markdown, the goal is to display and link to other file types naturally within the journal structure.

This is the feature I most wanted from Obsidian and couldn’t get cleanly. It’s the main reason I built my own tool.

Other things on the roadmap:

  • Richer linking between notes and across sections
  • Improved tag management eg. renaming, merging, browsing
  • Export options for sharing specific notes or sections
  • Mobile access to the same files

The Desktop App Part

One more thing worth mentioning: SheafJournal runs as a desktop application. Not via Electron. The app itself is a Bun/SvelteKit server; a small Go launcher starts it, handles authentication, and opens your browser. The result is a quick cold start without the weight of a bundled browser.

The launcher architecture is its own story. I’ll cover it in a separate post. The short version is: I wanted to write pure SvelteKit without learning a native bridge API, so I built a thin launcher that makes that possible.


Why Build It at All?

Partly because I wanted the tool. Partly because building it taught me things about the stack I wouldn’t have learned otherwise. And partly because the act of maintaining a journal only works if the tool gets out of the way — and the only tool guaranteed to get out of the way is one you built and understand completely.

SheafJournal v0.1 is what I use now. It’s not feature-complete. Some things are rough. But it autosaves, it’s fast, my data is files I can read without the app, and I can add exactly the features I want in exactly the way I want them.


SheafJournal is open source. (GPL and the launcher is Apache 2.0 licence) The code is at github.com/robdeas/sheafjournal. To run it you will either need the launcher or set environment variables. The launcher architecture will be covered in a separate post: [SheafLauncher: Building Desktop Apps with SvelteKit and Bun, Without Electron].

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top