← All changelog entries
April 25, 2025 · Feature

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.

Authors
Michael Staton
Augmented with
Claude Code on Opus 4.7
Tags
#Webinars#Agentic-VC-Dojo#Content-Collection#Calendar-UI#Status-Inference#Schema-Design

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 sets status manually — it can never go stale.
  • The card’s CTA flips from “RSVP” to “Watch recording” automatically when you add a recordingUrl to 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_scheduledUpcoming
  • date_scheduled ≤ now < date_scheduled + durationLive (default duration: 60 min)
  • now ≥ date_scheduled + durationRecorded

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 at src/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-in render(entry) with scoped prose styles to counter Tailwind preflight (the recurring cross-site list-styles bug that the LFM blueprint flags).

Catalog + nav

  • Header gained a Webinars nav link.
  • WebinarCard cataloged in /design-system with 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-system in 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 rsvpUrl field 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/lfm later for richer markdown (callouts, citations), the body will upgrade automatically.
Files modified (8)
  • sites/fullstack-vc/src/content.config.ts
  • sites/fullstack-vc/src/lib/webinar-status.ts
  • sites/fullstack-vc/src/components/webinars/WebinarCard.astro
  • sites/fullstack-vc/src/pages/webinars/index.astro
  • sites/fullstack-vc/src/pages/webinars/[id].astro
  • sites/fullstack-vc/src/content/webinars/2026-05_agentic-vc-dojo-launch.md
  • sites/fullstack-vc/src/components/basics/Header.astro
  • sites/fullstack-vc/src/pages/design-system/index.astro