calendar-tsx

Server rendering

Render on the server, hydrate, and use the parts from Server Components.

The parts render with renderToString and stream like any other component.

Hydration

Today's highlight and the now indicator depend on the current time. If the server and the client use different times, for example across midnight, the markup doesn't match. Give both sides the same instant:

  1. Pick an instant once per request, on the server.
  2. Send it to the client as a string, with the page's data.
  3. Pass it as initialNow on both sides.

initialNow is read once, when the calendar is created. After mounting, the client reads its clock and catches up to the real time. On the server the clock never starts.

React Server Components

The package entry is marked 'use client', so Server Components can import and render the parts. The options cannot cross that boundary as props: Temporal values, views and onNavigate are not serializable. Create the calendar in a client component, and pass it only strings to parse:

schedule.tsx
// the server picks `now` once per request and passes it, with `date`, as strings
export const Schedule = ({ now, date, children }: { now: string; date: string; children: ReactNode }) => {
  const calendar = useCalendar({
    timeZone,
    views,
    features,
    view: 'week',
    date: Temporal.PlainDate.from(date),
    events: bookings,
    onNavigate: () => {},
    initialNow: Temporal.Instant.from(now),
  });

  return <CalendarProvider value={calendar}>{children}</CalendarProvider>;
};