The whole stack. One person.
Modern web apps with a CMS your team can actually use. Researched with the people who will use them, then designed, built, secured, hosted and run by me. Interface to DNS.
How I build
Minimal technical debt.
Every dependency, build step and moving part is a future cost to you. I only add one when it pays for itself, and I remove what stops paying. Code is linted, typed or validated at its edges, tested in CI, and documented well enough that someone else could take it over. Everything below follows from that.
Slim servers.
Small, single-purpose Node services with thin request handlers. No heavyweight runtime, no plugin pile. Several production apps share one 2GB VPS, and some have no npm dependencies at all. You get speed and a small hosting bill.
JSON throughout.
Content is structured data from a headless or JSON-backed CMS, not pages locked in a theme. Schemas are validated at the boundary with Zod or JSON Schema. The same data feeds your website, a PWA, a dashboard or another system without rework.
Server-rendered first.
HTML arrives complete, with its own title, description, canonical link and structured data. Pages are pre-rendered where the content allows. JavaScript enhances. It is never required to read the page.
Build in CI or not at all.
Servers run code. They do not build it. Where a server needs TypeScript, Node runs it directly with type stripping.
Current versions, always.
Dependencies stay on current releases. They are not left to rot until an upgrade becomes a project.
Standard and portable.
Nothing proprietary. The same app runs on a VPS, on Vercel, on Cloud Run or on Azure, and you can take it elsewhere.
The lot
Every layer, from the people using it down to the network. No subcontractors. No gaps.
-
Research and design
I find out what people need before I build it, then test it with them.
- User research
- Interviews
- Usability testing
- Prototyping
- Interaction design
- UX
- Accessibility to WCAG 2.2 AA
-
Research and data analysis
I design the study, run it, analyse the results and report them. Large datasets included.
- Study design
- Surveys
- Data analysis
- Large datasets
- Dashboards
- Reporting
- Peer-reviewed publication
-
Architecture
Designed for the job and sized to run fast on modest hardware.
- Headless CMS
- JSON APIs
- Small services
- Server rendering
- Pre-rendering
- Progressive enhancement
-
Web apps with a CMS
Your staff edit the content. Nobody phones a developer.
- Payload
- Directus
- A custom CMS written for the job
-
Interface
Hand-written where that is enough, a framework where the app warrants it.
- HTML
- CSS
- JavaScript
- React
- Next.js
- TypeScript
- Tailwind
-
Application and data
APIs, databases, and the data you already have, moved in safely.
- Node
- Express
- Fastify
- REST and JSON APIs
- Postgres
- SQLite
- Prisma
- Full-text search
- Data migrations
- Legacy imports
- Feeds to and from other systems
-
Identity
One sign-in for every app, with roles that match how your organisation works.
- Passkeys (WebAuthn)
- OIDC
- Single sign-on
- Google sign-in
- Magic links
- Role hierarchies
- Central identity service
-
Payments and ticketing
- Stripe
- Box office
- Events
- Bookings
-
Integrations
- Social media hooks
- Webhooks
- Media pipelines
- Third-party feeds
-
AI
LLM features behind a provider you can swap, with privacy designed into the schema.
- LLM features
- Swappable provider interface
- Privacy by schema
-
DevSecOps
- GitHub Actions
- Automated deploys
- Dependency patching
- Content Security Policy
- Security headers
- Secrets management
- pm2
- Docker
- Monitoring
- Health checks
-
Hosting
Several production apps on one small box.
- Linux VPS
- nginx
- Vercel
- Google Cloud
- Managed Postgres
- Backblaze B2
- Object storage behind a CDN
-
Cloudflare
- DNS
- CDN
- Caching
- TLS
- Edge protection
-
DNS and email
Your domain cannot be spoofed, and your mail arrives.
- DNS management
- Domain migrations
- SPF
- DKIM
- DMARC to p=reject
- BIMI
- MTA-STS
- Mail forwarding
- Mailing lists
- Transactional email
-
Network
- Reverse proxies
- TLS
- Private networking
- VPN (Tailscale)
- Network design
-
Policy and governance
I write the policy as well as the code.
- Data protection by design
- Accessibility
- Security policy
- Safeguarding
- Regulatory compliance
Work
A charity platform, small-business sites on custom CMSs, university systems and a public archive.
-
Solent Gay Men's Chorus
Registered charity. The whole platform, built and run by me.
- One identity service for every app, with passkey sign-in and a role hierarchy.
- Stripe payments, box office and ticket sales, and events.
- Media library on object storage behind Cloudflare.
- Social media hooks, member email and a CMS the chorus edits itself.
- Five Node services: main website, box office, governance, members portal and identity. Content in Payload.
- All five share one 2GB server behind nginx, deployed from GitHub Actions.
- Email domain at DMARC p=reject, with DKIM aligned.
-
SUMS
Blind double-marking and moderation platform for a university.
- In production since 2018, on Google Cloud with single sign-on and a full audit trail.
- About 600 projects a year: 350 undergraduate and 250 master's, plus resits and two international partner programmes. About 100 markers a year.
- More than 4,800 projects marked since 2018.
-
Student feedback platform
Commissioned by a university, designed from research with students and staff.
- Next.js, TypeScript, Postgres and Prisma.
- Anonymity is enforced by the schema: a response cannot be joined to the student who wrote it.
- LLM features sit behind a swappable provider interface.
-
Survey analysis dashboard
Adopted across a university faculty.
- Whole-institution survey results analysed in three hours.
-
geraldlarner.com
A public, searchable archive, built from a pile of old files.
- About 6,700 legacy word-processor files, covering 444 composers.
- A thin Express server over one SQLite file of pre-rendered pages, with full-text search and a JSON API.
-
alicedennis.net
Site for a piano and singing teacher. Replaced a broken legacy site.
- A custom lightweight CMS with a built-in admin page and Google sign-in, so the owner edits it herself.
- Express on my VPS.
-
morganharnett.tattoo
Site for a tattoo artist, on a custom CMS written for the job.
- It fills itself from Instagram, so the artist updates one place.
-
Photo archive for a school
Private. Built on Directus.
- Artists' photographs managed in one place so students can learn from them.
-
ASICA
Research tablet app for melanoma self-monitoring.
- Designed with patients and run in a six-month NHS pilot.
Receipts
Figures about this page, measured by the server that sent it. None of them are typed in by hand.
- Page weight
- 11.7 KB Everything this page downloads, compressed, in 4 requests. Check it yourself: page weight
- Server render
- 0.15 ms Median of the last 21 renders. 95% took under 1.1 ms. Check it yourself: Server-Timing response header (browser dev tools, Network tab)
- Server memory
- 21.6 MB What this server holds on its own, right now. Node's shared program code is not counted. Check it yourself: server memory
- Third-party requests
- 0 The content security policy lets the browser load from this domain only. Check it yourself: third-party requests
- Runtime dependencies
- 2 69 packages installed in total, counted from the lockfile. Check it yourself: runtime dependencies
- Cookies set
- 0 Out of 4 responses since the server started. Check it yourself: Application tab in your browser's dev tools
- Version
- 8d56c42 Deployed 2 October 2026 at 16:45 UTC. Check it yourself: version
- DMARC policy
- p=none Read live from DNS for passionfruit.design. Check it yourself: dmarc policy
- Security headers
- This response was served with:
Content-Security-PolicyStrict-Transport-SecurityX-Content-Type-OptionsX-Frame-OptionsReferrer-PolicyPermissions-PolicyCross-Origin-Opener-PolicyCross-Origin-Resource-PolicyCross-Origin-Embedder-PolicyOrigin-Agent-Cluster
Tell me what you need
A few lines about the project is enough. I read every message myself. Or email hello@passionfruit.design, or call or WhatsApp 07385 509278 (open WhatsApp).