Benito Pedro Xavier

Full stack, concept to cloud

Interfaces, APIs, and the infrastructure underneath them.

Loading experience000
All case studies
Case studyProduct2025

Markado

Service scheduling platform with real calendar and payments

In plain English

A booking website where a professional shares one link, clients pick a free time slot, and the meeting plus the payment are handled automatically.

My role

Solo full stack developer

Timeline

Ongoing

Team

Solo

Status

Case study

Next.jsTypeScripttRPCPrismaPostgreSQLStripeDockerGitHub Actions

Design

Product tour

Markado appointments dashboard
Markado weekly availability editor
Markado public booking page as seen by a client
Markado booking form question editor

Section 01

The problem

Booking a service still runs on message threads. Someone asks for a time, the provider checks their calendar, they go back and forth, and then payment happens somewhere else entirely. Every step is manual and every step can fail: double bookings, forgotten meetings, unpaid sessions.

Section 02

How I approached it

I built a single scheduling surface that owns availability, the calendar event, and the money. The provider defines their working rules once. Everything downstream — the free slots a client sees, the Google Calendar entry, the Meet link, the Stripe charge — derives from that one source of truth.

Outcome

A booking link that turns a conversation into a confirmed, paid, calendar-synced appointment in about thirty seconds, with no manual step for the provider.

Section 03

Going deeper

What it actually does

A provider signs up, connects their Google account, and describes when they work: days, hours, buffer between sessions, how far in advance people can book. Markado turns those rules into a public page. A client opens it, sees only genuinely free time, picks a slot, pays, and receives a calendar invite with a video link. The provider never touches anything.

Why availability is the hard part

Showing free time sounds trivial until you account for timezones, existing events in an external calendar, buffers, minimum notice, and two people trying to book the same slot in the same second. Availability is computed on the server from working rules plus live Google Calendar data, and the final write is guarded so the second person to click gets a clear 'just taken' message instead of a silent double booking.

Type safety end to end

The whole app speaks one type system. tRPC means the frontend calls backend procedures as if they were local functions, with argument and return types checked at compile time. Prisma generates the database types. If I rename a column, the build fails in the UI file that used it. That eliminates an entire category of bugs that normally reach production.

Section 04

The build process

1

Map the booking journey

I wrote out every state a booking can be in — requested, confirmed, paid, rescheduled, cancelled, no-show — before writing code. That state list became the database schema.

2

Model availability first

Availability was built and tested as a pure function: given rules, existing events, and a timezone, return open slots. Isolating it meant I could test edge cases like DST transitions without spinning up a UI.

3

Layer the integrations

Google OAuth, then Calendar read, then Calendar write with Meet conferencing, then Stripe. Each integration shipped behind its own boundary so a failure in one doesn't take down the booking flow.

4

Automate the pipeline

GitHub Actions runs typecheck, lint, and tests on every push, then builds the Docker image. Deploys are a merge, not a ritual.

Section 05

How the pieces fit together

Each layer has one job. Read it top to bottom — that's roughly the path a request takes through the system.

Client

Next.js App Router

Server components for the public booking page, client components for the interactive slot picker.

API

tRPC procedures

End-to-end typed RPC layer — no hand-written fetch clients, no drifting API contracts.

Data

PostgreSQL + Prisma

Relational schema for users, event types, availability rules, and bookings with migrations in version control.

Integrations

Google Calendar / Meet · Stripe

OAuth 2.0 for calendar access, conferencing auto-created per booking, Stripe for checkout and webhooks.

Infra

Docker + GitHub Actions

Reproducible container builds, automated checks, and continuous deployment.

Section 06

What it does

Multi-step authentication

Signup is split into deliberate stages so the account, the calendar connection, and the payment setup each get a clear, recoverable step.

Live availability engine

Slots are computed against real calendar data, timezones, and buffer rules — never a static list.

Automatic video meetings

Every confirmed booking creates a Google Calendar event with a Meet link attached for both parties.

Payments at booking time

Stripe checkout runs inside the booking flow, so a confirmed slot is a paid slot.

Section 07

The hard parts

Timezones

A provider in Rio and a client in Lisbon must see the same moment in their own local time. Everything is stored in UTC and converted only at the display edge, with the timezone captured explicitly at booking.

Race conditions

Two clients can request the same slot simultaneously. The booking write revalidates availability inside the transaction, so the loser gets a clean error rather than a corrupted calendar.

External API failure

Google and Stripe both go down occasionally. Failures are isolated per integration and surfaced honestly instead of leaving a booking in an unknown state.

Section 08

What I took away

  • Modelling the state machine before the schema saved weeks of migration churn.
  • Pure functions for business rules are worth the extra indirection — they are the only parts you can test cheaply.
  • End-to-end type safety pays for itself the first time you rename something.

Type

SaaS product

Integrations

Google Calendar, Meet, Stripe

Auth

Multi-step

Deploys

CI/CD via GitHub Actions

Contact

Let's build something worth shipping

Available for freelance projects, full-time roles, and technical consulting. Tell me what you're building and I'll tell you honestly whether I'm the right person for it.

Based in Rio de Janeiro, Brazil · Working with teams in any timezone · Fluent in English and Portuguese