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.

July 2026

Sun
Mon
Tue
Wed
Thu
Fri
Sat
28
29
30
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
31
1

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