2025 · Co-founder & Full-stack Developer

Vain

  • NestJS
  • Next.js
  • PostgreSQL
  • Prisma
  • Redis
  • BullMQ
  • Stripe
  • TailwindCSS
  • Sanity

Vain

Independent service providers — barbers, hairdressers, estheticians — manage their schedules through WhatsApp, physical notebooks, or spreadsheets. This leads to confusion, no-shows without consequences, and time wasted on manual confirmations. Vain was built to solve exactly that: a platform where providers configure their services and availability once, and clients book on their own online — no back-and-forth needed.

What it does

Every provider gets a public booking page with their own URL. The client visits, picks a service, selects an available time slot, and confirms — all in under two minutes.

Behind the scenes, the provider has a full management portal:

  • Visual calendar with all appointments
  • Working hours, breaks, and closed periods configuration
  • Services with pricing, duration, and optional booking fees
  • Custom forms clients fill out when booking
  • Client management with history, notes, and a blocklist
  • Payments via Stripe Connect — cancellation fees or deposits go directly to the provider's account
  • Google Calendar sync
  • Automated reminders via email and WhatsApp

Technical decisions

Why NestJS on the backend? Scheduling has complex rules: minimum notice periods, slot optimization to avoid gaps, auto-cancellation of expired bookings, automatic charges. NestJS's modular architecture and native queue support (BullMQ) kept this domain organized. Each feature lives in an isolated module — changes to payments don't touch the calendar logic.

Stripe Connect as the central trade-off We could have held the money and transferred it later — simpler technically. We chose Stripe Connect so each provider has their own account and gets paid directly. This increased onboarding complexity, but eliminated the regulatory risk of "holding third-party funds" and built significantly more trust with providers.

Availability calculated in real time The biggest technical challenge: computing available slots considering working hours, breaks, closed periods, existing appointments, extra buffer time per service, and schedule optimization (avoiding unproductive gaps). I ended up writing a custom algorithm that runs on the backend on every availability request — straightforward to test and easy to adjust as new edge cases appear.

What I learned: Scheduling seems simple until you start dealing with timezones, concurrency conflicts, and cancellation edge cases. Modeling the domain properly before writing code would have saved weeks.

Another key lesson was that providers had needs we never anticipated. What we planned as the next step was repeatedly pushed back, because more urgent demands kept surfacing from actual users — things that weren't on the roadmap but were blocking them in their day-to-day. We learned early that our perception of what was important rarely matched the reality of the people using the product.

Results

The project is still in its early stage — early traction, not yet profitable:

  • 3 providers actively using the platform
  • 5,000+ appointments processed
  • ~$35/month in recurring revenue (MRR)
  • ~$70/month in infrastructure costs — still operating at a loss while validating the product

The most valuable lesson was realizing that the provider onboarding problem (configuring services, hours, connecting Stripe) was harder than the booking flow itself. The next phase is simplifying that process to reduce time-to-activation.