The problem
Customers needing custom fabrication work (e.g. laser engraving) have no easy way to reach and compare local providers.
Providers lack a channel to discover nearby jobs and bid competitively, and neither side has a trusted way to transact.
The approach
Built a two-sided marketplace loop: a guided posting wizard for customers and a discovery-plus-bidding surface for providers.
Modeled the full job lifecycle as an explicit state machine and matched supply to demand geographically from zip-code centroids.
Added per-bid threaded messaging so customers and providers can negotiate before awarding.
What I built
- A Next.js 16 (App Router) application with credentials and Google OAuth authentication via NextAuth
- A five-step guided job-posting wizard (description, material/dimensions, design upload, quantity/deadline, budget/delivery)
- Provider discovery by zip code, radius, material, and keyword, using Haversine distance for geographic matching
- A bidding system with price/turnaround/message bids, accept-decline handling, and threaded per-bid messaging
- An 11-state job state machine, cursor-based pagination on list endpoints, and a guided demo mode for provider recruitment
- A PostgreSQL schema via Prisma 7 (17 models) with base and demo seed scripts, plus 90 unit tests across the modules
- Next.js 16
- TypeScript
- PostgreSQL
- Prisma 7
- NextAuth.js
- Tailwind CSS 4
- Vitest
- React Testing Library