Case study
Operations for a hand-built offer model
MVP, deployed to production. Stack: Next.js, TypeScript, Tailwind CSS, Convex, Vercel.
Business context
The agency does not sell fixed packages. Customers describe a trip; the team assembles flights, hotels, transfers, and insurance into a single offer. That personalization is the product — and the operational bottleneck.
What failed in email
- Trip requests arrived as free-form emails, often missing fields needed to quote.
- Offers lived in threads — no reliable answer to where a request stood.
- Customer history was scattered; repeat clients restarted from zero.
- Volume increased dropped balls rather than throughput.
What shipped
Customer: Six-step request wizard with saved progress and required fields.
Operations: Queue, assignment, New → In Review → Offer Sent → Accepted → Closed pipeline, messaging, documents.
Data model: Offers as first-class objects with lifecycle — intended extension point for Stripe and booking APIs.
Changes at launch
- Every submission uses a structured wizard with enforced fields.
- Each request has an assignable owner and explicit status.
- Messages and documents attach to the request, not an inbox.
- Customer profiles retain past requests for returning travelers.
- Offers are modeled as objects with a lifecycle — the seam for payments and booking APIs.
Leverage came from modeling the workflow correctly, then building the interface around it.