Lesson 1: Introduction
Why we built our own calendar engine and what problems it solves.
Lesson 1 of 8: why another calendar library exists, and what you'll build by the end of this course.
Why build a calendar engine?
Every React calendar library we evaluated hit at least one of these problems:
- Too large —
react-datepickerships 32 KB gzipped with 3 runtime dependencies. - Coupled to a date library —
react-day-pickerrequiresdate-fns(~15 KB). - Not tree-shakeable — monolithic components bundle everything even if you only need a date picker.
- Ships CSS — forces you to import and override stylesheets.
We wanted:
- Under 10 KB gzipped, zero dependencies.
- Any date library through an adapter.
- Headless — no opinions on rendering.
- WAI-ARIA grid pattern built in.
The architecture
@gentleduck/calendar is built in four layers:
| Layer | What it does | React required? |
|---|---|---|
| Core | Pure functions: grid building, selection, navigation | No |
| Adapter | Abstracts date operations via Adapter.IDateAdapter<TDate> | No |
| React hooks | State management + prop getters | Yes |
| Compound components | Declarative API via @gentleduck/primitives | Yes |
Each layer imports only from the layer below. Use the core functions without React, the hooks without compound components, or the whole stack.
What you will build
By the end of this course, you'll have:
- A calendar with single, range, and multi-select.
- A 12/24 hour time picker.
- Full keyboard navigation and screen reader announcements.
- Custom styling via data attributes and Tailwind.
- A custom date adapter (dayjs example).