Independent project. Not affiliated with NICTS or the Department of Justice.
Inside CourtWatch NIRole, engineering and verified figures
The build
A scheduled collector performs the search any member of the public could: every available date, every venue, every court tier. It runs one request at a time, 1.5 seconds apart, twice a day — so loading a page here never sends a request to a government system. Listings are normalised and validated, and where the source withholds a name CourtWatch withholds it too: suppressed matters are never entered into the search index at all, rather than filtered out afterwards.
My role
Sole developer — collector, data model, search, interface, and the privacy and legal surface around it.
A court listing records that a matter is due to be heard. It says nothing about guilt, innocence, or how a case ends.
Day rolling window
1414
Refreshes a day
22
Requests per refresh
~320~320
Trackers or cookies
00
Repository figures documented in the project index, August 2026—not live usage metrics.
01
Gentle on the source, invisible to it
Twice daily, at 05:40 and 13:10. One request at a time with a fixed 1.5-second pause — roughly 320 requests over eight minutes. Visitor traffic never reaches the government service; you read our copy.
02
Suppression is structural, not a filter
Family and domestic lists publish no case title; youth lists publish a placeholder. Suppressed matters never enter the search index, so no query can return them by name.
03
Only what is published right now
The official service serves a rolling window — today to fourteen days ahead — and refuses anything outside it. CourtWatch reads that window on every refresh and enforces the same limits in the interface and the API.
04
A mirror, not an archive
A listing disappears the moment it leaves the official window, and the record is deleted shortly after. There are no person profiles, and no history of anyone’s past appearances.
05
Search that cannot be farmed
Wildcards and operators are stripped, results are capped and cannot be paged through, queries are rate limited and never logged, and list pages are kept out of search engines.
06
Stale beats empty
If the source is unavailable the last good lists stay up, labelled with when they were read. A refresh returning unexpectedly little data is treated as a fault and is not allowed to delete anything.
Inside SchedlyRole, engineering and verified figures
The build
Schedly makes PostgreSQL the booking authority instead of trusting application code. A public booking request takes a per-resource advisory lock, re-validates availability server-side against opening hours, buffers, blocks and imported calendar busy-time, and lands behind a GiST exclusion constraint that makes an overlapping reservation physically unrepresentable.
My role
Sole developer — frontend, database schema, edge functions, billing, server configuration, deploy automation and the QA harness. 157 commits.
Stripe Connect deposits are code-complete and deployed, pending Stripe’s own platform enrolment.
Tests passing
508508
SQL migrations
108108
Edge functions
3232
RLS policies
9898
Repository figures documented in the project index, August 2026—not live usage metrics.
01
Double-booking is impossible by construction
Advisory locks and a GiST exclusion constraint enforce it in the database, so a race between two customers cannot produce two reservations.
02
Safe retries on every booking
Each request carries an idempotency key hashed with its payload — a network retry replays the original response, a changed payload under a reused key is rejected.
03
Tenant isolation enforced by Postgres
98 row-level-security policies gate every business-owned table, and triggers reject writes that exceed a plan’s resource, location or seat limits before a row exists.
04
Email that cannot double-send
A durable Postgres outbox claims rows with FOR UPDATE SKIP LOCKED, backs off exponentially over six attempts, and passes a deterministic idempotency key to the mail provider.
05
Subscriptions on live Stripe
Deploys are gated on a preflight that refuses to ship unless the Stripe key is live-mode, resolves to the expected account, and has charges and payouts enabled.
06
Calendar sync and a public booking page
Two-way Google Calendar sync, a self-serve page per business, and token-scoped links so guests can view, cancel or reschedule without an account.
Inside NebulaSMSRole, engineering and verified figures
The build
A React dashboard over an Express and TypeScript API on Supabase Postgres, with a live carrier integration behind it. Credits live in an append-only ledger whose application roles hold no UPDATE or DELETE privileges, and message segment counts are computed independently on the server so billing never trusts a number the client supplied.
My role
Sole developer — dashboard, API, database, carrier integration, security model, test suite and deployment. Every commit in the repository.
Registration is invite-only by design, so the dashboard sits behind an invite rather than open signup.
Tests passing
205205
Destination countries
245245
SQL functions
6767
Migrations
2121
Repository figures documented in the project index, August 2026—not live usage metrics.
01
Live sending, worldwide
The deployed API reports a carrier connected, sending available, and 245 allow-listed destination countries.
02
API keys that cannot be recovered
Generated from CSPRNG bytes, stored only as a server-peppered HMAC-SHA-256 digest, shown once at creation and compared with timingSafeEqual.
03
An append-only credit ledger
Reservation, exactly-once refund and adjustment run as SQL functions rather than application arithmetic — application roles get no UPDATE or DELETE on the ledger.
04
Billing that does not trust the browser
GSM 03.38 segment accounting runs twice — live in the composer for feedback, and again independently on the server for the actual credit reservation.
05
A boot-time security contract
In production the server refuses to start on a mock carrier, missing credentials, any non-HTTPS origin, a non-loopback bind address or a missing key-hash secret.
06
Text-to-speech voice alongside SMS
Voice operations run through the same platform, ledger and access-key model as messaging.
Inside WEBTIMESTWORole, engineering and verified figures
The build
Flat monthly plans from £35, one-off builds from £299, and Premium tiers that add a CMS panel, analytics and priority support. Client sites run on a purpose-built multi-tenant headless CMS, so the content a business actually changes is editable without touching the build.
My role
Founder and developer of the studio and its client sites. The CMS platform the sites run on is built by Toby Black.
Companies House No. 17313799
Pages, marketing site
1212
Plans from, per month
£35£35
One-off builds from
£299£299
Repository figures documented in the project index, August 2026—not live usage metrics.
01
One route table, no drift
Every path, page title and meta description is declared once and read back by the router, the header, all three footer columns and the SEO hook.
02
Sites that degrade gracefully
Client sites read editable content from the CMS at runtime and fall back to typed data compiled into the build, so an outage shows the real menu rather than an empty page.
03
Plans, not projects
Monthly plans cover hosting, SSL, domains, email and ongoing maintenance, so there is no separate bill every time something changes.
A site for a Bangor Indian takeaway. Both menus are typed data rendered through one search-and-filter browser, with opening hours and contact details editable from the CMS.
Lead developer, with Toby Black.
06
Schedly Discord bot
Provisioning and community bot for the Schedly Discord. Its permission auditor computes effective permissions from a live guild and asserts them — 58 of 58 checks passing.
The index you are reading. A lightweight canvas field, pinned project stories and a motion system that scales itself down on modest hardware.
Sole developer.
DESIGN / FRONTEND / DATABASE / DEPLOYMENT /ONE DEVELOPER / THE WHOLE SYSTEM /
02 / APPROACHONE DEVELOPER / THE WHOLE SYSTEM
02
Josh / Independent developer / UK
Built endto end.
I build software that has to keep working after I stop looking at it.
Independent products, a studio building websites for UK businesses, and a preference for putting hard guarantees in the database. That’s the thread running through everything here.
From making court lists readable to making double bookings impossible, I’m interested in the point where a useful idea becomes dependable software.