Journal v1.0: A Simple Go Project That Grew Up
Posted on Wednesday April 29, 2026

Side projects have a funny way of evolving. You start with a small idea - something you need for yourself - and if you keep at it, you end up with something that's actually pretty capable. Journal started as exactly that: I wanted somewhere I could write down my thoughts privately, without relying on a third-party service, and I wanted to build it myself in Go to get some proper hands-on experience with the language.
A few years later, I still use it every single day.
What Is It?
Journal is a straightforward web-based journal built in Go. You run a binary, it serves a web interface, and you can create, edit and read entries in a simple Markdown format. It stores everything in a SQLite database, which means there's no database server to configure or maintain - just a single file on disk that you can back up or move around easily.
There's also an API - a proper REST API documented with an OpenAPI 3.0 spec - which means you can interact with your entries programmatically if you want to build something on top of it.
What makes it interesting as a project, beyond being a useful tool, is that it was deliberately built to be readable. It only has two dependencies. Everything else is standard Golang libraries - the router, the template engine, the SQLite adapter. The aim was to write something that a developer who is just getting started with Go could pick up, read through, and actually understand from end to end. That's always been one of the goals alongside the personal use case.
The Journey to v1.0
The project has been in pre-release for most of its life, sitting in the v0.x range while I incrementally added features and tinkered with it when time allowed. Over those versions, a few experiments came and went - at one point I added Giphy integration (a novelty that didn't survive), and at another I built in AWS Lambda deployment support when I was exploring serverless hosting for it. Neither of these felt like they belonged long-term, and v1.0 was the right time to clean the slate.
This is the thing about a major version release for a side project: it gives you permission to make the calls you've been putting off. What should stay? What needs to go? What's actually missing?
The v1.0 overhaul was a significant piece of work. Here's what changed:
Breaking changes and removals:
- The Giphy integration is gone entirely. It was a fun experiment, but it didn't fit the purpose of the tool
- Lambda deployment support has been removed - Journal now runs as a straightforward HTTP server, which is the right model for something self-hosted
- The J_DATA_PATH environment variable was renamed to J_WEB_PATH, which better describes what it actually configures
- The entry point moved from a root journal.go to a proper cmd/journal/main.go structure following Go project conventions
- The frontend build toolchain (gulp, sass, webpack) was replaced with a pre-built CSS theme system that's much simpler to work with and extend
New features: - A calendar view lets you browse entries by month and year, which turns out to be a really natural way to navigate a journal - A stats page (and API endpoint) shows article counts, word counts, and visit data - useful for keeping a sense of how much you're actually writing - A random article endpoint was added to both the web UI and API, which is a nice way to surface old entries you've forgotten about - Full Markdown rendering support means entries can now use proper formatting, headings, links and code blocks - A database migration system handles schema changes cleanly without downtime - Visit and request tracking are now stored in the database, feeding into the stats view
Distribution and packaging: - Multi-platform binary builds for Linux and macOS on both amd64 and arm64 - Proper apt/deb and yum/rpm packaging via nfpm, so it installs like any other application on Linux - Multi-platform Docker images pushed to both Docker Hub and the GitHub Container Registry - A Homebrew tap for macOS installations - Automated semantic versioning driven by conventional commits in the repository
Test coverage is now sitting at around 100% across all application packages, which I'm genuinely pleased about. Writing tests for Go is pleasant enough that it doesn't feel like a chore, and having that coverage means I can make changes with confidence.
Why I Still Use It Every Day
I mentioned at the start that I use Journal every day. I wasn't being hyperbolic - in the article I wrote about returning to work after parental leave, I mentioned that journalling regularly is one of the things I do to keep a handle on my well-being. I host a private instance of Journal and write in it each morning or evening to process what I'm thinking and feeling. It's become a genuine habit.
The fact that I built it myself matters here. I know exactly what happens to my data. There are no third-party services involved, no accounts, no subscription. The database is a file on a server I control, and I can back it up, move it, or read it directly whenever I want. That kind of ownership over your own data feels increasingly rare, and it's something I value a lot.
Why It's Worth Continuing
For me, Journal serves two purposes that I find equally motivating.
The first is purely personal - it's a tool I actually use, which means I have genuine feedback about what works and what doesn't. Features like the calendar view and random article came directly from using it and noticing what was missing. That feedback loop is invaluable.
The second is educational. I built Journal to be a good learning project, and I want to keep it that way. It's a real application - it has a web interface, an API, a database, configuration, deployment packaging - but it's small enough that you can understand the whole thing without drowning in complexity. If someone wants to learn Go, they can fork it, run it, break it, and fix it. That's a genuinely useful thing to put into the world.
What's Next
There are a few things I'd like to look at in future versions. Better theming support and a wider selection of default themes would make it more visually interesting. I'd also like to explore tagging and search, which would make it significantly more useful as a long-term record. Import and export functionality - particularly for Markdown files - would make it easier for people to get their data in and out.
For now though, I'm happy with where v1.0 has landed. It's a clean, well-tested, well-documented release that represents what I actually want the project to be. If you're curious about it, the source code is on GitHub and there's a dedicated page here on this blog with installation instructions and more detail on what it offers.