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.
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/widgetProvider 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)}
/>;Popup Mode
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
| Prop | Type | Default | Description |
|---|---|---|---|
eventTypeId | string | — | Event type UUID (required) |
mode | "inline" | "popup" | "inline" | Render mode |
apiUrl | string | "https://api.astrocal.dev" | API base URL |
timezone | string | auto-detect | IANA timezone |
theme | ThemeConfig | — | CSS custom property overrides |
colorScheme | "light" | "dark" | "auto" | "auto" | Color scheme |
demo | boolean | false | Demo mode (mock data) |
onBookingCreated | (booking) => void | — | Booking success callback |
onError | (error) => void | — | Error callback |
onClose | () => void | — | Popup 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"
}
}| Code | Status | Description |
|---|---|---|
network_error | 0 | Network failure or timeout |
invalid_response | varies | Non-JSON response |
not_found | 404 | Resource not found |
validation_error | 400 | Invalid 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
- Embeddable Widget — Using the widget without React
- Quickstart — REST API basics
- API Reference — Full endpoint documentation