Back home Case study · Bubble → fully coded

Bridge STAY: taking a booking marketplace off Bubble and onto a database that refuses to double-book anyone.

A from-scratch rebuild of the peer-to-peer lease marketplace I led the migration for at Split Lease — same problem space, same lessons, rebuilt clean as a portfolio-grade reference so the architecture is inspectable end to end.

Role
Full-stack developer, solo build
Stack
Astro (SSR) · Supabase · Cloudflare Workers
Surface
27 pages · guest, host, and admin
Status
Feature-complete, test-covered

The problem this rebuild answers

At Split Lease — a PropTech startup renting to recurring NYC visitors, visiting professors, and separated parents splitting custody — the product had outgrown Bubble.io. Page loads were slow, the scaling tiers got expensive fast, and every new feature meant fighting the platform's plugin constraints instead of just writing code. I led the migration: benchmarked the index page against a coded rebuild to prove the speed case, then took the team through migrating 30+ pages from Bubble into JavaScript and Supabase, consolidating desktop and mobile into one responsive layout on the way.

This project is that migration's lessons, rebuilt as a standalone reference — the same domain (proposal-based leases, host/guest roles, admin oversight), engineered the way I'd do it knowing what a marketplace like this actually breaks on: double bookings, half-finished state transitions, and admin actions nobody double-checked.

Where a booking marketplace actually breaks

Most booking-app bugs aren't in the UI — they're in what happens between two people acting on the same dates at the same time, or an admin action that only half-applies because a request failed halfway through. Three decisions in this build target exactly that:

01

Database-enforced double-booking prevention

Availability isn't checked in application code and hoped for — it's a PostgreSQL btree_gist exclusion constraint over a daterange column, with [start, end) exclusive bounds so a same-day checkout/check-in turnover doesn't false-positive as a conflict. Two proposals racing for the same dates literally cannot both commit; the database is the source of truth, not a pre-check in the API layer.

02

Server-mediated state, not client-mediated state

The full lease lifecycle — proposal → host accept → guest payment → admin review → active stay → closed — runs through atomic Postgres RPC functions (create_proposal, respond_to_proposal, admin_review_lease, close_expired_leases) rather than a chain of client-side writes. Every transition is one atomic call with its own guard rails: guests must be verified, hosts can't book their own listings, dates get re-validated server-side even if the UI already checked them.

03

Maker-checker on high-risk admin actions

Disputes above a dollar threshold and host suspensions above a payout threshold don't execute on a single admin's click — they route to a pending-approvals queue that requires a second administrator to authorize. It's the same dual-control pattern banks use for wire transfers, applied to the two admin actions in a marketplace that actually cost someone real money if fat-fingered.

The design system underneath it

27 pages across three audiences (guest, host, admin) will drift into visual chaos without a system, so the UI runs on one shared token set rather than page-by-page styling: an ink/emerald palette borrowed from the calm precision of modern fintech products (aligned columns, tabular numerals for every price and date, hairline rules instead of drop shadows), two densities on the same tokens (comfortable for guest-facing pages, compact for the admin tables), and a closed set of five button variants and one status-badge taxonomy so "pending," "verified," and "disputed" mean the same color everywhere in the app. This portfolio site borrows the same token language, tuned for a personal brand instead of a marketplace.

Result

95+
Lighthouse performance score
$0–5
Monthly hosting cost
30+
Pages migrated off Bubble
0
Client-side-only state transitions

Self-measured against the original Bubble build during the Split Lease migration, where typical Bubble page loads ran 40–50 on the same scale. The win isn't just the number — it's that the number stopped depending on which Bubble plugin was on the page that week.

The repository is private while this reference implementation keeps evolving. I'll happily walk through the schema, the RPC functions, or the admin approval flow live — reach out below.

Want the walkthrough?

Happy to screen-share the schema, the RPC layer, or the design system live.

Email rcsharath@gmail.com