Skip to content

feat(events): migrate events from Notion to ICS calendar feed, redesign category UI#515

Open
mohanadft wants to merge 8 commits into
mainfrom
feat/events-ics-migration
Open

feat(events): migrate events from Notion to ICS calendar feed, redesign category UI#515
mohanadft wants to merge 8 commits into
mainfrom
feat/events-ics-migration

Conversation

@mohanadft

Copy link
Copy Markdown
Collaborator

Summary

  • Replaces the Notion-backed events pipeline (fetchNotionEvents) with a public ICS calendar feed from the Mattermost Events Calendar plugin, fetched and parsed server-side (src/store/eventsClient.ts) — no external ICS library, hand-rolled line unfolding/property parsing/unescaping.
  • Rebuilds both /events (MUI) and /events-new (new design system) around category-grouped sections — In-Person Events, Occupied Tech Podcast, Community Calls, Roundtable, Book Club, and an "Others" catch-all — instead of a flat list. Each page keeps its own distinct visual language.
  • Both pages: collapsible sections (default expanded), always feature the 2 most-recent events per category (upcoming first, falling back to latest past) with the rest in a capped "Past events" list ("Show N more"), a detail popup with a sticky CTA footer (Register/Watch/Add to calendar), and a feed-wide "Subscribe to this calendar" link.
  • Popup descriptions render through a small Markdown-lite parser (src/utils/eventDescription.tsx) — headings, bold, rules, lists, auto-linked URLs — as real React nodes (no dangerouslySetInnerHTML), since the text is externally sourced.
  • Cleans up known data-quality issues from the source calendar: dedupes recurring master/override duplicates and same-day "community call" duplicates, strips internal organizer usernames and redundant inline "Register here: <url>" lines from descriptions (while preserving the link in the exported Google Calendar event's details).
  • Removes dead code: event-details.astro/EventDetails.tsx (already broken — fetched a non-existent /api/event-by-id route) with a 301 redirect to /events, and fetchNotionEvents/fetchNotionEventById from notionClient.ts (other Notion-backed features — FAQ, ideas, agenda, signatories, community calls — are untouched).
  • Docs updated: EVENTS.md, NOTION.md, API.md, ENVIRONMENT.md, DEPLOYMENT.md, CLAUDE.md; EVENTS_ICS_URL added to .env.example.

Test plan

  • Set EVENTS_ICS_URL in .dev.vars, run pnpm dev, and check /events and /events-new
  • Confirm category sections group events correctly and collapse/expand
  • Confirm "Past events" caps at 5 with "Show more"
  • Confirm in-person events show a location (not a register button pointed at a map link); online events show Register/Watch online correctly
  • Confirm the detail popup opens, scroll works inside it (not the page behind it), and the CTA footer stays visible while scrolling
  • Confirm "Add to calendar" produces a correct Google Calendar link, including the registration URL in its details
  • Confirm /event-details 301-redirects to /events
  • pnpm check and pnpm build pass

…gn category UI

Replaces the Notion-backed events pipeline with a public ICS calendar feed
(Mattermost Events Calendar plugin), and rebuilds both /events (MUI) and
/events-new (new design system) around category-grouped sections instead
of a flat list — each page keeps its own visual language.

- src/store/eventsClient.ts: hand-rolled ICS parser (line unfolding,
  property parsing, text unescaping), dedupes recurring master/override
  duplicates and same-day "community call" duplicates from the source
  calendar, classifies links into register/location/watch buckets
- src/utils/eventSections.ts: groups events into named categories
  (In-Person, Occupied Tech Podcast, Community Calls, Roundtable, Book
  Club, Others) with a title-keyword fallback for untagged events
- src/utils/icalDate.ts: shared TZID->UTC resolver, extracted from
  notionClient.ts's existing implementation (now reused by community calls)
- src/utils/eventDescription.tsx: lightweight Markdown-lite renderer
  (headings, bold, rules, lists, auto-linked URLs) for the popup — renders
  real React nodes rather than dangerouslySetInnerHTML, since descriptions
  are externally-sourced text
- src/utils/googleCalendarLink.ts / webcal.ts: per-event "Add to calendar"
  links and a feed-wide "Subscribe to this calendar" link
- Both pages: collapsible category sections (default expanded), always
  feature the 2 most-recent events per category (upcoming or past) with
  the rest in a capped "Past events" list, a detail popup with a sticky
  CTA footer instead of inline register/recording links
- Removes dead code: event-details.astro/EventDetails.tsx (already
  broken, fetched a non-existent API route), fetchNotionEvents/
  fetchNotionEventById from notionClient.ts
- Updates docs (EVENTS.md, NOTION.md, API.md, ENVIRONMENT.md,
  DEPLOYMENT.md, CLAUDE.md) and adds EVENTS_ICS_URL to .env.example
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 18, 2026

Copy link
Copy Markdown

Deploying website with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0990c1c
Status: ✅  Deploy successful!
Preview URL: https://be2953e1.website-aun.pages.dev
Branch Preview URL: https://feat-events-ics-migration.website-aun.pages.dev

View logs

Events whose tags/title don't match a named category are now skipped
entirely instead of falling into a generic "Others" section.
Featured cards get a badge overlay on the image; the compact past-list
rows get a small inline badge for the rare case a category has more
upcoming events than fit in the featured slots.
The card itself now carries a colored border + subtle tint for upcoming
events, instead of relying solely on a small corner badge. Adds a
dedicated "positive" design token (muted sage, derived from the
existing warm palette) rather than a generic bright green, used
consistently on both /events and /events-new.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant