Writing
Articles
Notes from client and personal projects — mostly WordPress, performance and the occasional detour into whatever broke this week.
Filter by topic
25 articles
Your In-Memory Cache Is Lying to You on Serverless
A Map in module scope really does persist between requests — on that instance, until it is reclaimed, alongside however many other copies are running. The four things people put there, ranked by how badly each fails.
- Architecture
- Reliability
The Print Stylesheet Nobody Writes
Print now mostly means save as PDF, which is how a page gets emailed to an accountant or attached to an application. What breaks — dark themes, fixed headers, viewport units, and the content hidden behind a toggle.
- CSS
- Accessibility
Receiving Webhooks Without Losing Events
A webhook endpoint is a public URL with no session behind it that changes your data. Verifying raw bytes, answering before you work, and why delivery is at-least-once rather than exactly-once.
- APIs
- Reliability
The Documentation That Replaces the Handover Call
Most project docs explain what the system does, which the code already says, and skip why it does it that way, which the code cannot. Written for someone competent, on day one, with nobody to ask.
- Process
- Remote work
The Form Problems That Only Show Up in Internal Tools
Forty fields, filled in forty times a day, editing a record someone else may also have open. Losing work, mapping server errors onto fields, and the select box with ten thousand options.
- Dashboards
- Forms
Why Your Contact Form Email Lands in Spam
Almost always one line: the visitor's address in the From header. That is your server claiming to be a domain it has no authority over, which is exactly what DMARC exists to stop.
- Forms
- Reliability
The Admin Table Is the Hardest Screen in Your Dashboard
It looks like the easy part and it is the only screen whose cost grows with the business. Client-side filtering that does not degrade, offset pagination that drifts, and a row count that is often the slowest thing on the page.
- Dashboards
- Performance
The Five States Every Screen Has, and the Two Nobody Designs
Complaints are never about the button. They are about the blank two seconds, the form that seemed to save, the empty page a new user landed on. Those are not missing components — they are missing states.
- Dashboards
- Architecture
Customising CS-Cart Without Losing the Ability to Upgrade
An upgrade replaces core files rather than merging them, so a change made in one is not at risk — it is guaranteed to be deleted, silently. How to customise heavily and still stay current.
- E-commerce
- Architecture
Your CSP Says unsafe-inline. Here Is What That Costs.
Blocking inline scripts is most of what a Content Security Policy is for, because injected XSS is almost always inline. Why so many policies give that up anyway, and the two ways to take it back.
- Security
- Architecture
What an NFC Attendance System Actually Has to Handle
Reading the card takes a weekend. Modelling identity so cards can be lost, surviving an offline reader, and being honest that a tap records a card rather than a person — that is the project.
- Research
- Architecture
Prerendering a React Site Without Adopting a Framework
A plain Vite build ships an empty div. You can get real HTML out of it in about forty lines, keep your setup, and skip hydration entirely — as long as you know which trade you are making.
- Performance
- Architecture
Scroll-Driven CSS Animations Without Stranding Your Content
animation-timeline replaces a pile of IntersectionObserver code with a few lines of CSS. It also has a failure mode you will never see in your own browser, because unsupported browsers fall back to a time-based clock.
- CSS
- Accessibility
- Performance
Your Phone Is Still Downloading the Desktop Effects
CSS hides the pixels, not the JavaScript. Gating two decorative libraries behind the breakpoint the stylesheet already used cut this site's mobile payload by about two thirds — with the real numbers.
- Performance
- CSS
99% Accurate and Still Wrong: What Face Recognition Benchmarks Do Not Tell You
Every model quotes an accuracy figure above 99%. Almost nobody explains why yours will be worse — the threshold you pick, the size of the gallery you search, and whose faces the benchmark was built from.
- Research
- Reliability
Access Control That Holds: Roles, Permissions and Where to Check Them
Permissions have to stay correct in code nobody has written yet. Why capability checks beat role checks, why scoping belongs in the query rather than the view, and the defaults that quietly grant access.
- Security
- Architecture
Migrating a Busy WooCommerce Store to HPOS Without Downtime
High-Performance Order Storage has been the default for new WooCommerce installs since 8.2 — but an upgraded store keeps the old one, and the version number won't tell you which you're on. The order of operations that makes the switch boring.
- WordPress
- E-commerce
Building a Multi-Vendor Marketplace: What the Comparison Posts Leave Out
Every guide compares plugins on features and price. Six months in, none of that is what hurts. What actually decides the stack is money that is not yours, shipping that is not one parcel, and the vendors themselves.
- E-commerce
- Architecture
Stopping Contact Form Spam Without a CAPTCHA
A honeypot, a minimum fill time and a rate limit stop the overwhelming majority of form spam, cost a real visitor nothing, and send no data to a third party. Including the parts that go wrong — starting with the honeypot that traps screen reader users.
- Security
- Forms
- Accessibility
Checkout Bugs Are Not Like Other Bugs
Payment and shipping code fails differently: the customer finds it before you do, the damage is money, and you often can't just deploy a fix and move on. What that changes about how you write it.
- E-commerce
- Reliability
Real-Time Without the Mess: What a WebSocket Actually Costs You
A WebSocket is easy to open and hard to keep honest. The reconnection, the gap while you were away, and why I'd usually send 'something changed' instead of the change itself.
- APIs
- TypeScript
- Architecture
What Breaks First When a WooCommerce Store Gets Busy
WooCommerce handles real traffic fine. What falls over is everything built around the assumption that it wouldn't — here's what goes first, and the order I'd fix it in.
- WordPress
- E-commerce
- Performance
Where TypeScript Stops: The API Boundary From Both Sides
TypeScript checks nothing about what the server actually sent. Where the types stop being true against an untyped backend, what belongs at that boundary — and the point at which defending in every client is the wrong answer and the boundary should move.
- APIs
- TypeScript
- Architecture
Twelve Hours Out of Sync: Working From Bali for Teams in the US and Australia
What actually makes a twelve-hour time difference workable — not tooling, but a handful of habits about how questions get asked and how work gets handed over.
- Remote work
- Process
Why Your WordPress + Elementor Site Feels Slow (And How to Actually Fix It)
A practical, no-fluff guide to speeding up WordPress sites built with Elementor — what actually causes the slowdown, and the fixes that make a measurable difference.
- WordPress
- Performance