Your first calendar.
Your own stack.
Use the JavaScript core directly or choose a framework wrapper. Add the optional PHP or ASP.NET Core server package when your application needs authenticated, durable event APIs.
The generated API reference covers every client option and public calendar API, plus the complete PHP and ASP.NET Core route-level contracts.
Search the complete API reference →1. Choose your frontend integration
npm install @wts-calendar/coreMount the core into a browser element, then call destroy() when removing it.
Read JavaScript setup guide ↗2. Add a backend when your application needs one
Frontend wrappers render the calendar. The PHP and ASP.NET Core packages implement the same server-side event REST contract while your application keeps control of authentication, authorization, and durable storage.
composer require wts-calendar/server-php:^1.0 nyholm/psr7<?php
use Nyholm\Psr7\Factory\Psr17Factory;
use WtsCalendar\Server\CalendarApiHandler;
use WtsCalendar\Server\CalendarApiOptions;
use WtsCalendar\Server\CalendarEventStoreInterface;
$psr17 = new Psr17Factory();
$handler = new CalendarApiHandler(
$container->get(CalendarEventStoreInterface::class),
$psr17,
$psr17,
new CalendarApiOptions(
requireIfMatchForUpdate: true,
requireIfMatchForDelete: true,
),
);
// $request is the host application's PSR-7 ServerRequestInterface.
$response = $handler->handle($request);Use any PSR-7 request, PSR-17 factories, and a durable CalendarEventStoreInterface implementation owned by your application.
Shared HTTP contract
| Method | Route | Purpose |
|---|---|---|
GET | /api/calendar/events?start=...&end=... | Load a bounded visible range |
GET | /api/calendar/events/{id} | Load one event and its ETag |
POST | /api/calendar/events | Create an event |
PATCH / PUT | /api/calendar/events/{id} | Update with If-Match conflict protection |
DELETE | /api/calendar/events/{id} | Delete with an optional version precondition |
The server package handles
- Typed calendar event requests and responses
- Range validation, CRUD routes, and RFC 7807 errors
ETagandIf-Matchoptimistic concurrency- A replaceable storage interface
Your application still handles
- Authentication and event-level authorization
- Database schema, migrations, and tenant isolation
- CORS origins, rate limits, secrets, and monitoring
- Production storage; in-memory stores are demo-only
3. Connect every frontend to the same endpoint
Angular, React, and Vue use the core REST adapter. It carries mutation versions through ETag and If-Match so the server can reject stale edits. React Native calls the same authenticated JSON endpoint and passes the resulting events to its native component.
import {
CalendarDataClient,
createRestCalendarDataAdapter,
} from '@wts-calendar/core/data-adapter-sdk';
const endpoint = 'https://api.example.com/api/calendar/events';
export const calendarEvents = new CalendarDataClient(
createRestCalendarDataAdapter({
url: endpoint,
mutationUrl: ({ type, id }) =>
type === 'create'
? endpoint
: `${endpoint}/${encodeURIComponent(id ?? '')}`,
headers: async () => ({
authorization: `Bearer ${await accessToken()}`,
}),
}),
);import { useEffect, useState } from 'react';
import { WtsCalendarNative } from '@wts-calendar/react-native';
import type { NativeCalendarEventInput } from '@wts-calendar/react-native';
const endpoint = 'https://api.example.com/api/calendar/events';
export function Schedule({ accessToken }: { accessToken: string }) {
const [events, setEvents] = useState<readonly NativeCalendarEventInput[]>([]);
useEffect(() => {
const query = new URLSearchParams({
start: '2026-09-01T00:00:00Z',
end: '2026-10-01T00:00:00Z',
timeZone: 'UTC',
});
fetch(`${endpoint}?${query}`, {
headers: { authorization: `Bearer ${accessToken}` },
})
.then((response) => {
if (!response.ok) throw new Error('Calendar request failed');
return response.json();
})
.then((page) => setEvents(page.records));
}, [accessToken]);
return <WtsCalendarNative events={events} />;
}4. Start with the core
This minimal JavaScript example uses only Standard features. Framework components manage mounting and teardown for you.
import { WtsCalendar } from '@wts-calendar/core';
import '@wts-calendar/core/styles/calendar.css';
const calendar = new WtsCalendar({
container: document.querySelector('#calendar'),
view: 'month',
viewDate: '2026-09-07',
events: [{ id: 'hello', title: 'Hello, calendar', start: '2026-09-07' }],
});
// On unmount:
// calendar.destroy();5. Explore one feature at a time
The examples directory shows the feature options and runtime behavior together. Optional modules are loaded only for the relevant examples.
Open examples →Sample events are stored in memory and reset when you reload or switch examples. This demo does not ask for provider credentials, store customer events, or run premium integrations.