jfhr's blog
Hi, I write blog posts about software development and little else. If you enjoy this blog, feel free to say hello :)
HTTP security headers on error pages
Security-related header fields that are set through Apache or nginx configuration files may be missing on error pages without extra configuration.
Streaming HTML inside the DOM
Shows a way to stream HTML from a remote server and add it inside an existing DOM.
Ways to reset an HTML form
It's possible to reset a form after submission, through a user interaction, or arbitrarily with JavaScript.
GitHub Copilot and HTTP form injection
GitHub uses an auto-generated code snippet on its homepage to advertise its AI programming assistant Copilot. However, that code snippet is vulnerable to accidental injection of form values. This post shows how that injection works and how it can be avoided.
HTML, NPF and other markup formats
I've recently published html2tumblr, a website that converts HTML into posts on the blogging service tumblr. While tumblr used to allow its users to submit posts as HTML, it has since switched to an alternative format called NPF.
Sorting a JavaScript array of objects by a property value
JavaScript's built-in Array.prototype.sort function can be difficult to use. A small helper function can make it easier.
Fungible Tokens and Decentralized Exchanges
This post tries to explain the fundamentals of fungible tokens, how they work and what they're used for.
Consider using CSV
JSON is a common data format for modern APIs. However, depending on what your data looks like, CSV might be a better choice.
Talking to yourself
Why I talk to myself and why you might also want to.
Estimate Firestore collection count from a small sample of documents
This article shows a method of estimating the number of documents in a Firestore collection by reading only a small number of documents. It works if all documents in the collection use Firestore auto-IDs.
Strict Transport Security and preloading
You've probably heard that HTTPS makes websites more secure. That's true, but HTTPS has some limitations, and Strict Transport Security and Preloading are ways you can overcome those limitations.
What is an eTLD + 1?
In short, an eTLD + 1 is the part of the web address that tells you who owns a website. What does that mean and how exactly can you find it? This post answers these questions.
New Blog Design + Performance Improvements
Tl;dr this blog now has a (slightly) new design, a dark mode, and better loading performance.
Smart Contracts: a (mildly) practical example
This post is a short introduction to smart contracts: How they work, what you can do with them, and how to develop and interact with one.
Optimizing images with the CSS image-set() function
I previously blogged about optimizing images with the HTML <picture> tag. You can use the image-set() function to get equivalent behavior in CSS.
Optimizing images with the HTML picture tag
If you have a website, you probably want it to be fast. One common reason why websites aren’t fast is because they have a lot of images. Images take time to load. Generally, the browser will load your website, find out that it contains a bunch of images, and start loading those as well. You can optimize that with HTTP/2 Server Push. Another optimization is to simply make your images smaller, without sacrificing quality - that’s what this post is about.
Test Email sending with cypress
The company I work for uses its own little email newsletter software. I wanted to write an automated test to make sure that newsletter sending works correctly. In the spirit of full e2e testing, that meant verifying that newsletters are actually sent out, and that the unsubscribe link at the bottom of every email works correctly. Turns out, that's not as easy as it sounds.
HTTP/2 Server Push and Cache-Digest
Server Push is a feature in HTTP/2 that can make websites more efficient. This post is about how it works, how you can implement it - and why it is so rarely used.
Build automation with JavaScript and zx
zx is an open-source tool by google for creating server-side scripts with JavaScript. In this post I'll talk a bit about what it does, and how and why I use it in several projects to automate builds.
The DeconstruCT.F 2021
I played in the DeconstruCT.F 2021 with ps1ttacus! It's a little late, but these are my writeups for the web challenges I solved.
The Down Under CTF 2021
I was spontaneously invited to play on the DownUnderCTF 2021 by ps1ttacus.
The most important thing I learned: CTF's are fun! I'm glad I participated and want to say a big thank you to the organizers. In this post I share writeups of the challenges I solved.
How to really know if your webapp is online
If you search for "check online JavaScript", you'll quickly come across the navigator.onLine property. Unsurprisingly, it returns true if you're online, and false if you aren't. In addition, the window.ononline and window.onoffline events notify you whenever that value changes.
False positives
If it was quite this easy, I wouldn't be sitting here writing a blog post about it. In fact, if we look at the spec, we find the following...
document.designMode
document.designMode = "on";
This single line of JavaScript makes an entire webpage editable. Try it out here...
Mighty
I've recently read about the project Mighty. Tl;dr, it's stadia for the web browser. Mighty runs Chrome on their server and streams it to your device, promising better performance and less battery use. Sounds interesting, and I'll definitely try it once it's available - but there are some things I want to talk about.
Start an app with Angular 12 and Bootstrap 5
Learn how to quickly create a web-app with Angular 12 and Bootstrap 5.
Start an app with Angular 12 and Bootstrap 4
Learn how to quickly create a web-app with Angular 12 and Bootstrap 4.
Light and dark themes with Angular, Bootstrap and SASS
Let's say you have an Angular single-page app and use Bootstrap for styling. You want to let your users choose between multiple themes (e.g. a light and dark theme). You also want the option to use custom SASS for each theme, as well as for all themes at once.
The solution
...