Pages & Routes

Route Structure

RouteFileCollectionTemplate
/index.astroAll 5BaseLayout + HeroSlider + SectionCarousel x6
/404404.astroBaseLayout (noIndex)
/rss.xmlrss.xml.tsAll 5RSS endpoint (top 50, always excludes drafts)
/{type}/{type}/index.astroOneCategoryIndex with type-specific accent color
/{year}/tank-talk/{slug}/[year]/tank-talk/[...slug].astrotank-talkWineryArticleTemplate
/{year}/one-voice/{slug}/[year]/one-voice/[...slug].astroone-voiceWineryArticleTemplate
/{year}/raise-a-glass/{slug}/[year]/raise-a-glass/[...slug].astroraise-a-glassInline template
/{year}/uncorked/{slug}/[year]/uncorked/[...slug].astrouncorkedInline template
/{year}/operation-storyteller/{slug}/[year]/operation-storyteller/[...slug].astrooperation-storytellerInline template
/{year}/hot-off-the-vine/{slug}/[year]/hot-off-the-vine/[...slug].astrohot-off-the-vineThin MDX wrapper

Category Landing Pages

All 6 follow the same pattern:

  1. getCollection(type) with environment-aware draft filtering
  2. Map entries to card objects (title, description, date, heroImage, entity logo/name)
  3. Sort by publishDate descending
  4. Render via CategoryIndex component

Entity field per type: tank-talk/one-voice -> winery, uncorked -> venue, raise-a-glass -> company, hot-off-the-vine -> brand, operation-storyteller -> none

Accent colors (oklch): Tank Talk 0.55 0.02 75, One Voice 0.55 0.12 110, Uncorked 0.55 0.15 160, Raise a Glass 0.65 0.16 55, HOTV 0.48 0.16 10, Op Storyteller 0.55 0.15 290

Dynamic Article Routes

All use [year]/collection/[...slug].astro:

Template Assignments

Tank Talk + One Voice -> WineryArticleTemplate (shared in src/components/article/templates/). Full interview layout: FeatureCover, ProfileCard, IntroSection, InterviewTimeline with slotted ProductShowcase and PhotoSliders, Featured Wines grid.

Raise a Glass + Uncorked -> Inline templates in page files. Same interview components (InterviewTimeline, ProfileCard, IntroSection) plus FindOurWinesAt. FeatureCover hero, career highlights (raise-a-glass only).

Operation Storyteller -> Inline template. Prose-first layout with author bio, category pill (6 color-coded categories), reading time, series info, related interviews, optional ProductShowcase.

Hot Off The Vine -> Thin MDX wrapper. BaseLayout + SmoothScroll + body background from themeColors.background + <Content />. All visual composition lives in the MDX file.

Photo Slider Resolution

1. Page template: import.meta.glob("/src/content/{type}/**/assets/photo-slider-*/*.{jpg,...}")
2. resolvePhotoSliders() maps string paths -> ImageMetadata
3. Returns Record<sectionNumber, ResolvedSlider> passed to template/timeline

Glob must use static string literal per Vite constraint.

Homepage Data Flow

getCollection() x 5 (parallel) -> filter drafts -> toIndexArticle()
  -> getHeroArticles(): 3 real + 4 placeholders = 7 hero cards
  -> getSectionArticles(): per-section arrays padded with gradient placeholders