# New Website, New Technology
If you come here occasionally, you may have noticed that the style of my website
has changed completely. I've built a new website using [Go](https://go.dev/).
The old website was a bloated custom [Node.js](https://nodejs.org/) app that was
probably [full of keyloggers and bitcoin
stealers](https://gitlab.com/grepular/safernode). It was also difficult to work
on, and stored blog posts in [MongoDB](https://www.mongodb.com/) .
This one keeps all of my blog posts in markdown files, making it much easier to
write and edit. You will even see a "[View as raw
markdown](New_Website_New_Technology.md)" link at the top of each blog post.
Hopefully this will give me a little more impetus to post on a regular basis.
Here are some new things that I learnt in the process and some things that I've
done which are a little novel:
## SVG Sprites
You can stick several distinct images inside a single
[SVG](https://developer.mozilla.org/docs/Web/SVG "Scalable Vector Graphics")
file, and then reference them individually when displaying them from HTML. For
example, if you were to stick the following SVG content at `/img/icons.svg`:
```html
```
That SVG has a "blog" and "gitlab" image inside it. See the `id` attribute of
the `symbol` tags. If you want to show the "blog" image in your html, instead of
using an `` tag, do this:
```html
```
The fragment value is used to select the correct symbol.
## [Early Hints](https://developer.mozilla.org/docs/Web/HTTP/Reference/Status/103)
You can basically respond to an HTTP request with two responses instead of one.
The first response is a 103, which tells the client to start fetching some
resources that it will need later (unless it already has it in it's cache). The
second one is the actual response you requested. This is useful because you
might want to tell the browser to start fetching a CSS file immediately, even
though it's going to take another 200ms or whatever to render the HTML that
you've asked for:
```text
HTTP/2 103
Link: ; rel=preload; as=style; crossorigin=anonymous
HTTP/2 200
...headers
...body
```
My framework dynamically scans the templates at build time to find content that
could be pre-loaded using this method, and makes sure it is. It probably has
little impact here as my responses are so quick anyway, but it's interesting to
know about.
## [Speculation Rules](https://developer.mozilla.org/docs/Web/API/Speculation_Rules_API)
I have a minified version of the following in the head of each page on this
website:
```html
```
The above makes it so that when your mouse hovers over an anchor tag pointing to
local content, it is pre-fetched over the network. And also, at the point of a
mousedown event triggering, it starts pre-rendering that content. No JavaScript
required.
## Browser Tests
I created a set of Headless Browser tests. If I run `make test`, it fires up a
local copy of the website and visits each page in turn, searching for any errors
in the browser console and 404 or 5xx codes etc. I also have tests which will
visit all external links to see if any are broken. I've cleaned up quite a few,
but there are still some left to do after ~17 years of blogging. I have further
tests to check if external links can be upgraded from http to https.
## Single Compiled Binary
The whole website is a single executable, containing all of the code, the
webserver, the HTML, templates, CSS, images and so on. I use
[aprice/embed](https://github.com/aprice/embed) to embed the content inside the
binary. Content is even gzip compressed before being embedded where appropriate.
It's a 4.6MB binary ([UPX](https://upx.github.io/) compressed). I simply run it,
and it listens on port 8080 and serves up all content.
## Caching
In my templates, rather than using `` I put ``. My framework has a `static` template function, which
calculates a SHA256 of the content of example.png, and adds a prefix of that as
a query string parameter. E.g it might change it to ``. My framework then identifies a request
for some static content, with a `v` parameter in the query string, and makes
sure to send a `Cache-Control: public, max-age=2592000, immutable` header with
it. This tells the browser (and my nginx proxy) that this content will not
change, and to cache it for 30 days in case it is needed again. If I decide to
change the content of that file, the hash will change, and therefore your
browser will immediately receive the next version of it, ignoring the previously
cached version. The hashes are pre-calculated at build time.
## Privacy
Privacy policies are usually not very interesting, but I put some effort into
using the web technologies that are available, to secure my visitors privacy.
You might learn something interesting from it. For example I send a HTTP
response header which stops your browser from reporting to external websites
that you came from www.grepular.com when you click one of my external links. See
the full policy [here](/privacy).