Prompted by Manuel Schipper’s piece on technical leaders and AI, I document my current workflow for using LLMs in web development. This approach keeps context small and explicit — frequent clearing, markdown summaries passed between stages, no background agents or MCPs — supported by a personal library of prompt playbooks that encode my stack and conventions. Work proceeds in discrete stages (exploration, plan, AI and human plan review, implement, checking) so problems surface at the document level before code gets written...
Client-side JavaScript errors go unnoticed by keyword-based uptime checks like Uptime Kuma’s, which is how a broken weather widget slipped past monitoring on one of my sites. I walk through building Faultsy, a lightweight alternative to Sentry: a browser script captures uncaught errors and unhandled promise rejections, reports them to a small Node server via sendBeacon(), and exposes per-site error counts as JSON that Uptime Kuma can monitor. The project is on GitHub and still under active development...
I explain the browser’s same-origin policy, covering what counts as an origin, why the restriction exists, and how it blocks JavaScript from reading cross-origin responses. I then introduce CORS as the mechanism servers use to permit specific origins via Access-Control-Allow-Origin headers...
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...
In this tutorial, I build a user login and session management system from scratch in Node and Express, starting with a simple cookie-based session counter and progressively adding file-based persistence, user accounts, logout, and password authentication using bcrypt. I also cover input sanitisation, secure cookies, and enforcing HTTPS behind an NGINX proxy. The tutorial is aimed at readers with basic familiarity with Node and Express...
This is a write-up of an exercise from Mosh’s React 18 course: building a small expense-tracking app in React and TypeScript, with Zod used for form validation. I cover component breakdown decisions, persisting expenses to local storage, tradeoffs in TypeScript type definitions, and refactoring repeated table markup into reusable components...
I compare approaches to styling React components, including global stylesheets, inline style objects, CSS and component libraries, per-component CSS files, CSS modules, and styled-components. I demonstrate each on a simple card component, noting trade-offs such as name clashes, hover effects, and unused CSS accumulating over time. I find styled-components the most elegant but lean toward per-component CSS files to avoid extra dependencies...
My To Do app gets rebuilt in React, continuing a series that has already covered vanilla JavaScript and htmx versions backed by the same REST API. I cover React’s core ideas—components, declarative UI, and the virtual DOM—along with Vite build tooling, and walk through the app’s components, useState-based state management, and passing data via props. React’s tooling complexity and 150K of shipped JavaScript make it overkill at this scale, but I plan further React work, possibly with TypeScript...
An introduction to htmx and the hypermedia and HATEOAS concepts behind it, followed by a conversion of a simple todo app from a Node/Express setup that serves JSON and renders client-side in JavaScript to an htmx version where the server returns HTML fragments instead. I compare the two implementations and discuss when htmx makes sense, particularly for server-side developers who want to avoid writing frontend JavaScript...
The mdserver project needed page titles defined as YAML front matter inside markdown files, in the style of Jekyll and Hugo, instead of being generated from the file name. Rather than writing custom extraction code, I use Showdown’s built-in metadata support, enabled with a converter flag, and confirm the front matter leaves the HTML output unchanged...