Live product

Wrench Club

wrenchclub.com

Pre-launch Physical businessSquare API
Wrench Club screenshot

Wrench Club is a membership DIY auto shop opening in Grand Rapids in 2026: members book a hoist or flat bay by the hour and do their own work in a professionally outfitted space. The site at wrenchclub.com is the marketing front, the member portal, and the booking engine — and it runs the business, not just describes it.

The architecture bets everything on Square as the system of record. The app's own database is six tables: users, sessions, two token tables, vehicles, waitlist. Customers, bookings, orders, payments, saved cards, subscriptions and the merch catalog all live in Square. The owner adds a t-shirt in the Square Dashboard and it's on the store in five minutes with no deploy. The catch is that Square Appointments can't price a service by the hour, doesn't detect double-bookings when you create one, and offers no field linking a booking to the payment that paid for it. So the hourly price grid was materialised as 24 pre-provisioned catalog variations (three bay types × eight durations, with the eight-hour slot as a day rate); each physical bay is modelled as a Square "team member" so availability search works as a per-bay calendar; and checkout is a hand-written compensating transaction — pre-check availability, open an order, vault the card, capture the payment, create the booking, then stamp the order and payment IDs into the booking's note field so a later cancellation can find the money and refund it. If the booking fails after the card is charged, it refunds automatically and tells the member so. If the refund fails too, it escalates with the payment ID rather than swallowing it.

The unglamorous half got the same treatment. Lucia v3 sessions over Argon2id, a self-written sliding-window rate limiter, email verification and password reset, an allowlist that retroactively invalidates live sessions when pre-launch access is revoked, and an admin promotion path that's an env var instead of DB surgery. Square webhooks are signature-verified with timingSafeEqual. The OpenAPI 3.1 spec is generated from the same Zod schemas the endpoints validate against, so it cannot drift. 71 unit tests and 112 Playwright tests run against the deployed staging environment, registering a real member through a secret-gated bypass that skips only the charge. One env var — set because the detail bay is waiting on a zoning hearing — removes that bay from the bookable roster, the pricing page, the SEO meta, the JSON-LD offer catalog, and the transactional emails simultaneously. The whole thing, including the procedurally generated animated OG card, was built and tested on an Android phone under Termux, with three committed shims that make Vite, Rollup and Playwright believe they're on Linux.

  • Checkout is a compensating transaction, not a call — availability pre-check → Order → card vault → Payment → Booking, with automatic full refund if the booking fails after the charge lands, and a payment-ID escalation if the refund fails too.
  • 24 pre-provisioned Square catalog variations (3 bay types × 8 durations, $25/$30/$35 per hour) work around Square Appointments having no duration-variable pricing; a parallel 24-variation sandbox grid switches on one env var.
  • Order and payment IDs are smuggled through the booking note as [order:X|payment:Y] because Square exposes no link between them — parsed back on cancel to issue an exact-amount refund, behind a server-side ownership check.
  • First-party analytics proxy serves Umami from /_a/ with a reconstructed X-Forwarded-For chain, defeating adblock filter lists for a claimed 25-40% lift in captured sessions — and returns 204 on any upstream failure so a beacon can never break a page load.
  • 183 automated tests — 71 Vitest, 112 Playwright across 7 suites, run against deployed staging with a TEST_SECRET-gated registration bypass that is structurally impossible to trigger in production.
  • One feature flag cascades through six layers — bookable roster, pricing UI, SEO meta, JSON-LD hasOfferCatalog, and email templates — because the detail bay is blocked on a zoning hearing, not a code change.
  • Built entirely on an Android phone: committed Termux shims symlink esbuild's platform triple, swap Rollup's native binary for WASM, and monkey-patch process.platform before Playwright's registry loads.