GoBrand Calendar

Your first calendar

Build a navigable month with one hook.

Enable a view with true, pass your events, and tell the calendar where each event belongs.

import type { Temporal } from '@js-temporal/polyfill'
import { useCreateCalendar } from '@gobrand/react-calendar'

type Event = {
  id: string
  title: string
  date: Temporal.PlainDate
}

function Calendar({ events }: { events: Event[] }) {
  const calendar = useCreateCalendar({
    views: { month: true },
    items: events,
    getDate: event => event.date,
  })

  return (
    <section>
      <h2>{calendar.title()}</h2>
      {calendar.activeView.weeks.flat().map(day => (
        <div key={day.id}>
          {day.date.toString()}: {day.items.map(event => event.title).join(', ')}
        </div>
      ))}
    </section>
  )
}

That is the whole setup. TypeScript infers the event type, and calendar.activeView is a MonthView because month is the only enabled view.

Basic monthA navigable month whose event type is inferred from values.

September 2026

Sun
Mon
Tue
Wed
Thu
Fri
Sat
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3

The preview is live. Its source uses small website-only components for markup and styles; its calendar state and month data come directly from useCreateCalendar.

What the library does

  • Keeps the current date and active view.
  • Moves with previous(), next(), and today().
  • Gives you a localized title() and timezone-aware visibleRange.
  • Builds the month, week, or day data you render.

Your app owns the markup, styles, data fetching, and caching.

Add week and day views

const calendar = useCreateCalendar({
  views: {
    month: true,
    week: true,
    day: true,
  },
  items: events,
  getDate: event => event.date,
})

An omitted view is unavailable. Use an options object instead of true when a timed week or day needs custom hours or slot length.

See the complete month/week/day example.

On this page