Webinars Collection — Calendar-Style Cards, Index Page, and Detail Pages
Built the Agentic VC Dojo schedule end-to-end: webinars content collection with date_scheduled / date_posted frontmatter, status (Upcoming / Live / Recorded) inferred at render time from the scheduled date, calendar-style WebinarCard component with a date tear-off, /webinars index page grouped by status, and /webinars/[id] detail pages that render the markdown body. Authoring a new session is now one .md file.
Changelog - 2025-04-25 (02)
Webinars Collection — Calendar-Style Cards, Index, and Detail Pages
Why Care?
For the firm (Mike): Adding a new monthly Dojo session is now a single-file operation. Drop a .md file into src/content/webinars/, fill the frontmatter (title, lede, date_scheduled, durationMinutes, presenters, rsvpUrl), commit, push. The site does the rest:
- Status (Upcoming / Live / Recorded) is inferred at render time from
date_scheduled+durationMinutes. No author ever setsstatusmanually — it can never go stale. - The card’s CTA flips from “RSVP” to “Watch recording” automatically when you add a
recordingUrlto the frontmatter after the session ends. - Sorting (Live first, then nearest Upcoming, then most-recent Recorded) is handled by the index page.
That means zero ongoing site maintenance overhead per session — exactly the right amount of work for someone running a community in the margins of investing.
For our end users (VCs looking to participate): The /webinars page is the dojo’s calendar. At a glance:
- Date tear-off on the left of every card (MAY · 15 · FRI) — the visual element a busy VC actually scans for.
- Status badge — clear “Upcoming” / “Live now” (with pulsing dot) / “Recorded”.
- One-click action — RSVP for upcoming, jump-to-recording for past sessions, no clicking through.
- Click the title for a full detail page with the session description, format breakdown, and who it’s for.
The grouping (Live / Upcoming / Past) means the right session is always at the top of what they see. New visitors see “what’s next” without scrolling.
What landed
Content schema
src/content.config.ts defines the webinars collection. Required fields: title, date_scheduled. Optional: lede, date_posted, durationMinutes, presenters[], tags[], rsvpUrl, recordingUrl. status is deliberately NOT in the schema — it’s derived.
const webinars = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/webinars' }),
schema: z.object({
title: z.string(),
lede: z.string().optional(),
date_scheduled: z.coerce.date(),
date_posted: z.coerce.date().optional(),
durationMinutes: z.number().optional(),
presenters: z.array(z.string()).optional(),
tags: z.array(z.string()).optional(),
rsvpUrl: z.string().url().optional(),
recordingUrl: z.string().url().optional(),
}),
});
Status inference
src/lib/webinar-status.ts exports inferWebinarStatus({ date_scheduled, durationMinutes }) returning 'Upcoming' | 'Live' | 'Recorded':
now < date_scheduled→ Upcomingdate_scheduled ≤ now < date_scheduled + duration→ Live (default duration: 60 min)now ≥ date_scheduled + duration→ Recorded
Pure function. Accepts a now override for snapshot tests.
Components
WebinarCard.astro— calendar-style card. Date tear-off (MAY / 15 / FRI), status badge, title (linked to detail), lede, meta dl (When / With), CTA. Recorded variant uses an outlined CTA so it doesn’t compete with active sessions. Live status has a pulsing dot. Hover lifts the shadow and switches the border to--color-primary. Responsive collapse on narrow screens.- All tokens via the two-tier system — no hardcoded hex values.
Pages
/webinars/index.astro— three sections rendered conditionally: Live now (with pulsing accent dot in the section header), Upcoming (sorted nearest first), Past sessions (sorted most-recent first). Empty-state message points atsrc/content/webinars/for first-time authoring./webinars/[id].astro— detail page. Same date tear-off, scaled up (4.5rem day digit, weekday spelled out, year underneath). Bigger title. Meta panel with When / With / Tags. Same CTA. Markdown body rendered via Astro 6’s built-inrender(entry)with scoped prose styles to counter Tailwind preflight (the recurring cross-site list-styles bug that the LFM blueprint flags).
Catalog + nav
Headergained aWebinarsnav link.WebinarCardcataloged in/design-systemwith all three status variants stacked side by side (synthetic dates) plus a Props + tokens spec — per the maintenance motion that every new component lands in/design-systemin the same change that introduces it.
Sample content
src/content/webinars/2026-05_agentic-vc-dojo-launch.md — the Launch Session. Format breakdown, who it’s for. Real frontmatter as a working example for the next entry’s author.
Authoring a new session
# Create the file
touch sites/fullstack-vc/src/content/webinars/2026-06_topic-slug.md
Minimal frontmatter:
---
title: "Session Title"
lede: "One-sentence hook."
date_scheduled: 2026-06-15T17:00:00-04:00
date_posted: 2026-04-25
durationMinutes: 60
presenters:
- Michael Staton
rsvpUrl: https://lu.ma/your-event-url
---
Body markdown describing the session.
If the dev server doesn’t pick it up immediately: rm -rf sites/fullstack-vc/.astro && pnpm --filter fullstack-vc dev. Astro 6’s content-collection sync sometimes misses freshly-added files mid-session.
What’s still TBD
- RSVP infrastructure. Currently the
rsvpUrlfield accepts any URL. Plan: point at Luma (lu.ma) once the first event is created — built for tech community events, common among VCs, handles invites + reminders + waitlists. We do not build RSVP ourselves. - Detail page polish. The body prose styles are functional but minimal. If we adopt
@lossless-group/lfmlater for richer markdown (callouts, citations), the body will upgrade automatically.
Files modified (8)
sites/fullstack-vc/src/content.config.tssites/fullstack-vc/src/lib/webinar-status.tssites/fullstack-vc/src/components/webinars/WebinarCard.astrosites/fullstack-vc/src/pages/webinars/index.astrosites/fullstack-vc/src/pages/webinars/[id].astrosites/fullstack-vc/src/content/webinars/2026-05_agentic-vc-dojo-launch.mdsites/fullstack-vc/src/components/basics/Header.astrosites/fullstack-vc/src/pages/design-system/index.astro