my website is one binary
my website is one binary 2022-04-06 ---------------------------- a.k.a. this one weird trick that inspires me to program creatively i have struggled for years to figure out a website framework that feels good to me. i tried all of the classics, including but limited to: - ghost - hugo - jekyll - sr.ht + tarball - manual html editing i have very high and unusual standards, and none of the above felt correct to me. more importantly, none of the above excited me. i have uncovered the secret. i have discovered my path. a website that feels good. but first, the search. mY vALuES ------------- i place an extremely high value on systems that i am capable of understanding and trivially maintaining front-to-back as a single individual. i like human- friendly code that is optimized for readability, and i like extremely fast feedback loops. i like fun and cleverness and being cute too. the first recommendation people always get is "hugo." for those who aren't in the know, hugo is a "static website generator" - aka, it is a program that takes templates & markdown as input and compiles HTML that you may deploy wherever you'd like. people normally couple a static site generator (SSG) framework with some hosting platform for an ez-pz pretty reliable & fast blog. or so they say. one of my core values is maintainability. this is true of most everything that i own. from my framework laptop to my bicycle, i like to be able to get my hands dirty when things break down, and i will always prefer tools and platforms that treat users as capable and curious. i make a lot of unconventional sacrifices and people think it's weird - but the truth is that i _hate_ maintaining things. i'm extremely bad at it. but when something of mine breaks, i _need_ to be able to dig in myself, because god knows i'm not responsible enough to go through the painfully long feedback loop of having someone else help me. (i am so averse to this in my personal life that i will simply let my broken things stay broken if i cannot trivially fix them myself) hence another core value of mine - reliability. i need the thing to work today, and i need the thing to work in ten years. i spend a lot of time choosing my things, and i refuse to depend on anyone else to ensure that they continue to work. i don't care if your company went under, my car will keep working. i don't care if you end-of-life'd the product, my laptop takes generic components that i can insert myself. you get the point. so, when people say "just build your blog with hugo and host it on github pages bruh!" i am naturally very skeptical. here are some of the dependencies that hugo + github pages come with: - github pages, the service (it must remain up) - github pages, the product (it must remain viable) - hugo, the project (it has 1,200 dependencies that require constant updates) - hugo, the community (they must document the code) (i cannot read it all myself) (i have limited time and interest) - hugo, the plugin ecosystem (if you rely on any of their plugins) - hugo, the binary (it must compile your HTML in roughly the same way over time) (it must not break your website between releases) - github pages, the deployment mechanism (the ability for github to actually deploy the hugo code) - golang (it's pretty clear that golang is here to stay) it could be argued that you could use a single version of hugo forever - but in my experience that rarely works out. (i quickly run into a bug, and am forced to upgrade). nah, i won't - i tried it, i don't like it. people think that it's simple and effortless, but it's riddled with dependencies (on people, software, and companies) and winds up making me feel helpless, like my values are being violated. it took me a long time to figure out why hugo made me feel uneasy. (to be clear, i am not attacking hugo _specifically_, this is a problem that i have with most software) so, clearly, i needed a system that fit my values plain old html ------------------ i decided that i would host a website on a machine that i controlled, and program in plain old HTML, and edit everything by hand using vim. ~ * ~ and so i gave birth to the worst workflow ever used ~ * ~ the first draft of https://j3s.sh was built like this - it is where a lot of my ideas for the layout came from. the website still looks largely the same - writing HTML by hand felt a lot like doing intensive labor by hand - like dishwashing with a hand pump instead of a sink. it forced me into an insane level of minimalism in order to avoid the pain of having to use the workflow. i embedded styling directly into the HTML, made cross-site functions as minimal as possible, and shied away from much styling. in a lot of ways, this experience was exactly what i had hoped for. it was simple, reliable, and maintainable - the HTML i wrote could be reused without modification, and i felt pretty confident that my site would be around for awhile. i had no dependencies. but i grew very tired of the workflow. i wanted to handle "templating" of common functionality more efficiently. i didn't want to use a pre-existing framework. i wanted to have fun. and i wanted to leave myself a lot of room for adjustment in case i changed my mind about this-or-that. single binary website -------------------------- one afternoon, i was browsing the internet neurotically - this is typical of me. i had a sudden idea: if i wrote my website entirely in one language, i could contain and deploy it within a single binary. i have been using linux & programming for a long time, and golang is by far my favorite language to develop in, for a few reasons: - it is easily maintainable by a single person - it emphasizes few dependencies - it is a relatively simple language - there is a backwards compatability guarantee - it produces statically compiled binaries trivially - compilation speed is fast (less than 10s most of the time) - most of the standard library is very well developed (but not overdeveloped) and so i gave birth to my personal website project for j3s.sh. a single binary that serves my website. it has many amazing properties. >>> it is d y n a m i c <<< statically generated websites may seem "simple" (even though i think that most SSG frameworks are not), but dynamically generated websites are simpler. the reason i think they're simpler is because you don't need to think about arcane workarounds to generate content - you can just generate it easily, on the fly. for example, say you want to print the visiting users IP address - how would you do this on a statically generated website? to be honest i'm not sure. typically, you would scrape a header and display it. on my website, i do this: func ipHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprintf(w, r.Header.Get("X-Forwarded-For")+"\n") } four lines of code - and then i just call it with a handler: http.HandleFunc("/ip", ipHandler) simple. i could call this function wherever i need it. all i needed to research was the best way to scrape user IP addresses, and implement only that functionality. it answers "what do i want" in a very straightforward way. with a static site, i imagine you'd need to wind up with external dependencies, since you'd likely need to rely on javascript. this means adding the dep, making sure it loads, and executing it. you need to integrate the javascript on any page, and think about handling cases where javascript isn't available (some of my readership refuses to execute javascript - i don't blame them!) honestly, that sounds like a lot of toil to me, and discourages me. the dynamic solution excites me, because the website viewer simply receives HTML that has the IP address in it already. this has another nifty benefit: you can request the HTML from non-browser tools & receive a correct response (otherwise, the tool would have to understand javascript!) another example - i generate all of my RSS feeds on my homepage when my website starts up. this ensures that i get a fresh copy of my friends' latest posts. this is another dynamic thing that would be nontrivial to do statically - it would be so nontrivial that i'd probably just give up tbh. instead, i've programmed my own rss feed fetcher that will work for years and years with no maintenance. additionally, i understand exactly how it functions. i can't wait to make more little fun dynamic things just like it. >>> deployment is simple <<< i use a shell script to deploy my website. it looks like this: #!/bin/sh -eu # # deploy my website cd /home/j3s/code/j3s.sh git fetch origin if git status | grep -q behind; then git merge origin/main go build mv j3s.sh /usr/local/bin/j3s.sh service j3s.sh restart fi this script runs every minute on a cronjob, and rebuilds my site if the git repo has been updated. in this sense the deployment is automatic - i just test my code locally, upload it, and it's reflected in my public website within a minute. good enough for me. and simple enough that it'll probably just work forever. again, very few dependencies. you can read it and understand it in ten seconds if you know a little shell. beauty. you should do this too! --------------------------- i find that personal websites have a very _distinct_ feel on the web nowadays. nobody really makes personal sites anymore, so when we stumble across them they seem fun and quirky - and they can deeply reflect what the author cares about. if statically generated sites suit you, please use them! but they don't suit me. if you have values similar to mine, i strongly suggest trying a dynamic website. it's a ton of fun, you can start small, and it enables you to iterate through all manner of fun ideas! you can also write your code like shit and hardcode everything, because hey - it's yours and yours alone. that's part of the fun. make it in your favorite language! rust? perl? python? that's part of the fun too. do it because it's exciting. start small --------------- i know you're all excited now, but let's do a quick reality check. we get it, you have big ideas. you want to use the big rust framework, you want to learn elixer and implement wokesockets. google dot gov said that phoenix is the next big web framework! isn't nasa using wordpress 6.9?? stop. consider how much time you actually have. consider how much motivation you have. if you're like anyone else with a fulltime job, probably not much of either. do you think that you can keep up with any project that's continuously developed and makes breaking changes constantly? i hate to break it to you, but most people who work with those projects _full time_ can't keep up. you definitely can't in your personal time. your website will outdate itself in .2 seconds. start small. make an index.html and focus on getting your language to serve it. don't worry about RSS. don't worry about markdown. write HTML and serve it. then, as your needs increase, extend the scope using the simplest, most maintainable tools you can find - normally this means the standard library. in ruby, it might mean using Sinatra instead of Rails. in python, maybe use Gin instead of Flask. i suggest going even further - can you just do it yourself with 0 libraries? you should try - if you run into horrible blockers, you should consider using something larger at that point. but there's no reason to start with someone elses project. start with your own project. just write python. just write ruby. just write erlang. or WHATEVER! but if you start big, you'll burn out fast. that's a fact bruh. the beauty is that you'll be sitting on a plane and will have a marvelous idea for a feature - and then, you'll realize that you can pretty easily incorperate it into your personal website project. it's liberating. and so. much. fun. closing arguments --------------------- the web needs more weirdness. and more excitement. and more personality. SO GET OUT THERE AND MAKE A FUCKING DYNAMIC WEBSITE. THERE'S NOTHING STOPPING YOU. YOU WILL BE GLAD YOU DID. 10/10 WOULD RECOMMEND WITH MUCH LOVE. JES ~2022-04-01
follow me on mastodon!
last updated 2022-04-06T00:00:00.000Z