Homefinder
A consumer real-estate MVP for browsing seeded Bay Area listings. Shoppers search by city and filters, explore results on a Leaflet/OSM map synced with the list, open rich listing detail pages, and save favorites when signed in with Clerk. Convex powers typed listing and saved-home APIs with reactive updates—no Mapbox key, MLS feed, or agent tooling in scope.

Tech stack
- TypeScript
- Next.js
- React
- Tailwind CSS
- Convex
- Clerk
- Leaflet
Architecture
Consumer app shell
Next.js App Router covers marketing search entry, filterable browse, listing detail, and auth-gated saved homes.
- Public routes for home, search, and listing detail
- /saved protected via Clerk middleware (proxy.ts)
- Shared SiteHeader / SiteFooter and design tokens across pages
Reactive listings backend
Convex owns listings, users, and savedHomes with indexed queries for city/status filters and slug lookup.
- Clerk JWTs validated in auth.config.ts for ctx.auth
- Seed mutation bootstraps ~50 Bay Area demo homes
- Saved homes scoped per user via by_user / by_user_listing indexes
Map + list browse
Leaflet with OpenStreetMap tiles syncs price markers to the results list; optional bounds filter powers “Search this area.”
- Client-only map (dynamic import) avoids SSR issues
- Hover/selection sync between list cards and map markers
- URL-driven filters for shareable search state
Engineering highlights
Map without a paid tile API
Leaflet + OSM keeps map browse free for the MVP while still supporting area search via TypeScript bounds filtering on small seed data.
Auth-backed favorites
Save/unsave mutations ensure a Convex user from the Clerk identity, with isolation enforced by userId-scoped indexes.
URL-as-state search
City, price, beds/baths, and status live in query params so filters are shareable and refresh-safe.
End-to-end typed stack
Convex schema and return validators flow into the Next.js client for listings, search, and saved homes from database to UI.