A curated collection of design system resources and video content, powered by Astro.
DesignSystems.media aggregates and showcases the best design system content from across the web, making it easy for designers and developers to discover talks, tutorials, and insights from the design systems community.
- Automated content curation from YouTube channels and playlists
- Static Astro site optimized for performance, SEO, and search indexing
- Shared content-domain layer for pages, APIs, and metadata
- Prebuild content validation for assets and internal references
- Responsive UI with reusable Astro and React components
- Social media image generation during build
- Node.js v20 or higher
- Google API key for YouTube Data API v3 (Get one here)
-
Clone the repository
git clone https://github.com/DesignSystemsCollective/designsystems.media.git cd designsystems.media -
Install dependencies
npm install
-
Set up environment variables
cp .env.example .env
-
Validate local content
npm run validate:content
-
Aggregate initial content
npm run aggregate
-
Start development server
npm run dev
Visit http://localhost:4321 to see the site running locally.
The site now uses a shared content-domain layer so content collections are loaded and indexed in one place instead of being queried directly from route files.
src/lib/content-domain/loaders.ts: one-pass collection loadingsrc/lib/content-domain/normalizers.ts: taxonomy, slug, and date normalizationsrc/lib/content-domain/selectors.ts: derived indexes and selectorssrc/lib/content-domain/index.ts: public query interface used by pages, APIs, and componentsscripts/lib/content-validation.mjs: reusable validation logic for build-time checks
This keeps Astro getCollection() access inside a single boundary and removes duplicated route logic for tags, speakers, shows, playlists, stats, and sitemap generation.
Decision records for the major refactors live under docs/adr/.
├── public/ # Static assets served directly
│ ├── fonts/ # Custom web fonts
│ └── social/ # Social media cards and generated images
├── scripts/ # Build-time validation and maintenance scripts
│ └── lib/ # Shared script helpers
├── src/
│ ├── components/ # Reusable Astro and React components
│ ├── content/ # MDX content collections and schemas
│ ├── layouts/ # Page layout templates
│ ├── lib/
│ │ └── content-domain/ # Shared content query layer
│ ├── pages/ # File-based routes and API endpoints
│ ├── styles/ # Global CSS, themes, and tokens
│ ├── templates/ # Content templates for posts
│ ├── tests/ # Unit, smoke, and visual regression tests
│ └── utils/ # General helpers
├── video-aggregator/ # Content ingestion automation
│ ├── data/ # Source configurations and generated outputs
│ └── scripts/ # Collection and processing scripts
├── docs/
│ └── adr/ # Architecture decision records
├── astro.config.mjs # Astro framework configuration
└── package.json # Dependencies and scripts
| Command | Description |
|---|---|
npm run dev |
Start the Astro development server at localhost:4321 |
npm run validate:content |
Validate content assets and internal references |
npm run build |
Run content validation, then create a production build |
npm run preview |
Preview the production build with Astro |
npm run serve |
Serve the built dist/ directory |
npm run aggregate |
Collect the latest video metadata from configured sources |
npm run videos |
Run the video ingestion script |
npm run podcasts |
Run the podcast ingestion script |
npm run images |
Fetch or generate content images |
npm run test:unit |
Run unit tests for content selectors and validation |
npm run test:smoke |
Build the site, then verify generated pages and internal links |
npm run test:visual |
Build the site, then run curated Playwright screenshot checks |
npm run test:visual:update |
Rebuild the site and refresh Playwright screenshot baselines |
npm run build now runs validation before Astro starts:
npm run validate:contentastro build
Validation currently checks for:
- Missing local image assets referenced from frontmatter
- Duplicate slugs inside a collection
- Playlist items that reference missing content
- Podcast episodes that reference unknown
showSlugvalues
The ingestion scripts collect data from:
video-aggregator/data/sources.jsonfor YouTube channels and playlists to monitorvideo-aggregator/data/ignoreID.jsonfor YouTube videos to ignore
Adding new sources:
- Edit the appropriate JSON file in
video-aggregator/data/ - Run
npm run aggregate - Review the generated output in
video-aggregator/data/output.json
Unit coverage lives under src/tests/unit/ and focuses on:
- taxonomy normalization and slug generation
- selector and index generation in the content domain
- content validation behavior
Run them with:
npm run test:unitSmoke coverage lives under src/tests/smoke/ and verifies that the built site is intact:
- every generated HTML page loads successfully
- internal links resolve without 4xx or 5xx responses
Run it with:
npm run test:smokeVisual coverage lives under src/tests/visual/ and snapshots a curated set of stable routes in Chromium desktop and mobile viewports.
Covered surfaces currently include:
- homepage
/all//podcast/- one representative video detail page
- one representative podcast episode page
- one show page
- one tag page
- one speaker page
- one playlist page
To keep baselines stable, the visual tests:
- force reduced motion and disable CSS transitions
- wait for fonts and page chrome before capturing screenshots
- mask animated homepage counters
- mask dynamic content grids on
/all/and/podcast/
Run the visual suite with:
npm run test:visualRefresh baselines locally with:
npm run test:visual:updateThe site is deployed via Netlify when code is pushed to the main branch. Content aggregation runs on scheduled GitHub Actions to keep the collection up to date.
Manual deployment:
npm run buildDeploy the contents of dist/ to your hosting provider.
We welcome contributions. A typical change flow is:
- Fork the repository
- Create a feature branch
- Make your changes
- Run
npm run test:unit,npm run test:smoke, andnpm run build - Commit and push your branch
- Open a Pull Request
When adding or editing MDX content:
- run
npm run validate:contentbefore opening a PR - ensure local image references in frontmatter actually exist
- ensure podcast episodes reference a valid
showSlug - ensure playlist items reference valid
mediaorpodcastslugs
When adding new pages or APIs:
- consume data through
src/lib/content-domain/ - avoid direct
getCollection()usage outside the content-domain layer - keep route files focused on shaping page props, not indexing collections
- run
npm run test:visualwhen changing layout, styling, or component rendering
To suggest new YouTube videos, channels, or playlists:
- Submit a video contribution with the relevant YouTube URLs
- Optionally include relevant tags and speakers
- We will review and add valuable sources to the collection
This project is licensed under the MIT License. See LICENSE for details.
- Design Systems Community for creating amazing content
- Astro for the framework
- All the creators whose content we feature
Questions or suggestions? Open an issue or reach out to Design Systems Media.
