I Rewrote My Website
#golang #coding #webdev
My website was written in SvelteKit, a framework i still very much like. But i started on a new team at my job that is more backend focused and writes primarily in golang, so i wanted to get some practice by rewriting something familiar to me.
This was also an opportunity to rip tailwind out and go back to vanilla css which i have learned i much prefer especially since nesting became native.
New image architecture
(if the mermaid diagram doesn't render, you may need to refresh the page. It won't render without JS enabled, sorry! I tried SSRing it but it was taking >1s and i didn't dig into the alternative SSR method. Maybe another time...)
If you see my last post, you will see that my blog has images now. The funny thing about that post is that it is now mostly out of date đ
. The good news is that part of it is similar. Instead of SvelteMarkdown, I'm using goldmark and a custom extension to fetch a signed URL from my minio instance and i set an img
tag with the src
of the URI of the signed URL, then i set up a route on the server at /s3/
to reverse proxy to my minio instance so that i do not have to expose it publicly.
Open Telemetry
I was using pino-loki previously for logs but i wanted to delve deeper into understanding observability stuff since its still kind of new to me. This is the first time i've instrumented an application from scratch and after wrapping my head around the concepts it wasn't too bad. Although there is certainly some things i'm missing. It was hard to find definitive best practices as most guides i found were related to large distributed systems. Which makes sense. I did get really stuck on the zerolog otel bridge which i thought had a bug for a long time until i realized the bug was in zerolog itself. It can not transform fields into otel attributes, and the otel-zerolog bridge was actually unpublished. But the documentation hasn't been updated to reflect this so i was befuddled when trying to understand why the attributes weren't showing up in Grafana.
I switched to the otel slog package which is fine but doesn't seem to output in json format. The message itself doesn't seem to have a field attached so the | json
formatter in Grafana doesn't work. This is not a huge deal but there are some l things that seem difficult to config compared to zerolog.
Styles
I am using Open Props which i love because it provides great defaults for sizes and colors and other various things. It makes writing a stylesheet from scratch a lot less daunting. I learned about the light-dark()
css function which i made use of for my themes. Unfortunately the light-dark function doesn't work with gradients so i had to ditch the gradient on the "hashtags".
One day those will be clickable and will sort blog posts by the clicked tag but that feature will have to wait.
Other stuff
I am planning on writing a colophon page to list all of the tech behind this blog but for the rewrite I used the following libraries:
- golang 1.24
- templ for templating
- htmx (only using the boost feature currently)
- open props
- goldmark for markdown rendering
- otel, otelslog
- minio
- net/http for routing and http handling
The blog is deployed to my k8s cluster. Right now the only CI i have builds a staging image on the staging
branch and the production image on the main
branch. I would like to get the k8s definitions saddled up with the code itself but i have a messy homelab
repo full of yaml, helm commands in text files, and some deno script that lets me write typed k8s definitions that spits out yaml. Eventually that will be made into something more reusable and i can define those definitions in the same repo as the code i'm trying to deploy. It's good to have goals đ.
Golang thoughts
There are a lot of things i really like about golang, and some things that are not great. First, the bad: documentation is very obtuse. I will admit this is partly a skill issue on my part, but there way things are abstracted means the generated documentation for libraries is often extremely confusing. I am used to digging through TypeScript definitions to better understand an API but for golang even that is sometimes difficult the way interfaces are used abstract things. This is something that will get better over time as i become more comfortable with the language but it makes it difficult to learn.
The things i like are mostly what i see others who are new to golang like: the error handling, the "one way of doing things" style, the toolchain, and the standard library. That last one is probably because my main serverside language is TypeScript and outside of something like Deno there is no standard library.
Obsidian sync
My blog engine also got a little update with this rewrite. There was a bug that because i relied on the file's ctime
and mtime
, when syncing a vault to a linux machine, the ctime
would be incorrect because the filesystem doesn't track a createdAt time, only modifiedAt. The solution is to store this time in the frontmatter which is fine but in order to fix files that already existed, i had to write some code that injected the frontmatter when fetching files that did not have this new format. New files also get this injected and an on modify hook lets the mtime
update automagically. This let me also change the timestamp to use RFC1123 so I can use the mtime
as my Last-Modified
header for better caching semantics.
That is all for today. Thanks as always for reading and i will catch you on the internet.
Last updated: