+ Note: This post is unlisted! Please do not share
+ the link to it without asking me first.
+
+
+ '';
+
+ renderPost = post: runCommandNoCC "${post.key}.html" {} ''
+ cat ${toFile "header.html" (header post.title)} > $out
+
+ # Write the post title & date
+ echo '
${escape post.title}
' >> $out
+ echo '' >> $out
+
+ ${
+ # Add a warning to draft/unlisted posts to make it clear that
+ # people should not share the post.
+
+ if (isDraft post) then "cat ${draftWarning} >> $out"
+ else if (isUnlisted post) then "cat ${unlistedWarning} >> $out"
+ else "# Your ads could be here?"
+ }
+
+ # Write the actual post through cheddar's about-filter mechanism
+ cat ${post.content} | ${depot.tools.cheddar}/bin/cheddar --about-filter ${post.content} >> $out
+ echo '' >> $out
+
+ cat ${toFile "footer.html" footer} >> $out
+ '';
+in {
+ inherit renderPost isDraft isUnlisted;
+}
diff --git a/users/tazjin/blog/posts.nix b/users/tazjin/blog/posts.nix
new file mode 100644
index 0000000000..b43598d013
--- /dev/null
+++ b/users/tazjin/blog/posts.nix
@@ -0,0 +1,57 @@
+# This file defines all the blog posts.
+[
+ {
+ key = "emacs-is-underrated";
+ title = "Emacs is the most underrated tool";
+ date = 1581286656;
+ content = ./posts/emacs-is-underrated.md;
+ draft = true;
+ }
+ {
+ key = "best-tools";
+ title = "tazjin's best tools";
+ date = 1576800001;
+ content = ./posts/best-tools.md;
+ }
+ {
+ key = "nixery-layers";
+ title = "Nixery: Improved Layering Design";
+ date = 1565391600;
+ content = ./posts/nixery-layers.md;
+ }
+ {
+ key = "reversing-watchguard-vpn";
+ title = "Reverse-engineering WatchGuard Mobile VPN";
+ date = 1486830338;
+ content = ./posts/reversing-watchguard-vpn.md;
+ oldKey = "1486830338";
+ }
+ {
+ key = "make-object-t-again";
+ title = "Make Object Again!";
+ date = 1476807384;
+ content = ./posts/make-object-t-again.md;
+ oldKey = "1476807384";
+ }
+ {
+ key = "the-smu-problem";
+ title = "The SMU-problem of messaging apps";
+ date = 1450354078;
+ content =./posts/the-smu-problem.md;
+ oldKey = "1450354078";
+ }
+ {
+ key = "sick-in-sweden";
+ title = "Being sick in Sweden";
+ date = 1423995834;
+ content = ./posts/sick-in-sweden.md;
+ oldKey = "1423995834";
+ }
+ {
+ key = "nsa-zettabytes";
+ title = "The NSA's 5 zettabytes of data";
+ date = 1375310627;
+ content = ./posts/nsa-zettabytes.md;
+ oldKey = "1375310627";
+ }
+]
diff --git a/users/tazjin/blog/posts/best-tools.md b/users/tazjin/blog/posts/best-tools.md
new file mode 100644
index 0000000000..e4bad8f4cd
--- /dev/null
+++ b/users/tazjin/blog/posts/best-tools.md
@@ -0,0 +1,160 @@
+In the spirit of various other "Which X do you use?"-pages I thought it would be
+fun to have a little post here that describes which tools I've found to work
+well for myself.
+
+When I say "tools" here, it's not about software - it's about real, physical
+tools!
+
+If something goes on this list that's because I think it's seriously a
+best-in-class type of product.
+
+
+- [Media & Tech](#media--tech)
+ - [Keyboard](#keyboard)
+ - [Speakers](#speakers)
+ - [Headphones](#headphones)
+ - [Earphones](#earphones)
+ - [Phone](#phone)
+- [Other stuff](#other-stuff)
+ - [Toothbrush](#toothbrush)
+ - [Shavers](#shavers)
+ - [Shoulder bag](#shoulder-bag)
+ - [Wallet](#wallet)
+
+
+---------
+
+# Media & Tech
+
+## Keyboard
+
+The best keyboard that money will buy you at the moment is the [Kinesis
+Advantage][advantage]. There's a variety of contoured & similarly shaped
+keyboards on the market, but the Kinesis is the only one I've tried that has
+properly implemented the keywell concept.
+
+I struggle with RSI issues and the Kinesis actually makes it possible for me to
+type for longer periods of time, which always leads to extra discomfort on
+laptop keyboards and such.
+
+Honestly, the Kinesis is probably the best piece of equipment on this entire
+list. I own several of them and there will probably be more in the future. They
+last forever and your wrists will thank you in the future, even if you do not
+suffer from RSI yet.
+
+[advantage]: https://kinesis-ergo.com/shop/advantage2/
+
+## Speakers
+
+The speakers that I've hooked up to my audio setup (including both record player
+& Chromecast / TV) are the [Teufel Motiv 2][motiv-2]. I've had these for over a
+decade and they're incredibly good, but unfortunately Teufel no longer makes
+them.
+
+It's possible to grab a pair on eBay occasionally, so keep an eye out if you're
+interested!
+
+[motiv-2]: https://www.teufelaudio.com/uk/pc/motiv-2-p167.html
+
+## Headphones
+
+I use the [Bose QC35][qc35] (note: link goes to a newer generation than the one
+I own) for their outstanding noise cancelling functionality and decent sound.
+
+When I first bought them I didn't expect them to end up on this list as the
+firmware had issues that made them only barely usable, but Bose has managed to
+iron these problems out over time.
+
+I avoid using Bluetooth when outside and fortunately the QC35 come with an
+optional cable that you can plug into any good old 3.5mm jack.
+
+[qc35]: https://www.bose.co.uk/en_gb/products/headphones/over_ear_headphones/quietcomfort-35-wireless-ii.html
+
+### Earphones
+
+Actually, to follow up on the above - most of the time I'm not using (over-ear)
+headphones, but (in-ear) earphones - specifically the (**wired!!!**) [Apple
+EarPods][earpods].
+
+Apple will probably stop selling these soon because they've gotten into the
+habit of cancelling all of their good products, so I have a stash of these
+around. You will usually find no fewer than 3-4 of them lying around in my
+flat.
+
+[earpods]: https://www.apple.com/uk/shop/product/MNHF2ZM/A/earpods-with-35mm-headphone-plug
+
+## Phone
+
+The best phone I have used in recent years is the [iPhone SE][se]. It was the
+*last* phone that had a reasonable size (up to 4") *and* a 3.5mm headphone jack.
+
+Unfortunately, it runs iOS. Despite owning a whole bunch of SEs, I have finally
+moved on to an Android phone that is only moderately larger (still by an
+annoying amount), but does at least have a headphone jack: The [Samsung Galaxy
+S10e][s10e].
+
+It has pretty good hardware and I can almost reach 70% of the screen, which is
+better than other phones out there right now. Unfortunately it runs Samsung's
+impossible-to-remove bloatware on top of Android, but that is still less
+annoying to use than iOS.
+
+QUESTION: This is the only item on this list for which I am actively seeking a
+replacement, so if you have any tips about new phones that might fit these
+criteria that I've missed please let me know!
+
+[se]: https://en.wikipedia.org/wiki/IPhone_SE
+[s10e]: https://www.phonearena.com/phones/Samsung-Galaxy-S10e_id11114
+
+# Other stuff
+
+## Toothbrush
+
+The [Philips Sonicare][sonicare] (note: link goes to a newer generation than
+mine) is excellent and well worth its money.
+
+I've had it for a few years and whereas I occasionally had minor teeth issues
+before, they seem to be mostly gone now. According to my dentist the state of my
+teeth is now usually pretty good and I draw a direct correlation back to this
+thing.
+
+The newer generations come with flashy features like apps and probably more
+LEDs, but I suspect that those can just be ignored.
+
+[sonicare]: https://www.philips.co.uk/c-m-pe/electric-toothbrushes
+
+## Shavers
+
+The [Philipps SensoTouch 3D][sensotouch] is excellent. Super-comfortable close
+face shave in no time and leaves absolutely no mess around, as far as I can
+tell! I've had this for ~5 years and it's not showing any signs of aging yet.
+
+Another bonus is that its battery time is effectively infinite. I've never had
+to worry when bringing it on a longer trip!
+
+[sensotouch]: https://www.philips.co.uk/c-p/1250X_40/norelco-sensotouch-3d-wet-and-dry-electric-razor-with-precision-trimmer
+
+## Shoulder bag
+
+When I moved to London I wanted to stop using backpacks most of the time, as
+those are just annoying to deal with when commuting on the tube.
+
+To work around this I wanted a good shoulder bag with a vertical format (to save
+space), but it turned out that there's very few of those around that reach any
+kind of quality standard.
+
+The one I settled on is the [Waterfield Muzetto][muzetto] leather bag. It's one
+of those things that comes with a bit of a price tag attached, but it's well
+worth it!
+
+[muzetto]: https://www.sfbags.com/collections/shoulder-messenger-bags/products/muzetto-leather-bag
+
+## Wallet
+
+My wallet is the [Bellroy Slim Sleeve][slim-sleeve]. I don't carry cash unless
+I'm attending an event in Germany and this wallet fits that lifestyle perfectly.
+
+It's near indestructible, looks great, is very slim and fits a ton of cards,
+business cards, receipts and whatever else you want to be lugging around with
+you!
+
+[slim-sleeve]: https://bellroy.com/products/slim-sleeve-wallet/default/charcoal
diff --git a/users/tazjin/blog/posts/emacs-is-underrated.md b/users/tazjin/blog/posts/emacs-is-underrated.md
new file mode 100644
index 0000000000..afb8dc889e
--- /dev/null
+++ b/users/tazjin/blog/posts/emacs-is-underrated.md
@@ -0,0 +1,233 @@
+TIP: Hello, and thanks for offering to review my draft! This post
+intends to convey to people what the point of Emacs is. Not to convert
+them to use it, but at least with opening their minds to the
+possibility that it might contain valuable things. I don't know if I'm
+on track in the right direction, and your input will help me figure it
+out. Thanks!
+
+TODO(tazjin): Restructure sections: Intro -> Introspectability (and
+story) -> text-based UIs (which lead to fluidity, muscle memory across
+programs and "translatability" of workflows) -> Outro. It needs more
+flow!
+
+TODO(tazjin): Highlight more that it's not about editing: People can
+derive useful things from Emacs by just using magit/org/notmuch/etc.!
+
+TODO(tazjin): Note that there's value in trying Emacs even if people
+don't end up using it, similar to how learning languages like Lisp or
+Haskell helps grow as a programmer even without using them day-to-day.
+
+*Real post starts below!*
+
+---------
+
+There are two kinds of people: Those who use Emacs, and those who
+think it is a text editor. This post is aimed at those in the second
+category.
+
+Emacs is the most critical piece of software I run. My [Emacs
+configuration][emacs-config] has steadily evolved for almost a decade.
+Emacs is my window manager, mail client, terminal, git client,
+information management system and - perhaps unsurprisingly - text
+editor.
+
+Before going into why I chose to invest so much into this program,
+follow me along on a little thought experiment:
+
+----------
+
+Lets say you use a proprietary spreadsheet program. You find that
+there are features in it that *almost, but not quite* do what you
+want.
+
+What can you do? You can file a feature request to the company that
+makes it and hope they listen, but for the likes of Apple and
+Microsoft chances are they won't and there is nothing you can do.
+
+Let's say you are also running an open-source program for image
+manipulation. You again find that some of its features are subtly
+different from what you would want them to do.
+
+Things look a bit different this time - after all, the program is
+open-source! You can go and fetch its source code, figure out its
+internal structure and wrangle various layers of code into submission
+until you find the piece that implements the functionality you want to
+change. If you know the language it is written in; you can modify the
+feature.
+
+Now all that's left is figuring out its build system[^1], building and
+installing it and moving over to the new version.
+
+Realistically you are not going to do this much in the real world. The
+friction to contributing to projects, especially complex ones, is
+often quite high. For minor inconveniences, you might often find
+yourself just shrugging and working around them.
+
+What if it didn't have to be this way?
+
+-------------
+
+One of the core properties of Emacs is that it is *introspective* and
+*self-documenting*.
+
+For example: A few years ago, I had just switched over to using
+[EXWM][], the Emacs X Window Manager. To launch applications I was
+using an Emacs program called Helm that let me select installed
+programs interactively and press RET to execute them.
+
+This was very useful - until I discovered that if I tried to open a
+second terminal window, it would display an error:
+
+ Error: urxvt is already running
+
+Had this been dmenu, I might have had to go through the whole process
+described above to fix the issue. But it wasn't dmenu - it was an
+Emacs program, and I did the following things:
+
+1. I pressed C-h k[^2] (which means "please tell me what
+ the following key does"), followed by s-d (which was my
+ keybinding for launching programs).
+
+2. Emacs displayed a new buffer saying, roughly:
+
+ ```
+ s-d runs the command helm-run-external-command (found in global-map),
+ which is an interactive autoloaded compiled Lisp function in
+ ‘.../helm-external.el’.
+
+ It is bound to s-d.
+ ```
+
+ I clicked on the filename.
+
+3. Emacs opened the file and jumped to the definition of
+ `helm-run-external-command`. After a few seconds of reading through
+ the code, I found this snippet:
+
+ ```lisp
+ (if (get-process proc)
+ (if helm-raise-command
+ (shell-command (format helm-raise-command real-com))
+ (error "Error: %s is already running" real-com))
+ ;; ... the actual code to launch programs followed below ...
+ )
+ ```
+
+4. I deleted the outer if-expression which implemented the behaviour I
+ didn't want, pressed C-M-x to reload the code and saved
+ the file.
+
+The whole process took maybe a minute, and the problem was now gone.
+
+Emacs isn't just "open-source", it actively encourages the user to
+modify it, discover what to modify and experiment while it is running.
+
+In some sense it is like the experience of the old Lisp machines, a
+paradigm that we have completely forgotten.
+
+---------------
+
+Circling back to my opening statement: If Emacs is not a text editor,
+then what *is* it?
+
+The Emacs website says this:
+
+> [Emacs] is an interpreter for Emacs Lisp, a dialect of the Lisp
+> programming language with extensions to support text editing
+
+The core of Emacs implements the language and the functionality needed
+to evaluate and run it, as well as various primitives for user
+interface construction such as buffers, windows and frames.
+
+Every other feature of Emacs is implemented *in Emacs Lisp*.
+
+The Emacs distribution ships with rudimentary text editing
+functionality (and some language-specific support for the most popular
+languages), but it also brings with it two IRC clients, a Tetris
+implementation, a text-mode web browser, [org-mode][] and many other
+tools.
+
+Outside of the core distribution there is a myriad of available
+programs for Emacs: [magit][] (the famous git porcelain), text-based
+[HTTP clients][], even interactive [Kubernetes frontends][k8s].
+
+What all of these tools have in common is that they use text-based
+user interfaces (UI elements like images are used only sparingly in
+Emacs), and that they can be introspected and composed like everything
+else in Emacs.
+
+If magit does not expose a git flag I need, it's trivial to add. If I
+want a keybinding to jump from a buffer showing me a Kubernetes pod to
+a magit buffer for the source code of the container, it only takes a
+few lines of Emacs Lisp to implement.
+
+As proficiency with Emacs Lisp ramps up, the environment becomes
+malleable like clay and evolves along with the user's taste and needs.
+Muscle memory learned for one program translates seamlessly to others,
+and the overall effect is an improvement in *workflow fluidity* that
+is difficult to overstate.
+
+Also, workflows based on Emacs are *stable*. Moving my window
+management to Emacs has meant that I'm not subject to the whim of some
+third-party developer changing my window layouting features (as they
+often do on MacOS).
+
+To illustrate this: Emacs has development history back to the 1970s,
+continuous git history that survived multiple VCS migrations [since
+1985][first-commit] (that's 22 years before git itself was released!)
+and there is code[^3] implementing interactive functionality that has
+survived unmodified in Emacs *since then*.
+
+---------------
+
+Now, what is the point of this post?
+
+I decided to write this after a recent [tweet][] by @IanColdwater (in
+the context of todo-management apps):
+
+> The fact that it's 2020 and the most viable answer to this appears
+> to be Emacs might be the saddest thing I've ever heard
+
+What bothers me is that people see this as *sad*. Emacs being around
+for this long and still being unparalleled for many of the UX
+paradigms implemented by its programs is, in my book, incredible - and
+not sad.
+
+How many other paradigms have survived this long? How many other tools
+still have fervent followers, amazing [developer tooling][] and a
+[vibrant ecosystem][] at this age?
+
+Steve Yegge [said it best][babel][^5]: Emacs has the Quality Without a
+Name.
+
+What I wish you, the reader, should take away from this post is the
+following:
+
+TODO(tazjin): Figure out what people should take away from this post.
+I need to sleep on it. It's something about not dismissing tools just
+because of their age, urging them to explore paradigms that might seem
+unfamiliar and so on. Ideas welcome.
+
+---------------
+
+[^1]: Wouldn't it be a joy if every project just used Nix? I digress ...
+[^2]: These are keyboard shortcuts written in [Emacs Key Notation][ekn].
+[^3]: For example, [functionality for online memes][studly] that
+ wouldn't be invented for decades to come!
+[^4]: ... and some things wrong, but that is an issue for a separate post!
+[^5]: And I really *do* urge you to read that post's section on Emacs.
+
+[emacs-config]: https://git.tazj.in/tree/tools/emacs
+[EXWM]: https://github.com/ch11ng/exwm
+[helm]: https://github.com/emacs-helm/helm
+[ekn]: https://www.gnu.org/software/emacs/manual/html_node/efaq/Basic-keys.html
+[org-mode]: https://orgmode.org/
+[magit]: https://magit.vc
+[HTTP clients]: https://github.com/pashky/restclient.el
+[k8s]: https://github.com/jypma/kubectl
+[first-commit]: http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=ce5584125c44a1a2fbb46e810459c50b227a95e2
+[studly]: http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=47bdd84a0a9d20aab934482a64b84d0db63e7532
+[tweet]: https://twitter.com/IanColdwater/status/1220824466525229056
+[developer tooling]: https://github.com/alphapapa/emacs-package-dev-handbook
+[vibrant ecosystem]: https://github.com/emacs-tw/awesome-emacs
+[babel]: https://sites.google.com/site/steveyegge2/tour-de-babel#TOC-Lisp
diff --git a/users/tazjin/blog/posts/make-object-t-again.md b/users/tazjin/blog/posts/make-object-t-again.md
new file mode 100644
index 0000000000..420b57c0fd
--- /dev/null
+++ b/users/tazjin/blog/posts/make-object-t-again.md
@@ -0,0 +1,98 @@
+A few minutes ago I found myself debugging a strange Java issue related
+to Jackson, one of the most common Java JSON serialization libraries.
+
+The gist of the issue was that a short wrapper using some types from
+[Javaslang](http://www.javaslang.io/) was causing unexpected problems:
+
+```java
+public Try readValue(String json, TypeReference type) {
+ return Try.of(() -> objectMapper.readValue(json, type));
+}
+```
+
+The signature of this function was based on the original Jackson
+`readValue` type signature:
+
+```java
+public T readValue(String content, TypeReference valueTypeRef)
+```
+
+While happily using my wrapper function I suddenly got an unexpected
+error telling me that `Object` is incompatible with the type I was
+asking Jackson to de-serialize, which got me to re-evaluate the above
+type signature again.
+
+Lets look for a second at some code that will *happily compile* if you
+are using Jackson\'s own `readValue`:
+
+```java
+// This shouldn't compile!
+Long l = objectMapper.readValue("\"foo\"", new TypeReference(){});
+```
+
+As you can see there we ask Jackson to decode the JSON into a `String`
+as enclosed in the `TypeReference`, but assign the result to a `Long`.
+And it compiles. And it failes at runtime with
+`java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long`.
+Huh?
+
+Looking at the Jackson `readValue` implementation it becomes clear
+what\'s going on here:
+
+```java
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public T readValue(String content, TypeReference valueTypeRef)
+ throws IOException, JsonParseException, JsonMappingException
+{
+ return (T) _readMapAndClose(/* whatever */);
+}
+```
+
+The function is parameterised over the type `T`, however the only place
+where `T` occurs in the signature is in the parameter declaration and
+the function return type. Java will happily let you use generic
+functions and types without specifying type parameters:
+
+```java
+// Compiles fine!
+final List myList = List.of(1,2,3);
+
+// Type is now myList : List
+ Below is a collection of
+ my projects, blog
+ posts and some random things by
+ me or others. If you'd like to get in touch about anything, send
+ me a mail at mail@[this domain] or ping me on IRC or Twitter.
+
+
+
diff --git a/users/tazjin/homepage/static/favicon.webp b/users/tazjin/homepage/static/favicon.webp
new file mode 100644
index 0000000000..f99c908534
Binary files /dev/null and b/users/tazjin/homepage/static/favicon.webp differ
diff --git a/users/tazjin/homepage/static/img/nixery/dominator.webp b/users/tazjin/homepage/static/img/nixery/dominator.webp
new file mode 100644
index 0000000000..2d8569a6ca
Binary files /dev/null and b/users/tazjin/homepage/static/img/nixery/dominator.webp differ
diff --git a/users/tazjin/homepage/static/img/nixery/example_extra.webp b/users/tazjin/homepage/static/img/nixery/example_extra.webp
new file mode 100644
index 0000000000..101f0f633a
Binary files /dev/null and b/users/tazjin/homepage/static/img/nixery/example_extra.webp differ
diff --git a/users/tazjin/homepage/static/img/nixery/example_plain.webp b/users/tazjin/homepage/static/img/nixery/example_plain.webp
new file mode 100644
index 0000000000..a2b90b3e21
Binary files /dev/null and b/users/tazjin/homepage/static/img/nixery/example_plain.webp differ
diff --git a/users/tazjin/homepage/static/img/nixery/ideal_layout.webp b/users/tazjin/homepage/static/img/nixery/ideal_layout.webp
new file mode 100644
index 0000000000..0e9f745566
Binary files /dev/null and b/users/tazjin/homepage/static/img/nixery/ideal_layout.webp differ
diff --git a/users/tazjin/homepage/static/img/watchblob_1.webp b/users/tazjin/homepage/static/img/watchblob_1.webp
new file mode 100644
index 0000000000..27e588e1a1
Binary files /dev/null and b/users/tazjin/homepage/static/img/watchblob_1.webp differ
diff --git a/users/tazjin/homepage/static/img/watchblob_2.webp b/users/tazjin/homepage/static/img/watchblob_2.webp
new file mode 100644
index 0000000000..b2dea98b4f
Binary files /dev/null and b/users/tazjin/homepage/static/img/watchblob_2.webp differ
diff --git a/users/tazjin/homepage/static/img/watchblob_3.webp b/users/tazjin/homepage/static/img/watchblob_3.webp
new file mode 100644
index 0000000000..99b49373b5
Binary files /dev/null and b/users/tazjin/homepage/static/img/watchblob_3.webp differ
diff --git a/users/tazjin/homepage/static/img/watchblob_4.webp b/users/tazjin/homepage/static/img/watchblob_4.webp
new file mode 100644
index 0000000000..41dbdb6be1
Binary files /dev/null and b/users/tazjin/homepage/static/img/watchblob_4.webp differ
diff --git a/users/tazjin/homepage/static/img/watchblob_5.webp b/users/tazjin/homepage/static/img/watchblob_5.webp
new file mode 100644
index 0000000000..c42a4ce1bc
Binary files /dev/null and b/users/tazjin/homepage/static/img/watchblob_5.webp differ
diff --git a/users/tazjin/homepage/static/img/watchblob_6.webp b/users/tazjin/homepage/static/img/watchblob_6.webp
new file mode 100644
index 0000000000..1440761859
Binary files /dev/null and b/users/tazjin/homepage/static/img/watchblob_6.webp differ
diff --git a/users/tazjin/homepage/static/jetbrains-mono-bold-italic.woff2 b/users/tazjin/homepage/static/jetbrains-mono-bold-italic.woff2
new file mode 100644
index 0000000000..34b5c69ae1
Binary files /dev/null and b/users/tazjin/homepage/static/jetbrains-mono-bold-italic.woff2 differ
diff --git a/users/tazjin/homepage/static/jetbrains-mono-bold.woff2 b/users/tazjin/homepage/static/jetbrains-mono-bold.woff2
new file mode 100644
index 0000000000..84a008af7e
Binary files /dev/null and b/users/tazjin/homepage/static/jetbrains-mono-bold.woff2 differ
diff --git a/users/tazjin/homepage/static/jetbrains-mono-italic.woff2 b/users/tazjin/homepage/static/jetbrains-mono-italic.woff2
new file mode 100644
index 0000000000..85fd468789
Binary files /dev/null and b/users/tazjin/homepage/static/jetbrains-mono-italic.woff2 differ
diff --git a/users/tazjin/homepage/static/jetbrains-mono.woff2 b/users/tazjin/homepage/static/jetbrains-mono.woff2
new file mode 100644
index 0000000000..d5b94cb9e7
Binary files /dev/null and b/users/tazjin/homepage/static/jetbrains-mono.woff2 differ
diff --git a/users/tazjin/homepage/static/tazjin.css b/users/tazjin/homepage/static/tazjin.css
new file mode 100644
index 0000000000..aea4d426ea
--- /dev/null
+++ b/users/tazjin/homepage/static/tazjin.css
@@ -0,0 +1,183 @@
+/* Jetbrains Mono font from https://www.jetbrains.com/lp/mono/
+ licensed under Apache 2.0. Thanks, Jetbrains! */
+@font-face {
+ font-family: jetbrains-mono;
+ src: url(jetbrains-mono.woff2);
+}
+
+@font-face {
+ font-family: jetbrains-mono;
+ font-weight: bold;
+ src: url(jetbrains-mono-bold.woff2);
+}
+
+@font-face {
+ font-family: jetbrains-mono;
+ font-style: italic;
+ src: url(jetbrains-mono-italic.woff2);
+}
+
+@font-face {
+ font-family: jetbrains-mono;
+ font-weight: bold;
+ font-style: italic;
+ src: url(jetbrains-mono-bold-italic.woff2);
+}
+
+/* Generic-purpose styling */
+
+body {
+ max-width: 800px;
+ margin: 40px auto;
+ line-height: 1.6;
+ font-size: 18px;
+ padding: 0 10px;
+ font-family: jetbrains-mono, monospace;
+}
+
+p, a :not(.uncoloured-link) {
+ color: inherit;
+}
+
+h1, h2, h3 {
+ line-height: 1.2
+}
+
+/* Homepage styling */
+
+.dark {
+ background-color: #181818;
+ color: #e4e4ef;
+}
+
+.dark-link, .interblag-title {
+ color: #96a6c8;
+}
+
+.entry-container {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+}
+
+.interblag-title {
+ text-decoration: none;
+}
+
+.entry {
+ width: 42%;
+ margin: 5px;
+ padding-left: 7px;
+ padding-right: 5px;
+ border: 2px solid;
+ border-radius: 5px;
+ flex-grow: 1;
+ text-decoration: none;
+}
+
+.misc {
+ color: #73c936;
+ border-color: #73c936;
+}
+
+.blog {
+ color: #268bd2;
+ border-color: #268bd2;
+}
+
+.project {
+ color: #ff4f58;
+ border-color: #ff4f58;
+}
+
+.entry-title {
+ color: inherit !important;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+.entry-date {
+ font-style: italic;
+}
+
+/* Blog styling */
+
+.light {
+ color: #383838;
+}
+
+.blog-title {
+ color: inherit;
+ text-decoration: none;
+}
+
+.footer {
+ text-align: right;
+}
+
+.date {
+ text-align: right;
+ font-style: italic;
+ float: right;
+}
+
+.inline {
+ display: inline;
+}
+
+.lod {
+ text-align: center;
+}
+
+.uncoloured-link {
+ color: inherit;
+}
+
+pre {
+ width: 100%;
+ overflow: auto;
+}
+
+img {
+ max-width: 100%;
+}
+
+.cheddar-callout {
+ display: block;
+ padding: 10px;
+}
+
+.cheddar-question {
+ color: #3367d6;
+ background-color: #e8f0fe;
+}
+
+.cheddar-todo {
+ color: #616161;
+ background-color: #eeeeee;
+}
+
+.cheddar-tip {
+ color: #00796b;
+ background-color: #e0f2f1;
+}
+
+.cheddar-warning {
+ color: #a52714;
+ background-color: #fbe9e7;
+}
+
+kbd {
+ background-color: #eee;
+ border-radius: 3px;
+ border: 1px solid #b4b4b4;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset;
+ color: #333;
+ display: inline-block;
+ font-size: .85em;
+ font-weight: 700;
+ line-height: 1;
+ padding: 2px 4px;
+ white-space: nowrap;
+}
diff --git a/web/blog/.skip-subtree b/web/blog/.skip-subtree
deleted file mode 100644
index e7fa50d49b..0000000000
--- a/web/blog/.skip-subtree
+++ /dev/null
@@ -1 +0,0 @@
-Subdirectories contain blog posts and static assets only
diff --git a/web/blog/default.nix b/web/blog/default.nix
deleted file mode 100644
index d2f04aaea5..0000000000
--- a/web/blog/default.nix
+++ /dev/null
@@ -1,59 +0,0 @@
-# This creates the static files that make up my blog from the Markdown
-# files in this repository.
-#
-# All blog posts are rendered from Markdown by cheddar.
-{ depot, lib, ... }@args:
-
-with depot.nix.yants;
-
-let
- inherit (builtins) filter hasAttr map;
-
- # Type definition for a single blog post.
- post = struct "blog-post" {
- key = string; #
- title = string;
- date = int;
-
- # Path to the Markdown file containing the post content.
- content = path;
-
- # Should this post be included in the index? (defaults to true)
- listed = option bool;
-
- # Is this a draft? (adds a banner indicating that the link should
- # not be shared)
- draft = option bool;
-
- # Previously each post title had a numeric ID. For these numeric
- # IDs, redirects are generated so that old URLs stay compatible.
- oldKey = option string;
- };
-
- posts = list post (import ./posts.nix);
- fragments = import ./fragments.nix args;
-
- rendered = depot.third_party.runCommandNoCC "tazjins-blog" {} ''
- mkdir -p $out
-
- ${lib.concatStringsSep "\n" (map (post:
- "cp ${fragments.renderPost post} $out/${post.key}.html"
- ) posts)}
- '';
-
- includePost = post: !(fragments.isDraft post) && !(fragments.isUnlisted post);
-in {
- inherit post rendered;
- static = ./static;
-
- # Only include listed posts
- posts = filter includePost posts;
-
- # Generate embeddable nginx configuration for redirects from old post URLs
- oldRedirects = lib.concatStringsSep "\n" (map (post: ''
- location ~* ^(/en)?/${post.oldKey} {
- # TODO(tazjin): 301 once this works
- return 302 https://tazj.in/blog/${post.key};
- }
- '') (filter (hasAttr "oldKey") posts));
-}
diff --git a/web/blog/fragments.nix b/web/blog/fragments.nix
deleted file mode 100644
index 18416e4c4d..0000000000
--- a/web/blog/fragments.nix
+++ /dev/null
@@ -1,96 +0,0 @@
-# This file defines various fragments of the blog, such as the header
-# and footer, as functions that receive arguments to be templated into
-# them.
-#
-# An entire post is rendered by `renderPost`, which assembles the
-# fragments together in a runCommand execution.
-#
-# The post index is generated by //web/homepage, not by this code.
-{ depot, lib, ... }:
-
-let
- inherit (builtins) filter map hasAttr replaceStrings toFile;
- inherit (depot.third_party) runCommandNoCC writeText;
-
- # Generate a post list for all listed, non-draft posts.
- isDraft = post: (hasAttr "draft" post) && post.draft;
- isUnlisted = post: (hasAttr "listed" post) && !post.listed;
-
- escape = replaceStrings [ "<" ">" "&" "'" ] [ "<" ">" "&" "'" ];
-
- header = title: ''
-
-
-
-
-
-
-
-
- tazjin's blog: ${escape title}
-
-
-
-
- Note: This post is unlisted! Please do not share
- the link to it without asking me first.
-
-
- '';
-
- renderPost = post: runCommandNoCC "${post.key}.html" {} ''
- cat ${toFile "header.html" (header post.title)} > $out
-
- # Write the post title & date
- echo '
${escape post.title}
' >> $out
- echo '' >> $out
-
- ${
- # Add a warning to draft/unlisted posts to make it clear that
- # people should not share the post.
-
- if (isDraft post) then "cat ${draftWarning} >> $out"
- else if (isUnlisted post) then "cat ${unlistedWarning} >> $out"
- else "# Your ads could be here?"
- }
-
- # Write the actual post through cheddar's about-filter mechanism
- cat ${post.content} | ${depot.tools.cheddar}/bin/cheddar --about-filter ${post.content} >> $out
- echo '' >> $out
-
- cat ${toFile "footer.html" footer} >> $out
- '';
-in {
- inherit renderPost isDraft isUnlisted;
-}
diff --git a/web/blog/posts.nix b/web/blog/posts.nix
deleted file mode 100644
index b43598d013..0000000000
--- a/web/blog/posts.nix
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file defines all the blog posts.
-[
- {
- key = "emacs-is-underrated";
- title = "Emacs is the most underrated tool";
- date = 1581286656;
- content = ./posts/emacs-is-underrated.md;
- draft = true;
- }
- {
- key = "best-tools";
- title = "tazjin's best tools";
- date = 1576800001;
- content = ./posts/best-tools.md;
- }
- {
- key = "nixery-layers";
- title = "Nixery: Improved Layering Design";
- date = 1565391600;
- content = ./posts/nixery-layers.md;
- }
- {
- key = "reversing-watchguard-vpn";
- title = "Reverse-engineering WatchGuard Mobile VPN";
- date = 1486830338;
- content = ./posts/reversing-watchguard-vpn.md;
- oldKey = "1486830338";
- }
- {
- key = "make-object-t-again";
- title = "Make Object Again!";
- date = 1476807384;
- content = ./posts/make-object-t-again.md;
- oldKey = "1476807384";
- }
- {
- key = "the-smu-problem";
- title = "The SMU-problem of messaging apps";
- date = 1450354078;
- content =./posts/the-smu-problem.md;
- oldKey = "1450354078";
- }
- {
- key = "sick-in-sweden";
- title = "Being sick in Sweden";
- date = 1423995834;
- content = ./posts/sick-in-sweden.md;
- oldKey = "1423995834";
- }
- {
- key = "nsa-zettabytes";
- title = "The NSA's 5 zettabytes of data";
- date = 1375310627;
- content = ./posts/nsa-zettabytes.md;
- oldKey = "1375310627";
- }
-]
diff --git a/web/blog/posts/best-tools.md b/web/blog/posts/best-tools.md
deleted file mode 100644
index e4bad8f4cd..0000000000
--- a/web/blog/posts/best-tools.md
+++ /dev/null
@@ -1,160 +0,0 @@
-In the spirit of various other "Which X do you use?"-pages I thought it would be
-fun to have a little post here that describes which tools I've found to work
-well for myself.
-
-When I say "tools" here, it's not about software - it's about real, physical
-tools!
-
-If something goes on this list that's because I think it's seriously a
-best-in-class type of product.
-
-
-- [Media & Tech](#media--tech)
- - [Keyboard](#keyboard)
- - [Speakers](#speakers)
- - [Headphones](#headphones)
- - [Earphones](#earphones)
- - [Phone](#phone)
-- [Other stuff](#other-stuff)
- - [Toothbrush](#toothbrush)
- - [Shavers](#shavers)
- - [Shoulder bag](#shoulder-bag)
- - [Wallet](#wallet)
-
-
----------
-
-# Media & Tech
-
-## Keyboard
-
-The best keyboard that money will buy you at the moment is the [Kinesis
-Advantage][advantage]. There's a variety of contoured & similarly shaped
-keyboards on the market, but the Kinesis is the only one I've tried that has
-properly implemented the keywell concept.
-
-I struggle with RSI issues and the Kinesis actually makes it possible for me to
-type for longer periods of time, which always leads to extra discomfort on
-laptop keyboards and such.
-
-Honestly, the Kinesis is probably the best piece of equipment on this entire
-list. I own several of them and there will probably be more in the future. They
-last forever and your wrists will thank you in the future, even if you do not
-suffer from RSI yet.
-
-[advantage]: https://kinesis-ergo.com/shop/advantage2/
-
-## Speakers
-
-The speakers that I've hooked up to my audio setup (including both record player
-& Chromecast / TV) are the [Teufel Motiv 2][motiv-2]. I've had these for over a
-decade and they're incredibly good, but unfortunately Teufel no longer makes
-them.
-
-It's possible to grab a pair on eBay occasionally, so keep an eye out if you're
-interested!
-
-[motiv-2]: https://www.teufelaudio.com/uk/pc/motiv-2-p167.html
-
-## Headphones
-
-I use the [Bose QC35][qc35] (note: link goes to a newer generation than the one
-I own) for their outstanding noise cancelling functionality and decent sound.
-
-When I first bought them I didn't expect them to end up on this list as the
-firmware had issues that made them only barely usable, but Bose has managed to
-iron these problems out over time.
-
-I avoid using Bluetooth when outside and fortunately the QC35 come with an
-optional cable that you can plug into any good old 3.5mm jack.
-
-[qc35]: https://www.bose.co.uk/en_gb/products/headphones/over_ear_headphones/quietcomfort-35-wireless-ii.html
-
-### Earphones
-
-Actually, to follow up on the above - most of the time I'm not using (over-ear)
-headphones, but (in-ear) earphones - specifically the (**wired!!!**) [Apple
-EarPods][earpods].
-
-Apple will probably stop selling these soon because they've gotten into the
-habit of cancelling all of their good products, so I have a stash of these
-around. You will usually find no fewer than 3-4 of them lying around in my
-flat.
-
-[earpods]: https://www.apple.com/uk/shop/product/MNHF2ZM/A/earpods-with-35mm-headphone-plug
-
-## Phone
-
-The best phone I have used in recent years is the [iPhone SE][se]. It was the
-*last* phone that had a reasonable size (up to 4") *and* a 3.5mm headphone jack.
-
-Unfortunately, it runs iOS. Despite owning a whole bunch of SEs, I have finally
-moved on to an Android phone that is only moderately larger (still by an
-annoying amount), but does at least have a headphone jack: The [Samsung Galaxy
-S10e][s10e].
-
-It has pretty good hardware and I can almost reach 70% of the screen, which is
-better than other phones out there right now. Unfortunately it runs Samsung's
-impossible-to-remove bloatware on top of Android, but that is still less
-annoying to use than iOS.
-
-QUESTION: This is the only item on this list for which I am actively seeking a
-replacement, so if you have any tips about new phones that might fit these
-criteria that I've missed please let me know!
-
-[se]: https://en.wikipedia.org/wiki/IPhone_SE
-[s10e]: https://www.phonearena.com/phones/Samsung-Galaxy-S10e_id11114
-
-# Other stuff
-
-## Toothbrush
-
-The [Philips Sonicare][sonicare] (note: link goes to a newer generation than
-mine) is excellent and well worth its money.
-
-I've had it for a few years and whereas I occasionally had minor teeth issues
-before, they seem to be mostly gone now. According to my dentist the state of my
-teeth is now usually pretty good and I draw a direct correlation back to this
-thing.
-
-The newer generations come with flashy features like apps and probably more
-LEDs, but I suspect that those can just be ignored.
-
-[sonicare]: https://www.philips.co.uk/c-m-pe/electric-toothbrushes
-
-## Shavers
-
-The [Philipps SensoTouch 3D][sensotouch] is excellent. Super-comfortable close
-face shave in no time and leaves absolutely no mess around, as far as I can
-tell! I've had this for ~5 years and it's not showing any signs of aging yet.
-
-Another bonus is that its battery time is effectively infinite. I've never had
-to worry when bringing it on a longer trip!
-
-[sensotouch]: https://www.philips.co.uk/c-p/1250X_40/norelco-sensotouch-3d-wet-and-dry-electric-razor-with-precision-trimmer
-
-## Shoulder bag
-
-When I moved to London I wanted to stop using backpacks most of the time, as
-those are just annoying to deal with when commuting on the tube.
-
-To work around this I wanted a good shoulder bag with a vertical format (to save
-space), but it turned out that there's very few of those around that reach any
-kind of quality standard.
-
-The one I settled on is the [Waterfield Muzetto][muzetto] leather bag. It's one
-of those things that comes with a bit of a price tag attached, but it's well
-worth it!
-
-[muzetto]: https://www.sfbags.com/collections/shoulder-messenger-bags/products/muzetto-leather-bag
-
-## Wallet
-
-My wallet is the [Bellroy Slim Sleeve][slim-sleeve]. I don't carry cash unless
-I'm attending an event in Germany and this wallet fits that lifestyle perfectly.
-
-It's near indestructible, looks great, is very slim and fits a ton of cards,
-business cards, receipts and whatever else you want to be lugging around with
-you!
-
-[slim-sleeve]: https://bellroy.com/products/slim-sleeve-wallet/default/charcoal
diff --git a/web/blog/posts/emacs-is-underrated.md b/web/blog/posts/emacs-is-underrated.md
deleted file mode 100644
index afb8dc889e..0000000000
--- a/web/blog/posts/emacs-is-underrated.md
+++ /dev/null
@@ -1,233 +0,0 @@
-TIP: Hello, and thanks for offering to review my draft! This post
-intends to convey to people what the point of Emacs is. Not to convert
-them to use it, but at least with opening their minds to the
-possibility that it might contain valuable things. I don't know if I'm
-on track in the right direction, and your input will help me figure it
-out. Thanks!
-
-TODO(tazjin): Restructure sections: Intro -> Introspectability (and
-story) -> text-based UIs (which lead to fluidity, muscle memory across
-programs and "translatability" of workflows) -> Outro. It needs more
-flow!
-
-TODO(tazjin): Highlight more that it's not about editing: People can
-derive useful things from Emacs by just using magit/org/notmuch/etc.!
-
-TODO(tazjin): Note that there's value in trying Emacs even if people
-don't end up using it, similar to how learning languages like Lisp or
-Haskell helps grow as a programmer even without using them day-to-day.
-
-*Real post starts below!*
-
----------
-
-There are two kinds of people: Those who use Emacs, and those who
-think it is a text editor. This post is aimed at those in the second
-category.
-
-Emacs is the most critical piece of software I run. My [Emacs
-configuration][emacs-config] has steadily evolved for almost a decade.
-Emacs is my window manager, mail client, terminal, git client,
-information management system and - perhaps unsurprisingly - text
-editor.
-
-Before going into why I chose to invest so much into this program,
-follow me along on a little thought experiment:
-
-----------
-
-Lets say you use a proprietary spreadsheet program. You find that
-there are features in it that *almost, but not quite* do what you
-want.
-
-What can you do? You can file a feature request to the company that
-makes it and hope they listen, but for the likes of Apple and
-Microsoft chances are they won't and there is nothing you can do.
-
-Let's say you are also running an open-source program for image
-manipulation. You again find that some of its features are subtly
-different from what you would want them to do.
-
-Things look a bit different this time - after all, the program is
-open-source! You can go and fetch its source code, figure out its
-internal structure and wrangle various layers of code into submission
-until you find the piece that implements the functionality you want to
-change. If you know the language it is written in; you can modify the
-feature.
-
-Now all that's left is figuring out its build system[^1], building and
-installing it and moving over to the new version.
-
-Realistically you are not going to do this much in the real world. The
-friction to contributing to projects, especially complex ones, is
-often quite high. For minor inconveniences, you might often find
-yourself just shrugging and working around them.
-
-What if it didn't have to be this way?
-
--------------
-
-One of the core properties of Emacs is that it is *introspective* and
-*self-documenting*.
-
-For example: A few years ago, I had just switched over to using
-[EXWM][], the Emacs X Window Manager. To launch applications I was
-using an Emacs program called Helm that let me select installed
-programs interactively and press RET to execute them.
-
-This was very useful - until I discovered that if I tried to open a
-second terminal window, it would display an error:
-
- Error: urxvt is already running
-
-Had this been dmenu, I might have had to go through the whole process
-described above to fix the issue. But it wasn't dmenu - it was an
-Emacs program, and I did the following things:
-
-1. I pressed C-h k[^2] (which means "please tell me what
- the following key does"), followed by s-d (which was my
- keybinding for launching programs).
-
-2. Emacs displayed a new buffer saying, roughly:
-
- ```
- s-d runs the command helm-run-external-command (found in global-map),
- which is an interactive autoloaded compiled Lisp function in
- ‘.../helm-external.el’.
-
- It is bound to s-d.
- ```
-
- I clicked on the filename.
-
-3. Emacs opened the file and jumped to the definition of
- `helm-run-external-command`. After a few seconds of reading through
- the code, I found this snippet:
-
- ```lisp
- (if (get-process proc)
- (if helm-raise-command
- (shell-command (format helm-raise-command real-com))
- (error "Error: %s is already running" real-com))
- ;; ... the actual code to launch programs followed below ...
- )
- ```
-
-4. I deleted the outer if-expression which implemented the behaviour I
- didn't want, pressed C-M-x to reload the code and saved
- the file.
-
-The whole process took maybe a minute, and the problem was now gone.
-
-Emacs isn't just "open-source", it actively encourages the user to
-modify it, discover what to modify and experiment while it is running.
-
-In some sense it is like the experience of the old Lisp machines, a
-paradigm that we have completely forgotten.
-
----------------
-
-Circling back to my opening statement: If Emacs is not a text editor,
-then what *is* it?
-
-The Emacs website says this:
-
-> [Emacs] is an interpreter for Emacs Lisp, a dialect of the Lisp
-> programming language with extensions to support text editing
-
-The core of Emacs implements the language and the functionality needed
-to evaluate and run it, as well as various primitives for user
-interface construction such as buffers, windows and frames.
-
-Every other feature of Emacs is implemented *in Emacs Lisp*.
-
-The Emacs distribution ships with rudimentary text editing
-functionality (and some language-specific support for the most popular
-languages), but it also brings with it two IRC clients, a Tetris
-implementation, a text-mode web browser, [org-mode][] and many other
-tools.
-
-Outside of the core distribution there is a myriad of available
-programs for Emacs: [magit][] (the famous git porcelain), text-based
-[HTTP clients][], even interactive [Kubernetes frontends][k8s].
-
-What all of these tools have in common is that they use text-based
-user interfaces (UI elements like images are used only sparingly in
-Emacs), and that they can be introspected and composed like everything
-else in Emacs.
-
-If magit does not expose a git flag I need, it's trivial to add. If I
-want a keybinding to jump from a buffer showing me a Kubernetes pod to
-a magit buffer for the source code of the container, it only takes a
-few lines of Emacs Lisp to implement.
-
-As proficiency with Emacs Lisp ramps up, the environment becomes
-malleable like clay and evolves along with the user's taste and needs.
-Muscle memory learned for one program translates seamlessly to others,
-and the overall effect is an improvement in *workflow fluidity* that
-is difficult to overstate.
-
-Also, workflows based on Emacs are *stable*. Moving my window
-management to Emacs has meant that I'm not subject to the whim of some
-third-party developer changing my window layouting features (as they
-often do on MacOS).
-
-To illustrate this: Emacs has development history back to the 1970s,
-continuous git history that survived multiple VCS migrations [since
-1985][first-commit] (that's 22 years before git itself was released!)
-and there is code[^3] implementing interactive functionality that has
-survived unmodified in Emacs *since then*.
-
----------------
-
-Now, what is the point of this post?
-
-I decided to write this after a recent [tweet][] by @IanColdwater (in
-the context of todo-management apps):
-
-> The fact that it's 2020 and the most viable answer to this appears
-> to be Emacs might be the saddest thing I've ever heard
-
-What bothers me is that people see this as *sad*. Emacs being around
-for this long and still being unparalleled for many of the UX
-paradigms implemented by its programs is, in my book, incredible - and
-not sad.
-
-How many other paradigms have survived this long? How many other tools
-still have fervent followers, amazing [developer tooling][] and a
-[vibrant ecosystem][] at this age?
-
-Steve Yegge [said it best][babel][^5]: Emacs has the Quality Without a
-Name.
-
-What I wish you, the reader, should take away from this post is the
-following:
-
-TODO(tazjin): Figure out what people should take away from this post.
-I need to sleep on it. It's something about not dismissing tools just
-because of their age, urging them to explore paradigms that might seem
-unfamiliar and so on. Ideas welcome.
-
----------------
-
-[^1]: Wouldn't it be a joy if every project just used Nix? I digress ...
-[^2]: These are keyboard shortcuts written in [Emacs Key Notation][ekn].
-[^3]: For example, [functionality for online memes][studly] that
- wouldn't be invented for decades to come!
-[^4]: ... and some things wrong, but that is an issue for a separate post!
-[^5]: And I really *do* urge you to read that post's section on Emacs.
-
-[emacs-config]: https://git.tazj.in/tree/tools/emacs
-[EXWM]: https://github.com/ch11ng/exwm
-[helm]: https://github.com/emacs-helm/helm
-[ekn]: https://www.gnu.org/software/emacs/manual/html_node/efaq/Basic-keys.html
-[org-mode]: https://orgmode.org/
-[magit]: https://magit.vc
-[HTTP clients]: https://github.com/pashky/restclient.el
-[k8s]: https://github.com/jypma/kubectl
-[first-commit]: http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=ce5584125c44a1a2fbb46e810459c50b227a95e2
-[studly]: http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=47bdd84a0a9d20aab934482a64b84d0db63e7532
-[tweet]: https://twitter.com/IanColdwater/status/1220824466525229056
-[developer tooling]: https://github.com/alphapapa/emacs-package-dev-handbook
-[vibrant ecosystem]: https://github.com/emacs-tw/awesome-emacs
-[babel]: https://sites.google.com/site/steveyegge2/tour-de-babel#TOC-Lisp
diff --git a/web/blog/posts/make-object-t-again.md b/web/blog/posts/make-object-t-again.md
deleted file mode 100644
index 420b57c0fd..0000000000
--- a/web/blog/posts/make-object-t-again.md
+++ /dev/null
@@ -1,98 +0,0 @@
-A few minutes ago I found myself debugging a strange Java issue related
-to Jackson, one of the most common Java JSON serialization libraries.
-
-The gist of the issue was that a short wrapper using some types from
-[Javaslang](http://www.javaslang.io/) was causing unexpected problems:
-
-```java
-public Try readValue(String json, TypeReference type) {
- return Try.of(() -> objectMapper.readValue(json, type));
-}
-```
-
-The signature of this function was based on the original Jackson
-`readValue` type signature:
-
-```java
-public T readValue(String content, TypeReference valueTypeRef)
-```
-
-While happily using my wrapper function I suddenly got an unexpected
-error telling me that `Object` is incompatible with the type I was
-asking Jackson to de-serialize, which got me to re-evaluate the above
-type signature again.
-
-Lets look for a second at some code that will *happily compile* if you
-are using Jackson\'s own `readValue`:
-
-```java
-// This shouldn't compile!
-Long l = objectMapper.readValue("\"foo\"", new TypeReference(){});
-```
-
-As you can see there we ask Jackson to decode the JSON into a `String`
-as enclosed in the `TypeReference`, but assign the result to a `Long`.
-And it compiles. And it failes at runtime with
-`java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long`.
-Huh?
-
-Looking at the Jackson `readValue` implementation it becomes clear
-what\'s going on here:
-
-```java
-@SuppressWarnings({ "unchecked", "rawtypes" })
-public T readValue(String content, TypeReference valueTypeRef)
- throws IOException, JsonParseException, JsonMappingException
-{
- return (T) _readMapAndClose(/* whatever */);
-}
-```
-
-The function is parameterised over the type `T`, however the only place
-where `T` occurs in the signature is in the parameter declaration and
-the function return type. Java will happily let you use generic
-functions and types without specifying type parameters:
-
-```java
-// Compiles fine!
-final List myList = List.of(1,2,3);
-
-// Type is now myList : List
- Below is a collection of
- my projects, blog
- posts and some random things by
- me or others. If you'd like to get in touch about anything, send
- me a mail at mail@[this domain] or ping me on IRC or Twitter.
-