Slides System — Auto-Discovery, Theme Integration, and Image Assets
RevealJS decks now find themselves from three different sources — component decks, standalone .astro pages, and plain markdown — and inherit the site theme properly, dark/light switching included.
Changelog - 2025-12-14 (#1)
Hypernova Site: Slides System Implementation — Auto-Discovery, Theme Integration, and Image Assets
Overview
This sprint delivered a comprehensive RevealJS slides system for the Hypernova site with three major capabilities:
Auto-Discovery — Presentations are automatically discovered from three sources: component decks, standalone
.astropages, and markdown files.Theme/Mode Integration — Slides properly inherit the Hypernova theme and respond to dark/light mode switching.
Image Assets — Consistent
coverImage/shareImageproperties with intelligent fallbacks across all presentation types.
Key Achievement: A unified presentation system that supports both highly-designed component decks and quick markdown-based presentations, all with proper theming.
Architecture
src/pages/slides/
├── index.astro ← Auto-discovers all presentations
├── [...slug].astro ← Dynamic routing for all deck types
├── Global-CVC-for-Multinationals.astro ← Standalone presentation
└── The-Future-of-CPG.astro ← Standalone presentation
src/data/
├── componentDecks.ts ← Registry for component-based decks
└── markdownDecks.ts ← Loader for markdown content collection
src/layouts/
├── OneSlideDeck.astro ← RevealJS wrapper with theme integration
└── MarkdownSlideDeck.astro ← Markdown-to-slides converter
src/content/slides/
└── *.md ← Markdown presentations (slide separator: ---)Presentation Discovery Flow
slides/index.astro
│
├─► componentDecks.ts ──► Component Decks (hypernova-strategy)
│
├─► import.meta.glob('./*.astro') ──► Standalone Pages
│
└─► markdownDecks.ts ──► Markdown Decks (institutional-grade, etc.)
│
▼
Unified Presentation[] ──► TitleSlidePreviewCard ──► Grid DisplayChanges by Area
1. Component Deck System
New: src/data/componentDecks.ts
Registry for component-based presentations with rich metadata:
export interface ComponentDeck {
title: string;
description: string;
component: string;
author?: string;
date?: string;
tags?: string[];
type: 'component';
// Image assets
coverImage?: string; // Card preview on index page
shareImage?: string; // OpenGraph/social sharing
}
export const componentDecks: Record<string, ComponentDeck> = {
'hypernova-strategy': {
title: 'Hypernova Fund-with-Funds Strategy',
description: 'A differentiated approach to venture capital...',
component: 'SlideShowHypernovaStrategy',
author: 'Hypernova Capital',
date: '2025-12-14',
shareImage: '/share-banners/shareBanner__Hypernova-Cover.jpeg',
type: 'component',
}
};Helper functions:
getComponentDeck(slug)— Get a single deck by sluggetAllComponentDecks()— Get all decks as array with slugs
2. Markdown Deck Auto-Loading
New: src/data/markdownDecks.ts
Dynamically loads markdown presentations from the slides content collection:
interface MarkdownDeckData {
title: string;
description: string;
component: string;
content?: string;
coverImage?: string;
shareImage?: string;
}
// Loads all markdown files from src/content/slides/*.md
const loadMarkdownDecks = async () => {
const slides = await getCollection('slides');
for (const slide of slides) {
markdownDecks[slug] = {
title: slide.data.title,
description: slide.data.description,
coverImage: slide.data.coverImage,
shareImage: slide.data.shareImage,
content: slide.body
};
}
};3. Auto-Discovery in Index Page
Modified: src/pages/slides/index.astro
Unified presentation interface combining all three sources:
interface Presentation {
title: string;
slug: string;
description: string;
date?: string;
author?: string;
tags?: string[];
icon?: string;
coverImage?: string; // For card display
shareImage?: string; // For OpenGraph
type: 'component' | 'standalone' | 'markdown';
}Discovery sources:
Component decks from
componentDecks.tsregistryStandalone
.astropages viaimport.meta.glob('./*.astro')with lazy loadingMarkdown decks from
markdownDecks.ts
Key fix: Changed from eager: true to lazy loading to prevent OneSlideDeck's CSS from leaking into the index page.
4. Theme/Mode Integration
Modified: src/layouts/OneSlideDeck.astro
Fixed theming to use Hypernova theme with proper dark mode:
<!-- Before -->
<html lang="en" data-theme="water">
import '@styles/water-theme.css';
<!-- After -->
<html lang="en" class="theme-hypernova dark" data-theme="hypernova" data-mode="dark">
import '@styles/nova-theme.css';CSS Variables for slides:
:root {
--slide-bg-primary: rgb(var(--color-primary-950));
--slide-text-primary: rgb(var(--color-primary-50));
--slide-text-secondary: rgb(var(--color-primary-100));
--slide-accent: rgb(var(--color-accent-500));
--slide-accent-bright: rgb(var(--color-accent-300));
}5. MarkdownSlideDeck Rewrite
Modified: src/layouts/MarkdownSlideDeck.astro
Complete rewrite to fix broken nested HTML structure:
Before: Created its own <!DOCTYPE html> and nested BaseThemeLayout inside, causing theme conflicts.
After: Simply wraps content in OneSlideDeck:
<OneSlideDeck title={title} description={description}>
<Fragment set:html={slidesHtml} />
</OneSlideDeck>
<style is:global>
.slide h1 { color: var(--slide-text-primary); }
.slide h2 { color: var(--slide-text-primary); }
.slide p { color: var(--slide-text-secondary); }
.slide strong { color: var(--slide-accent-bright); }
</style>6. Mode-Responsive Preview Cards
Modified: src/components/slides/TitleSlidePreviewCard.astro
Refactored CSS to respond to dark/light mode:
/* Light mode defaults */
.presentation-card {
background: var(--color-card);
border: 1px solid var(--color-border);
}
/* Dark mode overrides */
:global(html[data-mode="dark"]) .presentation-card,
:global(html.dark) .presentation-card {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.1);
}7. Image Asset Fallback System
Image property cascade:
// Card display: coverImage → shareImage → site default
const displayImage = coverImage || shareImage || DEFAULT_COVER_IMAGE;
// Share button: shareImage → coverImage → site default
image={shareImage || coverImage || DEFAULT_SHARE_IMAGE}Default images created:
public/images/slides/
├── default-cover.jpg # 1600x900 card preview
└── default-share.jpg # 1200x630 OpenGraphFiles Changed Summary
New
src/data/componentDecks.ts— Component deck registry with metadatasrc/data/markdownDecks.ts— Markdown deck auto-loadersrc/components/slides/astro-decks/hypernova-strategy/— 6-slide strategy decksrc/pages/slides/Global-CVC-for-Multinationals.astro— Standalone presentationsrc/pages/slides/The-Future-of-CPG.astro— Standalone presentationpublic/images/slides/default-cover.jpg— Default card preview imagepublic/images/slides/default-share.jpg— Default OpenGraph image
Modified
src/pages/slides/index.astro— Auto-discovery for all three presentation typessrc/pages/slides/[...slug].astro— Dynamic routing for component + markdown deckssrc/layouts/OneSlideDeck.astro— Theme/mode attributes fixedsrc/layouts/MarkdownSlideDeck.astro— Complete rewrite for proper theme inheritancesrc/components/slides/TitleSlidePreviewCard.astro— Mode-responsive CSS + image fallbackssrc/layouts/BoilerPlateHTML.astro— Removed redundant favicon fallbacktsconfig.json— Added@data/*path alias
Removed
Water Foundation themed decks (meet-at, variant-1) — Not appropriate for Hypernova site
src/content/markdown-memos/from git tracking
Commits Included
001cccf— wip(slides): progress on rendering slides across complete-astro, components-astrob19b7ee— enhance(slides): enhance slides feature through autodiscovery of markdown slideshows69c4510— wip(slides): implemented theme sensitive styles and mode switching abilities
Notes / Follow-Ups
Markdown slides use
---as slide separators (horizontal rules)Markdown presentations display with
M↓icon to distinguish from component decksConsider adding date/author fields to markdown frontmatter for better sorting
The specification document at
context-v/Slides-System-for-Astro-and-Markdown.mdwas updated with image asset naming conventions
