Astrocal
Guides

React SDK

First-class React integration with Provider, hooks, and an embeddable booking widget.

React SDK

@astrocal/react provides a typed API client, React context provider, hooks, and a booking widget component for React applications.

npm · GitHub

Installation

bash npm install @astrocal/react
bash pnpm add @astrocal/react
bash yarn add @astrocal/react

For the widget component, also install the optional peer dependency:

npm install @astrocal/widget

Provider Setup

Wrap your app with AstrocalProvider to make the API client available via hooks:

import { AstrocalProvider } from "@astrocal/react";

function App() {
  return (
    <AstrocalProvider apiKey="sk_live_...">
      <MySchedulingPage />
    </AstrocalProvider>
  );
}

Never expose secret API keys in client-side code. Use a publishable key or proxy requests through your backend.

Hooks

useAstrocal

Returns the typed API client from the nearest AstrocalProvider:

import { useAstrocal } from "@astrocal/react";

function EventTypesList() {
  const astrocal = useAstrocal();
  const [eventTypes, setEventTypes] = useState([]);

  useEffect(() => {
    astrocal.eventTypes.list().then(({ data }) => setEventTypes(data));
  }, [astrocal]);

  return (
    <ul>
      {eventTypes.map((et) => (
        <li key={et.id}>{et.title}</li>
      ))}
    </ul>
  );
}

Widget Component

The AstrocalWidget component wraps @astrocal/widget with proper React lifecycle management.

Inline Mode

Renders the booking calendar directly in your page:

import { AstrocalWidget } from "@astrocal/react";

<AstrocalWidget
  eventTypeId="evt_abc123"
  timezone="America/New_York"
  onBookingCreated={(booking) => console.log("Booked!", booking.id)}
/>;

Wraps a trigger element that opens the widget as a modal:

import { AstrocalWidget } from "@astrocal/react";

<AstrocalWidget eventTypeId="evt_abc123" mode="popup">
  <button>Book a Meeting</button>
</AstrocalWidget>;

Props

PropTypeDefaultDescription
eventTypeIdstringEvent type UUID (required)
mode"inline" | "popup""inline"Render mode
apiUrlstring"https://api.astrocal.dev"API base URL
timezonestringauto-detectIANA timezone
themeThemeConfigCSS custom property overrides
colorScheme"light" | "dark" | "auto""auto"Color scheme
demobooleanfalseDemo mode (mock data)
onBookingCreated(booking) => voidBooking success callback
onError(error) => voidError callback
onClose() => voidPopup close callback

Standalone Client

Use AstrocalApiClient without React context:

import { AstrocalApiClient } from "@astrocal/react";

const client = new AstrocalApiClient({ apiKey: "sk_live_..." });

const { data: eventTypes } = await client.eventTypes.list();
const { slots } = await client.availability.query({
  event_type_id: eventTypes[0].id,
  start: "2026-03-01",
  end: "2026-03-07",
  timezone: "America/New_York",
  duration: 60, // optional — for variable-duration event types
});

Error Handling

All API errors throw AstrocalError with typed properties:

import { AstrocalError } from "@astrocal/react";

try {
  await client.eventTypes.get("invalid_id");
} catch (err) {
  if (err instanceof AstrocalError) {
    console.log(err.status); // 404
    console.log(err.code); // "not_found"
    console.log(err.message); // "Event type not found"
  }
}
CodeStatusDescription
network_error0Network failure or timeout
invalid_responsevariesNon-JSON response
not_found404Resource not found
validation_error400Invalid request body

TypeScript

All types are exported:

import type {
  EventType,
  Booking,
  AvailabilitySlot,
  PaginatedResponse,
  AstrocalClient,
  ThemeConfig,
} from "@astrocal/react";

Next.js

Works with both App Router and Pages Router. The provider and widget include "use client" directives automatically.

// app/layout.tsx
import { AstrocalProvider } from "@astrocal/react";

export default function RootLayout({ children }) {
  return (
    <AstrocalProvider apiKey={process.env.NEXT_PUBLIC_ASTROCAL_KEY!}>{children}</AstrocalProvider>
  );
}
// app/book/page.tsx
import { AstrocalWidget } from "@astrocal/react";

export default function BookPage() {
  return <AstrocalWidget eventTypeId="evt_abc123" />;
}

Next Steps

On this page