Full-Stack SaaS · Joseph Doyle-Samadi

Knockround

A live app for UK tradespeople that runs jobs, quotes and repeat customers, then sends invoices customers pay by Apple Pay, Google Pay or card. I built it with a business partner, and it has been live at app.knockround.co.uk since October 2026. The source is private.

ReactTypeScriptHonoCloudflare WorkersD1Stripe Connect
The Knockround home page: take card and Apple Pay on every job, beside a Scan to pay screen for an £85 invoice.
knockround.co.uk, the marketing site I built. The hero shows the same Scan to pay screen the app shows on the doorstep.

Problem

What it solves

Tradespeople run their work from WhatsApp chats, notes and a banking app. Knockround keeps the next job, the next quote and the next payment in one place on the phone, for quoted work and for customers who come back on a cycle. It covers 39 trades and costs £19.99 a month after a 7-day free trial.

Main features

Feature set

  • A jobs board from enquiry to quote, booked, done and paid, with quotes customers accept on a public page.
  • Repeat customers at their own interval, a four-week calendar and the day's stops in route order on a map.
  • Numbered invoices with a Pay button, sent by WhatsApp, text or email, or shown as a QR code to scan.
  • Team logins where workers see the round but never prices or payments.
  • Spreadsheet import and export, reports, a price-rise tool and bank statement matching.

My part

Who built what

My business partner set up the monorepo, email-code sign-in, subscription billing, CI and the first version of the core screens. I designed the app and rebuilt every screen in that design, then built card payments with Stripe Connect, the offline mode, Google sign-in, onboarding across 39 trades, invoices with QR codes, referrals, the EU deployment and the security hardening.

Backend

One Worker, one deploy

  • A single Cloudflare Worker running Hono serves the API, the customer-facing quote and invoice pages and the built React app, so there's one deploy and no CORS.
  • Cloudflare D1 in the EU jurisdiction. Every table carries the owner's id and every query filters on it, and API routes need a signed-in user with an active or trialing subscription.
  • Stripe Checkout for subscriptions and Stripe Connect for tradespeople's own card payments. A verified webhook marks a paid invoice's visits paid in one transaction.
  • Every push to main runs type checks and the build, applies D1 migrations and deploys through GitHub Actions.

Reliability

Works with no signal

A service worker opens the app with what it last loaded. Visits ticked off with no signal wait on the phone, then go once when the signal is back. Sign-in codes are hashed and rate-limited, customer pages run no scripts, and payment links are compared in constant time.

Tech used

Stack

React, TypeScript and Vite on the front end, Hono on Cloudflare Workers with D1 and R2 in the EU and an hourly Cron Trigger that sends reminders in batches, Better Auth for sign-in, Stripe Checkout and Connect for payments, Resend for email, and pnpm workspaces with GitHub Actions. The marketing site is a static site on its own Worker, with 22 search pages generated from Python, structured data and IndexNow, and Lighthouse mobile scores of 98 or more in every category.

A Knockround invoice on a phone: Invoice 1001 from Dave's Plumbing for an £85 annual boiler service, with a Pay £85.00 button and Apple Pay, Google Pay and card marks. The Knockround Scan to pay screen: a QR code for £85, invoice 1001, which the customer scans to open the invoice and pay.
Real app screens: an invoice with its Pay button, and the QR code a customer scans to pay. The business and customer are made up.