---
title: Next.js
description: Use FullCalendar WebMCP with Next.js App Router client components, server actions, and SSR-safe registration of calendar tools.
---

Use the hook in a Client Component. The package entry includes `'use client'`. Module load does not touch `window` or `document`, so SSR stays safe. Your repository can call Server Actions or Route Handlers.

This guide uses FullCalendar React **v6** import paths (`@fullcalendar/daygrid`). For v7, import plugins from `@fullcalendar/react/daygrid` and type the ref as `CalendarRef`.

## App Router

```tsx
"use client";

import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import { useCallback, useRef, useState } from "react";
import {
  useFullCalendarWebMCP,
  type CalendarEvent,
  type CalendarEventRepository,
} from "@protocoltooling/fullcalendar";
import {
  fetchEventsAction,
  createEventAction,
  updateEventAction,
  deleteEventAction,
} from "./actions";

export function CalendarClient({
  initialEvents,
}: {
  initialEvents: CalendarEvent[];
}) {
  const calendarRef = useRef<FullCalendar>(null);
  const [events, setEvents] = useState<CalendarEvent[]>(initialEvents);

  const repository: CalendarEventRepository = {
    list: (query) => fetchEventsAction(query),
    get: async (id) => {
      const all = await fetchEventsAction();
      return all.find((event) => event.id === id) ?? null;
    },
    create: (input) => createEventAction(input),
    update: (id, input) => updateEventAction(id, input),
    delete: (id) => deleteEventAction(id),
  };

  const refreshEvents = useCallback(async () => {
    setEvents(await fetchEventsAction());
  }, []);

  useFullCalendarWebMCP({
    calendarRef,
    events: repository,
    onEventsChanged: refreshEvents,
  });

  return (
    <FullCalendar
      ref={calendarRef}
      plugins={[dayGridPlugin]}
      initialView="dayGridMonth"
      events={events.map((event) => ({
        ...event,
        end: event.end ?? undefined,
      }))}
    />
  );
}
```

Server page:

```tsx
import { CalendarClient } from "./calendar-client";
import { fetchEventsAction } from "./actions";

export default async function CalendarPage() {
  const events = await fetchEventsAction();
  return <CalendarClient initialEvents={events} />;
}
```

For the shared golden path, see [Quickstart](/integrations/fullcalendar/quickstart).
