devlog 1 - foundations
Over the past few months, I’ve played around with multiple side projects. While working on these and the Stripe integrations, I realised I’d been through this process before—integrating Stripe, writing custom logic to handle Stripe Webhooks and building out features driven from the integration and wondered whether I had to repeat this each time.
I decided to create a standalone application that provides all the necessary functionality for my side projects. This application would sit alongside any project, offering hooks, notifications, and other essential features. I’ve named the project “stria” for now, though this might change. I’m considering selling it under a perpetual licence with free minor/patch updates. Major releases would be available as paid upgrades for existing users.
These devlogs aim to keep me on track. In the first entry, I will cover the technology choices for the project.
Technology Choices #
I’m trying to minimise external dependencies and rely primarily on the Go standard library.
Config #
Configuration is managed through YAML config files and environment variables. Initially, I used Pkl, but it required the Pkl CLI tool for parsing. While Pkl shows promise, it currently lacks a pure Go implementation and requires the Java CLI tool, which is a significant dependency. Therefore, I opted not to include it in my applications for now.
The current YAML-based solution uses
gopkg.in/yaml.v3 and the standard library’s
os.ExpandEnv function. This transforms any ${SOME_ENV_VAR}
or $SOME_ENV_VAR
in the YAML file before unmarshalling it into the application’s config structure.
Although this is a simple library I’m proud of the solution that this has evolved into it’s easy to understand and not overly complicated. The library can be found on Github aranw/yamlcfg.
Database: SQLite #
For data storage I’ve picked SQLite or more specifically Turso’s libSQL fork. The libSQL fork of SQLite means I require CGO. Right now I’m still unsure if this is the right choice and may ultimately change this part I could switch back to SQLite or even PostgreSQL. I use the sqlc library to code generate a bunch of the service layer code so if needed I think it should be fairly easy to swap out.
Migrations #
go-migrate/migrate is my current solution for migrations. While it supports “up” and “down” migrations, I don’t agree with the concept of “down” migrations. They often create more issues than they resolve, especially since not all database operations can be safely undone and deleted data is often irrecoverable.
Ideally, I prefer up-only migrations. If changes need to be undone, a new up migration should be applied to fix the issue. In the future, I hope to develop a custom library to address this need.
Frontend: Templ #
One of the core goals of the project is to ensure easy distribution. To achieve this, I aimed to integrate both the frontend and backend into a single binary. Go’s standard library for templating has its challenges, so I opted for the fantastic templ library for the frontend. Coupled with HTMX and alpinejs, this setup provides excellent interactivity and a modern user interface.
HTTP Router #
Currently, I use chi as the solution for the HTTP router. Chi is a lightweight and idiomatic HTTP router that easily integrates with other Go HTTP handlers, facilitating the composition of functionality. In the long term, I’d like to replace this with Go 1.22’s new and improved HTTP multiplexer. However, I still need to devise an effective approach for transitioning from Chi to this new multiplexer.
Sessions #
Having encrypted cookies to store session state is vital. To address this, I chose the alexedwards/scs library. I selected this library due to its comprehensive feature set and support for a wide range of storage backends for sessions.
Additional Features #
In the future I have other features that I want to add and integrate and those will require other technology choices to be hard. I have some of them decided but some are still up in the air as to what I want to use.
What is next? #
I’ve built a strong foundation and am progressing well with the project. Over the next few weeks, I aim to make further advancements and document these developments. However, my progress is currently slow since I have to fit in development whenever possible—on weekends, before and after work, and during holidays. Despite these challenges, I’m excited about tackling the upcoming tasks, which include implementing webhook receivers, setting up password authentication, automating various processes, and syncing workflows. I’m looking forward to sharing more updates as I continue to refine and expand the project.