Selected Work
2025 · Frontend

Chime: Booking Widget

A configurable, drop in scheduling widget that lets any service business take appointment bookings from a single embeddable React component.

ReactTypeScriptViteFramer MotionStripeExpressPostgreSQL
Chime: Booking Widget

Overview

Chime is a configurable, drop in scheduling widget that lets any service business take appointment bookings, service selection, live availability, terms acceptance, customer details, and a refundable card deposit, from a single embeddable React component. It is designed to be embedded on a business's own site and pointed at live scheduling data, with a fully working demo mode out of the box.

A reference Express and PostgreSQL backend, including schema, seed data, and endpoints, is included to demonstrate the full path from availability to confirmed booking.

Highlights

  • Guided booking flow: service, date and time, terms, details, deposit, and confirmation, with animated step transitions and a progress stepper that adapts to whether a deposit step is required.
  • Config driven embedding: branding, services, availability, terms, customer fields, currency, and API endpoints are all supplied through a single injected config object or environment variables, so deploying for a new business requires no code changes.
  • Graceful payment degradation: with Stripe keys configured, the flow collects a refundable deposit through Stripe Elements; without them, it detects the gap and submits the booking without an online deposit instead of dead ending on a broken payment form.
  • Live and demo data modes: the same UI runs against real services, availability, and booking endpoints, or against built in sample data, selected automatically by environment.
  • Scroll gated terms acceptance: the accept control unlocks only after the full terms document is scrolled, capturing an explicit termsAcceptedAt timestamp with each booking.

Architecture and engineering

  • Typed domain with a normalization layer: inbound service and availability data, from config or API, is normalized into strict TypeScript domain types, so the UI always renders from one consistent shape regardless of source.
  • Separation of concerns: presentational step components are decoupled from orchestration, and a single flow controller owns step state, deposit logic, and submission, keeping each screen simple and independently testable.
  • Time aware availability: slot generation and calendar navigation account for the current time, so slots that have already passed on the current day are never offered.
  • Custom design system: a hand built glassmorphism UI with responsive layouts, keyboard focus states, and support for prefers-reduced-motion and prefers-reduced-transparency.