# 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).