A follow-up to my earlier article on AI-assisted coding, describing my move from autocomplete tools to agentic coding with Cline, Claude Code, and Gemini CLI. I cover token costs, comparisons between Claude, OpenAI, DeepSeek, and Gemini models, and practical tips such as plan-then-act workflows, guardrails, and keeping context lean...
A walkthrough of end-to-end testing a web app with Cypress, which I demonstrate against a small Express app with customers and orders. I cover installing Cypress, writing tests for navigation, deletions and cascading deletes, element selection with data-test attributes, custom assertions using invoke and then, running tests in the browser, and handling state resets between runs...
I take a look at JavaScript’s reduce() method, walking through how the accumulator works with examples like summing and finding the maximum in an array, and explaining why reduce counts as a “functional” array method...
A look at Node’s built-in test runner from my perspective as a long-time Mocha and Chai user, showing how to write and run basic tests with node:test and node:assert. Coming from Mocha requires few changes, though test files need to live in a test directory to be picked up. I weigh the convenience of a bundled runner against lock-in to a particular runtime...
I reflect on my use of LLMs for coding, weighing concerns about training data, accuracy, energy use, and data leakage against the practical benefits. I describe trying GitHub Copilot, Codeium, and local models via Ollama, and settling on Codeium for code completion alongside web chatbots for code discussions. I also cover how AI has changed my practice, including writing clearer code, favoring well-established technologies, and adopting new libraries more readily...
The ‘show all’ button on The Rest Is History podcast’s episodes page is broken, and there’s no JSON endpoint behind the player, so the episode list has to be scraped from the page’s HTML. Using Cheerio, a jQuery-like library for the server, I show how to select the playlist’s list items and extract each episode’s title and link, ending with a complete working script...
After choosing the tiny BusyBox httpd server for containerised websites, I encountered third-party benchmarks suggesting NGINX was dramatically faster. Running my own A/B tests with Apache’s ab tool initially gave misleading results, which turned out to be NGINX Proxy Manager serving cached responses. With cache-busting requests, BusyBox and NGINX performed similarly over the network, so I am sticking with the 1.35MB BusyBox containers over the roughly 49MB NGINX-alpine images...
A step-by-step guide to moving my domain registration from WordPress.com to Porkbun, motivated by my unease over recent WordPress drama. I cover the transfer process—including a required 60-day wait, disabling the transfer lock, and a gotcha where private registration had to be turned off before the authorization code would work—plus copying DNS records and switching nameservers. In a closing update, I note that WordPress later blocked external domain pointing, pushing me toward self-hosting...
Hosting UptimeKuma on Fly.io’s free tier, I find that updating an out-of-date container image requires nothing more than running fly deploy with an existing fly.toml file. After the update the app starts crashing from memory exhaustion, and switching to a lighter Alpine-based image appears to keep usage within the free instance’s 256MB limit...
A BusyBox container serving a static site can’t fetch content over HTTPS because BusyBox ships without root CA certificates and has no package manager to install them. Rather than switch to a larger Alpine image, I settle on bind-mounting the host’s certificate directory into the container read-only, with example configurations for both docker-compose and docker run...
A follow-up on bundling static sites into BusyBox Docker containers, covering how to handle minor dynamic tasks such as periodically downloading an image into the directory of hosted static files. Rather than using cron, which behaves unexpectedly on BusyBox, my solution is a shell script with a download-and-sleep loop that runs in the background alongside the httpd server. I also note that BusyBox’s wget has TLS problems, a topic I defer to a later post...
Serving static websites from small Docker containers built on BusyBox httpd, coming in at around 4MB each. I walk through the Dockerfile setup, cross-platform builds from an M1 Mac to linux/amd64, pushing to the GitHub Container Registry, and deploying via docker-compose behind Nginx Proxy Manager, including DNS and SSL configuration...
My routine npm update, triggered by a GitHub security advisory, runs into the cryptic “Exit handler never called!” error. Alongside a refresher on what package-lock.json and npm update do, my fix is to confirm the lock file is at fault using npm install –no-package-lock, then delete it and regenerate it with a fresh npm install, followed by retesting and rebuilding any artifacts...
I walk through publishing my own JavaScript utility to npm so it can be installed and updated like any other package, rather than copying source files between Node projects. I cover creating an npm account, scoping the package name to my username, writing and publishing the code with npm publish, and installing it in another project, using a simple is-even example...
A beginner-friendly walkthrough of enabling file uploads in a Node/Express web app using the multer middleware. I cover setting up a basic Express server, configuring multer’s disk storage, and submitting files via an HTML form with multipart/form-data encoding, before briefly noting production concerns like sanitizing filenames and restricting file size and type...
I walk through building user authentication in an Express.js app from the ground up, starting with how HTTP requests, cookies, and sessions work before moving to session IDs and the express-session library. I then cover a login flow with bcrypt-hashed passwords and file-based session persistence, laying groundwork for a future post that will use Passport.js...
I survey the rise of AI coding tools, from ChatGPT and GitHub Copilot to open source ecosystems, alongside skeptic concerns about training data, code quality, model collapse, and code exfiltration. I explain why these assistants suit my situation as an experienced developer new to modern languages, and trace my journey from paid Copilot to the free Codium and finally to running local models via Ollama and the Continue VSCode extension to keep client code private...
A first-draft Dockerfile for my Node project, and how I keep the resulting image tidy by inspecting its contents with an interactive bash shell and adding entries to .dockerignore. I also explain my preference for copying everything over explicitly listing files, citing debugging time and security...
I take a look at using NGINX as a reverse proxy in front of self-hosted services, and at NGINX Proxy Manager, a project that adds a web GUI to the process and simplifies obtaining Let’s Encrypt certificates. I cover setup via Docker, along with a brief comparison of alternatives such as HAProxy, Caddy, and Traefik...
I walk through turning my small Node.js Markdown server into a Docker image, explaining the Dockerfile line by line, building the image locally, and pushing it to Docker Hub. I finish with a sample docker-compose file so self-hosters can deploy the app with a single command...