CASE STUDY · 2026

linx

A two-sided marketplace for short-term rental turnovers. Owners post the clean between one guest and the next, vetted local cleaners bid, and the owner awards the job.

Role
Requirements, data model and build, solo, with an AI coding agent
Status
Launch readiness
Stack
FastAPI, SQLAlchemy 2.0, Alembic, PostgreSQL, React 18, Vite, Tailwind, Stripe Connect
Tests
900+ automated tests gate every change
Diagram of one turnover moving from posted to bids, awarded, done and paid
How one turnover moves through linx, and what each of the three roles can do.

THE IDEA

A standing relationship, not a one-off lead

Rental hosts need a reliable cleaner in the window between checkout and the next check-in, and local cleaners want steady work without paying for leads. linx keeps it to one category and one region at launch: owners post turnovers, cleared cleaners bid, and the owner hires.

It is a separate codebase from BrightBase on purpose. Nothing imports from or depends on the cleaning company’s system.

HOW IT WORKS

One turnover, start to finish

  1. 01PostThe owner sets checkout and the next check-in for a property
  2. 02BenchUrgency is worked out on the server from the gap between guests
  3. 03BidVetted cleaners within their own service radius name a price
  4. 04AwardThe owner hires one cleaner; the address opens up to them only
  5. 05PayThe owner pays on Stripe’s page and the cleaner’s share transfers
  6. 06ReviewBoth sides review; neither sees the other’s until both are in

DECISIONS

Five choices and what each cost

Address withheld until the award

Open jobs show the area, not the street address or access notes. Those open to the hired cleaner and close again the moment the award ends.

COSTCleaners bid knowing the area and the job, not the exact house.

Awards taken under a row lock

The check and the write happen under one database lock, so two owners accepting at the same moment cannot both win.

COSTAwards on the same job wait their turn, a fair trade at this volume.

The bidding gate lives in Postgres

Whether a cleaner can take jobs is computed by the database from the vetting and background-check statuses. No screen or API call can override it.

COSTChanging the rule is a migration, not a settings toggle.

One Stripe charge settles both sides

A destination charge pays the cleaner’s Stripe Express account and takes the platform fee in the same transaction. Every Stripe call carries an idempotency key from a database id, and the attempt is written down before the call.

COSTEvery cleaner has to finish Stripe onboarding before their first payout.

A closed list of notifications

Fifteen events, each recorded in the same transaction as the change that caused it, with a unique key so a retry can never send twice.

COSTAdding an event takes a migration and a failing test, which is the point.

STATUS

Where it stands

900+automated tests
14tables, built by migrations
15notification events

Built

  • Owner, cleaner and admin roles enforced on the server
  • Properties, turnovers, bidding and awards
  • Admin vetting queue with ID, reference and background check
  • Cancellations and no-shows that put the job back on the bench
  • Stripe Connect payments, admin-only refunds and mutual reviews

Before launch

  • A launch runbook of decisions only a person can make
  • Stripe Connect tax reporting switched on before the first live payout
  • Opening the first region to real owners and cleaners