How this site works
Last checked 2026-10-07.
Hand-written HTML on a server I run, with as little as possible between you and the page. This is how it is built, what it records about visits, and what I learned setting it up.
Pages
Every page is a complete HTML file written by hand. There is no framework, no static site generator and no build step: what is in the repository is what the server sends. Since September 2026 the site no longer uses Bulma or Font Awesome. All pages share one stylesheet, and the homepage adds a second one for its own layout.
An inner page is about 10 KB of HTML, one 13 KB stylesheet and at most two 22 KB font files, before compression. Apart from the analytics below, the only JavaScript on the site is three short inline scripts: copy buttons on the Signal Proxy and Colors & type pages, and the print button on the resume.
The site is not split into English and Chinese versions. Each page is written in the language of the people most likely to read it: English for work and services, Chinese for the Tor tutorial and Taiwan's community, and both side by side where readers are mixed. Navigation is always in English, so everyone can find their way.
Color and type
Every color comes from the self-portrait on the homepage, shot in a mirror on a Lomo LC-A 120: a darkroom set for dark backgrounds and a photo-paper set for light ones. Dark mode follows your system setting, and every text color is checked to a WCAG contrast of at least 4.5:1 against its background. The brass in the photo only reached 4.15:1 on the paper color, so text uses a slightly darker brass. The palette, where each color came from, and the contrast numbers are on Colors & type.
Names and headings use Barlow Condensed, served from this site. Loading it from the Google Fonts CDN would be one line shorter, but every visit would then send your IP address to Google. Chinese text uses the fonts already on your device: a Chinese web font runs to several megabytes.
What gets counted
Two cookie-free counters run on the clearnet site: Cloudflare Web Analytics, and umami, which I host myself at aa.toomore.net, so its numbers stay on my server. Neither sets cookies or follows you to other sites. umami keeps the page, the referring site, your browser, operating system, screen size, language and country, and does not keep your IP address.
There is no Google Analytics, no advertising and no embedded third-party content. Readers of the Tor tutorial and the Signal Proxy page are often people trying to avoid being watched, and tracking them would work against what those pages are for. For the same reason, the film photos on the homepage are copies served from here, not embedded from my photo site, which loads Google Analytics.
When you follow a link from this site to another one, your browser does not tell the other site which page you came from.
This site over Tor
toomore.net is also an onion service. When you open the site in Tor Browser, the server's Onion-Location header tells the browser the onion address exists, and it offers to switch. The onion version is the same files with both analytics scripts removed on the way out, no access log, and no HSTS header, which has no meaning for an onion address. The address and why it runs as a single onion service are on the Services page.
Where it runs
The site is served by nginx on a single server, with Cloudflare in front. The server's web root is a git working copy of the site's repository, so deploying is one script: fetch the latest commit and reset to it. There is nothing to upload and nothing that can drift out of sync with the repository. The server only accepts web traffic coming through Cloudflare.
The resume PDF is generated from the resume page itself, by printing it with headless Chrome, so the web page and the PDF never disagree. The print layout lives in the same stylesheet as everything else.
Things I learned
Purging a CDN does not reach browsers
Browsers are told to keep stylesheets, images and fonts for 31 days. Purging Cloudflare's cache clears Cloudflare, but not the copy already in your browser, so after a stylesheet change returning visitors would get new HTML with old styles. Stylesheet URLs now end in ?v= and the first ten characters of a SHA-256 hash of the file, so the URL changes exactly when the contents do. A small script updates every page when a stylesheet changes. Images and fonts get a new file name instead. Pages themselves are cached for only four hours.
Dark mode can follow you onto paper
Print the resume with dark mode switched on and both the dark-mode and the print rules apply at once. In CSS the later rule wins, so the print rules have to sit at the very end of the stylesheet, or the PDF comes out with a dark background.
A bare return in nginx skips access control
nginx processes a request in phases, and return runs in the rewrite phase, before the access phase where allow and deny are checked. A return 410 for a removed page would therefore answer anyone, including clients the allowlist is meant to turn away. Fixed status codes here go through try_files to a named location instead, which runs after the access check.
An old forwarding rule can outlive the server it pointed to
The site used to be served from Amazon S3. After moving it to its own server and updating DNS, requests still reached S3. The cause was an old Cloudflare Cloud Connector rule that forwarded every request to the old bucket, ignoring DNS entirely. It does not appear with Cloudflare's page rules, origin rules or Workers, which is why it took a while to find.
Also here
- security.txt for reporting security issues
- My OpenPGP key by email address, through WKD
- A sitemap