Quick Start

This Next.js example adds an anonymous booking page to an existing Convex + React app with Tailwind 4. For a complete app you can run immediately, use the demo setup.

1. Install

bash
npm install @mrfinch/booking convex@^1.46.0

For the React Booker, also install its UI dependencies:

bash
npm install convex-helpers@^0.1.124 react-hook-form@^7.88.0 @hookform/resolvers@^5.9.1 lucide-react@^1.47.0

React 18 and 19 are supported; keep React DOM on the same version as React. Zod is installed by the component. For a backend-only integration, skip the UI dependencies and use the backend API.

2. Register the component

Add booking to your existing Convex configuration:

typescriptconvex/convex.config.ts
import { defineApp } from "convex/server";
import booking from "@mrfinch/booking/convex.config";
 
const app = defineApp();
app.use(booking);
export default app;

3. Add the booking gateway

A gateway is a file of host functions that your browser calls. It checks booking policy before calling the component. Use the complete reference implementation:

  1. Copy convex/public.ts into your app, including all helpers and exports.
  2. Add these public function builders:
typescriptconvex/functions.ts
export { query as publicQuery, mutation as publicMutation } from "./_generated/server";
  1. Merge the gateway's rate-limit table into your host schema:
typescriptconvex/schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
 
export default defineSchema({
  bookingRateLimits: defineTable({
    key: v.string(),
    windowStart: v.number(),
    count: v.number(),
  }).index("by_key", ["key"]),
});

The reference gateway includes the full API expected by the Booker: availability, setup lookups, booking creation, presence and token-protected management. It checks schedules, notice periods and booking horizons. Before using it for your own service, adapt its rate limits and resource visibility to your product; see host policies.

Run npx convex dev to generate your API and keep it running during development.

4. Create something bookable

Copy and run the setup seed. It creates:

  • meeting-room, the resource;
  • business-hours, its schedule;
  • quick-meeting, the event type, linked to the resource.

Creating a resource and event type alone does not link them.

5. Render the Booker

Under your existing Convex provider, add ConvexQueryCacheProvider. If your app has no provider yet, use this one and wrap your root layout's children with it:

tsxcomponents/ConvexClientProvider.tsx
"use client";
import { useState, type ReactNode } from "react";
import { ConvexProvider, ConvexReactClient } from "convex/react";
import { ConvexQueryCacheProvider } from "convex-helpers/react/cache/provider";
 
export default function ConvexClientProvider({ children }: { children: ReactNode }) {
  const [client] = useState(
    () => new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!)
  );
  return (
    <ConvexProvider client={client}>
      <ConvexQueryCacheProvider>{children}</ConvexQueryCacheProvider>
    </ConvexProvider>
  );
}

npx convex dev supplies NEXT_PUBLIC_CONVEX_URL in your app's .env.local. Keep your existing authenticated Convex provider if you already have one.

tsxapp/book/page.tsx
"use client";
import { Booker, BookingProvider } from "@mrfinch/booking/react";
import { api } from "@/convex/_generated/api";
 
export default function BookingPage() {
  return (
    <BookingProvider publicApi={api.public}>
      <Booker eventTypeId="quick-meeting" resourceId="meeting-room" title="Book a Meeting" />
    </BookingProvider>
  );
}

The UI uses Tailwind and your theme's color tokens. With Tailwind 4, include the package in app/globals.css:

css
@import "tailwindcss";
@source "../node_modules/@mrfinch/booking";

Use the demo stylesheet for the required color tokens if your app does not already define them. Open /book, select a date and time, and submit a booking to see its confirmation.

For cancellation and rescheduling screens, use the Booker onBookingComplete(booking) callback to access the returned uid and managementToken. Add token-based management routes using the management-page examples, then link to them from your confirmation screen or emails.

Next steps