Notes on
building things.
Short, practical write-ups on building with AI, Next.js, Shopify, the MERN stack and React Native — plus the occasional lesson from shipping on a deadline.
Short, practical write-ups on building with AI — and shipping on a deadline.
How I Actually Build With AI — and Where I Still Do the Work
The honest version of an AI-accelerated workflow: what gets generated, what gets rewritten, and the review discipline that keeps fast from meaning fragile.
Shipping an MVP in 19 Days Without Shipping Garbage
A real 19-day build of an AI research assistant: what got scoped out, what got generated, and the four things that never get cut no matter the deadline.
RAG That Actually Answers: Chunking, Reranking and Citations
Most bad AI answers are bad retrieval, not a bad model. The chunking, reranking and citation changes that moved accuracy most on a production assistant.
How Much Does It Cost to Build an AI Feature in 2026?
What an AI chat, search or extraction feature actually costs to build and to run — build fees, token spend, and the infrastructure most quotes leave out.
Why AI Is a Module on a Real App, Never a Stack of Its Own
AI-first architectures fall over the moment you need auth, billing or an audit trail. The case for bolting AI onto a boring, well-built application.
Validating Every LLM Tool Call With Zod
The model will eventually return a malformed tool call. The Zod schema layer that turns that from a corrupted database into a logged retry.
AI Booking Systems for Clinics, Salons and Trades
A booking assistant that checks real availability and books the slot — and the architecture rule that stops it double-booking your calendar.
Per-User AI Cost Logging: Finding the Account Burning Your Budget
What to log on every model call, and the query that finds the one user costing more than their whole plan is worth.
Streaming AI Responses Without Thrashing Your UI
Token streaming that stays smooth: batching updates, avoiding layout shift, and handling a dropped connection mid-answer.
Semantic Search With pgvector Before You Buy a Vector Database
Postgres handles semantic search for most products. When pgvector is enough, how to index it, and where a dedicated vector database earns its cost.
Provider-Agnostic AI: Swapping Models Without a Rewrite
The adapter layer that let a production app move between Claude, GPT and Groq by changing one file — and the four things it has to normalise.
Document Extraction Pipelines That Survive Messy Input
Turning PDFs, scans and inconsistent forms into structured data — with validation, confidence scores and a human review path that makes it trustworthy.
Rate Limiting an AI Feature So One User Cannot Drain the Budget
Per-user, per-org and global limits for AI endpoints — and why degrading gracefully beats returning an error the user cannot act on.
Evaluating an AI Feature Before You Trust It
A test set, a scoring method and a regression check — so a prompt change cannot quietly make your answers worse without anyone noticing.
Semantic Search That Understands What People Meant
Why keyword search fails on natural questions, what semantic search costs to add to an existing product, and when it is the wrong answer.
Prompt Versioning and Why Prompts Belong in Git
A prompt is code. Storing it in a dashboard means no review, no history, and no way to tell what changed when quality dropped.
The Four Setups I Start Every Project From
Landing, web app, B2B multi-tenant or AI app — the three questions that decide which a project gets, and why picking wrong is expensive.
How Much Does an MVP Cost in 2026?
What an MVP actually costs by scope, what drives the number up, and the features that get cut first without hurting the launch.
Supabase or Neon + Clerk? The Org Model Test
One vendor for database, auth and storage, or best-of-breed pieces. The single question about your organisation model that settles it.
Sharing TypeScript Types From Database to UI
One source of truth for your data shapes, so the compiler catches a mismatch between API and UI before a user does.
Database Design That Survives Version Two
The schema decisions that are cheap now and expensive in six months, and how to tell them apart before you commit.
Multi-Tenant Data Isolation in Prisma and Postgres
Shared schema, schema-per-tenant or database-per-tenant — and the middleware that stops a missing where clause leaking another customer’s data.
The Staging Environment Is Not Optional
What shipping straight to production actually costs, and the twenty minutes of setup that prevents it.
CI That Type-Checks and Tests on Every Push
A pipeline that catches the class of bug that reaches production most often, in under sixty lines of config.
Automated Backups With a Restore You Have Actually Tested
An untested backup is not a backup. The restore drill that takes an hour and the failure it prevents.
Auth, Billing and Onboarding Out of the Box
The three systems every product needs and nobody wants to pay for twice — built once, reused on every project.
Handing Over a Project So the Client Owns Everything
The accounts and access that belong in the client’s name from day one, and the handover document that stops the late-night support calls.
What a Discovery Call Should Actually Cover
Thirty minutes, and the questions that decide whether a quote is realistic or fiction.
Uptime Monitoring Versus Error Tracking
They catch different outages. Running only one is how a site stays down all weekend without anyone knowing.
Testing the Paths That Actually Break
Not 100% coverage. The handful of flows where a regression costs real money, and how to cover them cheaply.
Spam Protection on Every Public Form
Stopping bot submissions without making a human prove they are one — honeypots, Turnstile, rate limits and server-side verification.
Feature Flags Without a Platform
Shipping unfinished work safely with a database table and twenty lines of code, before paying for a flag service.
Role-Based Access Control in Next.js and Express
Where the permission check belongs, why hiding a button is not access control, and the one file that stops roles becoming a nest of if statements.
Stripe Webhooks That Do Not Double-Charge
Stripe sends the same event twice, out of order, and to an endpoint that timed out. The handler shape that survives all three without granting twice.
Supabase Row Level Security Without the Foot-Guns
The policies that actually hold, the service role key that quietly bypasses all of them, and why an unindexed policy turns a fast query into a slow one.
Why Your Password Reset Email Lands in Spam
SPF, DKIM and DMARC in the order they actually have to be set up, plus the subdomain decision that keeps a marketing blast from killing your login emails.
Database Branching in Neon, and What It Actually Fixes
A branch per pull request with production-shaped data, why it makes migration review possible, and the two ways it quietly leaks customer records.
Schema Migrations That Do Not Take the Site Down
The expand-and-contract pattern, which ALTER statements take an exclusive lock, and why the dangerous part of a rename is the deploy rather than the SQL.
Cloudflare R2 vs S3: Where the Bill Actually Comes From
Zero egress fees is the headline. The decision is really about egress volume, ecosystem depth and how much of your architecture assumes AWS is nearby.
REST API Design Decisions That Age Well
Pagination, errors, versioning and partial updates — the four choices that are trivial before launch and permanent afterwards.
MongoDB Schema and Index Decisions That Do Not Age Badly
Embed or reference, the compound index rule that decides whether a query is fast, and the unbounded array that eventually breaks a document.
Direct File Uploads With Signed URLs, Done Safely
The browser uploads straight to storage and your server never holds the bytes — plus the four checks that stop a signed URL being an open write endpoint.
Idempotency Keys: Making Retries Safe on Your Own API
A timeout tells the client nothing about whether the work happened. Idempotency keys are how a retry becomes safe instead of a second order.
Background Jobs: Which Queue, and When You Need One
Postgres table, Redis queue or hosted service — and the four properties that decide which one, starting with whether you need a queue at all.
Running Background Workers and Cron Jobs on Render
Background workers, cron jobs and the free-tier spin-down that quietly stops them — the practical setup for the always-on half of a serverless stack.
Rate Limiting at the Edge, Before It Reaches Your Server
Why the limit belongs in front of your origin, which algorithm to pick, and the identity question that decides whether it works at all.
When to Automate With n8n and When to Write the Code
Workflow tools are excellent glue and poor application logic. The line between the two, and how to keep automations from becoming untested production code.
Astro or Next.js: Picking by What the Page Has to Do
Not a benchmark. The question is whether your pages are documents or an application — and what it costs when you answer it wrong.
Astro Islands: Shipping Interactivity Without Shipping a Framework
Which client directive to use and when, the state problem nobody mentions, and why most islands turn out not to need a framework at all.
GSAP and Lenis Together, Without Breaking Scroll
Smooth scroll and scroll-triggered animation fight over the same number. Wiring them properly, and the accessibility work that is not optional.
Respecting prefers-reduced-motion Properly
The global override that misses half your animations, why animation does not inherit, and how to check a whole site in ten minutes.
A Fluid Spacing Scale That Replaces Ten Breakpoints
One clamp per step instead of a media query per component — plus the self-referential custom property that silently flattens a whole stylesheet.
The Contrast Audit That Found 300 Failing Elements
One grey token failed AA across an entire site. How to find that, why the same grey passes on white and fails on a panel, and how to stop it recurring.
Killing Every Third-Party CSS Request
Two render-blocking hops to other people's servers, removed. Self-hosted fonts with the right preload, and icons as inline SVG instead of a webfont.
A Design System Small Enough That People Use It
Tokens, four primitives and a rule about inline styles. What to build, what to skip, and the signs a system has quietly stopped being used.
Why 100vh Puts Your CTA Underneath the Nav
svh, dvh and lvh explained by what breaks, plus the fixed bottom bar that no viewport unit knows about and the shorter lede a phone actually needs.
Writing Your Own Portable Text Renderer
Portable Text stores each list item as a sibling, so naive rendering gives one list per bullet. That and four other things the format does not tell you.
Stop Stacking Cards One Per Row on Mobile
Two-up grids on a 375px screen, the CSS that handles an odd card, and why a page 26 screens long is a design problem rather than a content one.
Forms That Work Without a Framework
Labels, error announcement, autocomplete and the keyboard a phone shows — the plain HTML most form libraries reimplement badly.
Structuring Tokens So Dark Mode Is Possible Later
Semantic tokens over literal ones, the two-layer split that makes a second theme a data change, and an honest case for not shipping dark mode at all.
The Table of Contents That Points at Nothing
Two slugifiers agree on most headings and disagree on the ones with punctuation. One function, used by both the renderer and the contents list.
Scroll-Stacking Cards That Do Not Reverse on Mobile
A sticky cascade needs more height than a phone has, so the last cards pin above their own resting position and the effect silently runs backwards.
An Icon System a CMS Can Author
Inline SVG keyed on the class strings a CMS already stores, a missing icon that renders nothing, and the script that stops paths being pasted by hand.
Core Web Vitals in Next.js: The Handful of Changes That Move the Number
LCP is usually one image, INP is usually one handler, and CLS is usually one element with no reserved space. Fixing those beats a rewrite.
Getting CLS to Near Zero by Reserving Space
Every shift is something arriving into space nobody reserved. Aspect ratios, font metrics, and the banner that pushes the page down mid-read.
Cloudflare Pages or Vercel: Deciding by What You Deploy
Both serve static files fast. The decision is about runtime, framework fit and what happens when the bill scales — not about which edge is closer.
Bundle Splitting That Actually Changes the Number
Splitting moves bytes around; it does not remove them. What to split, what to delete instead, and why the shared chunk grows quietly.
Images Are the Performance Problem
Format, dimensions, the sizes attribute nobody sets, and why build-time optimisation beats an on-demand service for most sites.
Field Data vs Lab Data: Which Number Do You Trust?
Lighthouse says 98 and Search Console says the page is failing. Both are right. Here is what each measurement is for and which one decides.
What Third-Party Scripts Actually Cost You
A tag manager, a chat widget and two analytics scripts can outweigh your entire application. How to measure the damage and what to do about each one.
Lazy-Loading the Heavy Libraries Nobody Uses
A PDF generator, a chart library and an editor in your main bundle serve a fraction of visits. How to move them behind the click that needs them.
Prefetch on Hover: Navigation That Feels Instant
A pointer arrives at a link about 200ms before the click. That gap is enough to load the next page — if you spend it carefully and not on everything.
Headless Chrome for Social Cards and Visual Checks
Generating per-route social cards from real HTML, plus the screenshot helper I use to verify layout work — and the colour bug that fools both.
Is Headless Shopify Worth It? An Honest Answer
Going headless cut one store’s load time by 58% and lifted mobile conversion 24%. It also cost more to build and more to run. When that trade makes sense.
Where Ecommerce Conversion Actually Leaks
Most stores lose more revenue between the product page and the cart than anywhere else — and fix the homepage instead. Where to look, in order.
Making a Shopify Theme Fast Without Going Headless
Most slow Shopify stores are slow for four reasons, none of them Shopify. A day of the right work usually beats a quarter of rebuilding.
Custom Theme or Premium Theme? How I Decide
A £300 theme covers most stores completely. A custom build is right for a narrow set of them. The deciding factor is usually not what people think.
The CRO Loop: How Conversion Work Actually Runs
Measure, hypothesise, build, test, decide, repeat. The loop is simple and almost every team breaks it in the same three places.
A/B Testing a Shopify Store with PostHog
Feature flags, experiments and session recordings on a Liquid theme — without a dedicated testing tool, and without the flicker that ruins the result.
What Actually Belongs on a Product Page
The page that decides the sale, element by element — in the order a buyer needs them, and with the things that only add weight left out.
Product Schema on Shopify, Done Properly
Rich results need structured data that matches the page exactly. Most Shopify themes emit something close enough to look fine and wrong enough to fail.
Figma to Shopify Without Losing the Design
A design that looks perfect in Figma and wrong in the theme editor failed at handoff, not at build. What the file needs before anyone writes Liquid.
How Much of Shopify Checkout Can You Change?
Less than you want and more than you think. What is configurable, what needs Plus, what needs an extension, and what you should not touch at all.
Reading an Experiment Result Without Fooling Yourself
The test finished and the number is green. Here is what to check before you ship it, and the ways a result can be real and still not repeat.
Metafields Without Slowing the Store Down
Custom product data is how a Shopify store stops looking generic. It is also how a collection page ends up making four hundred lookups per render.
Shopify Subscriptions: What Nobody Warns You About
Recurring revenue is the easiest thing to sell internally and the hardest to run. The failure modes are operational, not technical — here they are.
Building Offline-First in React Native
An app that needs a connection to show data the user already owns is broken on a train. Local-first storage, sync, and the conflicts nobody plans for.
Native App or PWA? The Decision in Practice
Most people asking for an app need a fast mobile site. Some genuinely need the store. The question that separates them is not technical.
Expo in Production: What It Solves and What It Does Not
Expo is no longer the beginner option you outgrow. Here is what it actually removes from a React Native project, and where it still bites.
Gestures at 60fps in React Native
A drag that lags by two frames feels broken in a way users cannot name. Keeping animation off the JavaScript thread is the whole technique.
Push Notifications Are Not Guaranteed Delivery
Every layer between your server and a phone can drop a notification silently. Design for that, and ask for the permission at the right moment.
One API, Two Clients: Sharing Between Web and Mobile
Share the contract, the types and the validation. Share the interface layer and you get something slightly wrong on both platforms.
Why Nobody Opens Your App a Second Time
Most apps lose the majority of users within a week, and most of that happens in the first session. What actually causes it, and what fixes it.
The App Store Rejections You Can Avoid
Most first submissions are rejected, and most rejections are for the same handful of things. Here they are, with what to do before you submit.
Where Auth Tokens Belong on a Phone
AsyncStorage is a plain file on disk. Keychain and Keystore exist for exactly this, and the difference matters more than most teams assume.
Deep Linking That Works From a Cold Start
A link that opens the right screen when the app is already running, and the home screen when it is not, is the standard half-finished implementation.
How I Scope a Project Before Quoting It
Most projects that go wrong were mis-scoped, not mis-built. The questions that surface the real work, and what to do with the answers.
A Development Process Without the Ceremony
Six steps from first message to production. What each one is actually for, and why most process overhead solves problems small teams do not have.
Pricing Work When AI Makes You Faster
If you bill by the hour and the hours halve, you have given yourself a pay cut for getting better. What to charge for instead.
Positioning as AI-Accelerated, Not an AI Consultancy
One says you deliver faster. The other says you sell AI. They attract different clients, and only one of them survives the tooling changing again.
Choose Your Stack Once, Then Stop
Every project that starts with a technology debate loses a week. Four templates decided in advance, and the narrow cases where you deviate.
The Objections You Get, and What They Actually Mean
"It is too expensive" is rarely about the price. The eight objections that recur, what is underneath each one, and how to answer honestly.
Documentation That Survives You Leaving
Most project documentation describes what the code does, which the code already says. What is missing is why, and who has the passwords.
Working Across Time Zones Without Losing Your Evenings
A large time difference is an advantage if the work is structured for it and a slow disaster if it is not. What actually has to change.
Everything I Have Learned About Estimating
You are not bad at estimating the work. You are bad at remembering everything that is not the work — and that is the recoverable part.
The Projects Worth Turning Down
Every bad project was visible in the first conversation. The signals, what they cost when ignored, and how to say no without burning anything.