Service Marketplace — A Two-Sided Matching Platform
One unified model carrying both local and skill services, from listing to order, fulfilment and review — in a multi-package monorepo with a single contract source
- Role
- Architecture and full-stack implementation (solo)
- Scale
- 3 clients · 12 core tables · one contract source
- Period
- Oct 2026 — Present
What I did
- One model, two service shapes: local and skill services share service items and orders, with differences confined to category attributes and fulfilment fields — no dual-model maintenance cost
- Role, not account: a provider is just a role on a user, so one person can be both customer and provider, and auth, addresses and files are reused rather than duplicated
- Monorepo with a single contract source: pnpm + Turborepo organise api / admin / web, while packages/shared collapses types and interface definitions so types run end to end
- Documents first: AGENTS.md requires design, API and schema documents before code, and an API list out of sync with Apifox counts as unfinished
- Explicit non-goals: payment splitting, mini programs, real-time IM and smart dispatch are each written down with a trigger condition, which keeps scope from creeping
Starting point: two service shapes, not two models
The platform carries both local services (cleaning, repairs, moving) and skill services (design, development, copywriting). Their fulfilment looks nothing alike: the first depends on address, service area and booking slots; the second on deadlines, deliverables, acceptance and revision counts.
The easy route is a table set per shape, paid for later: every new feature written twice, every requirement change reconciled in two places. So modelling came first — one service-item and order model, with the differences collected into category attributes and fulfilment fields, leaving a single main flow.
Role model: a provider is a role, not an account
PROVIDER is not a separate account system; it is a role on User.roles. That buys three things:
- One person can be both customer and provider without registering twice;
- Auth, addresses, files and reviews are reused, so there is never a second permission system to keep aligned;
- Operations keep one user view, and certification is just an approval state attached to a role.
Engineering shape: built for an AI to keep iterating
The repository was designed from the start for an AI coding agent to work in over the long term:
| Design | What it solves |
|---|---|
| pnpm + Turborepo monorepo | api / admin / web / shared in one repository; a contract change is visible to all three at once |
Single contract source (packages/shared) |
Interface types written once, flowing frontend to backend, so a renamed field cannot silently break a client |
| Prisma + migrations | The schema is the only source of truth; database structure and code move together |
| AGENTS.md as a hard rule | Design, API and schema documents precede code, and code changes write back to them |
| A written Non-Goals list | Payments, mini programs, IM and smart dispatch are explicitly out, each with a condition for revisiting |
The last row matters most: stating what you will not build prevents scope creep far better than a long to-do list.
Current state
Core modelling is done — users, providers, categories, service items, orders, order events, disputes, reviews and files — with the API and admin skeleton running. Payment splitting, the mini-program client and smart dispatch sit at P3 per the non-goals, to be decided once the core loop has data.