← Prompts

Calendar

Read the current prompt
# Task: Build a Calendar & Event Planner

Build a calendar and event planner (vanilla JS, no external assets, no CDN, no libraries). The top priority is **correct date math** — month lengths, week alignment, leap years, and recurrence rules are where calendar implementations silently go wrong.

## Core Specification

**Views & Navigation**
- **Month view:** classic 6-row grid, Monday or Sunday start (settings toggle), correct leading/trailing days from adjacent months (shown dimmed), today highlighted, "Today" button, prev/next month and year jump
- **Week view:** 7 columns × hourly rows (e.g. 6:00–22:00), events rendered as positioned blocks with correct proportional height/offset; all-day events in a top strip
- **Agenda view:** chronological list of upcoming events grouped by day
- Smooth animated transitions between months/views; current time indicator line in week view when viewing the current week

**Date Engine (write it yourself — no Date-library shortcuts, native `Date` only)**
- Correct month/day grid computation for any year (including leap years, February, century rules)
- Week start configurable (Monday/Sunday) with correct week numbering either way
- All date arithmetic done on year/month/day components — never "add 86400000 ms per day" hacks that break across DST transitions

**Events**
- Full CRUD via a clean modal editor: title, date, start/end time (or all-day), color (from a fixed palette), optional notes
- Validation: end time must be after start time (or all-day); clear inline errors, never silent failure
- Click a day cell to create an event on that date; click an event to view/edit; delete with confirm or undo toast
- Drag-to-reschedule in month view (drag an event chip onto another day — updates its date) and in week view (drag vertically to change time in 15-minute snaps)

**Recurring Events**
- Recurrence rules: daily, weekly (choose weekdays), monthly (same day-of-month; `monthly on the 31st` must skip months without a 31st), yearly
- Editing a recurring event asks: this event only / this and following / entire series — each behaving correctly (exception instance, split series, edit master)
- Deleting one occurrence of a series must not delete the rest

**Persistence**
- Events (including recurrence rules and per-occurrence exceptions), settings, and current view serialize to `localStorage` and restore exactly on reload

## Visual Style
- Polished Google-Calendar-adjacent aesthetic: clean typography, soft event chips with color-coded left border or fill, subtle gridlines, today pill accent
- Month cells show up to ~3 event chips plus a "+2 more" overflow that opens a day popover
- Responsive: usable at laptop width and down to ~tablet width without breaking the grid

## Technical Requirements
- Vanilla JS; all code organized with clear section comments
- Clean separation: a date-util module (pure functions: daysInMonth, addDays, addMonths, weekStart, recurrence expansion) fully decoupled from rendering
- Recurrence expansion computed for visible date ranges only — never materialize infinite series
- Tunable constants block at the top (colors, hour range, snap interval, week start default)

## Quality Bar (must hit all)
- February renders correctly in 2024 (29 days), 2025 (28), and 2100 (28 — century rule); month grids align weekdays correctly for any year you navigate to
- A monthly event on Jan 31 appears Feb… nowhere, and reappears Mar 31
- Navigating 24 months forward then back lands on exactly the original month
- Drag-rescheduling an event across a month boundary keeps the correct date
- Editing "this event only" of a weekly series changes one occurrence and leaves all others untouched

## Self-Check Before Finishing
Verify with the browser tools (probe the date-util functions and the rendered grid directly):
- Assert day-of-week alignment for several known dates (e.g. 2026-01-01 is a Thursday — it must land in the Thursday column for both week-start settings)
- Create a weekly recurring event, edit one occurrence ("this event only"), reload, and assert exactly one changed instance plus the intact series
- Drag an event from Jan 30 to Feb 2 (crossing the month boundary) and assert its stored date is correct
- Navigate forward/back repeatedly and assert the grid, header, and today highlight stay consistent