🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
├── public/
├── src/
│ ├── components/
│ ├── content/
│ ├── layouts/
│ └── pages/
├── astro.config.mjs
├── README.md
├── package.json
└── tsconfig.json
Astro looks for .astro or .md files in the src/pages/ directory. Each page is exposed as a route based on its file name.
There's nothing special about src/components/, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
The src/content/ directory contains "collections" of related Markdown and MDX documents. Use getCollection() to retrieve posts from src/content/blog/, and type-check your frontmatter using an optional schema. See Astro's Content Collections docs to learn more.
Any static assets, like images, can be placed in the public/ directory.
🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
|---|---|
pnpm install |
Installs dependencies |
pnpm dev |
Starts local dev server at localhost:4321 |
pnpm build |
Build your production site to ./dist/ |
pnpm preview |
Preview your build locally, before deploying |
pnpm astro ... |
Run CLI commands like astro add, astro check |
pnpm astro -- --help |
Get help using the Astro CLI |
🚀 Project architecture
Overview
The website serves two main purposes:
- Blog - News, updates, and announcements about Video.js
- Documentation - Multi-framework documentation system with conditional content
Project Structure
website/
├── src/
│ ├── components/ # Reusable UI components
│ │ └── docs/ # Documentation-specific components
│ ├── config/ # Configuration files
│ │ └── docs/ # Documentation sidebar configuration
│ ├── content/ # Content collections (blog, docs)
│ │ ├── blog/ # Blog posts (Markdown/MDX)
│ │ └── docs/ # Documentation pages (MDX)
│ ├── layouts/ # Page layouts
│ ├── pages/ # Route definitions
│ ├── styles/ # Global styles
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utility functions
│ └── consts.ts # Site-wide constants
├── public/ # Static assets (fonts, favicon, images)
└── astro.config.mjs # Astro configuration
Key Features
1. Blog System
The blog uses Astro's Content Collections API with a custom loader for automatic metadata extraction.
Filename Convention
Blog posts use date-prefixed filenames: YYYY-MM-DD-slug.{md,mdx}
Example: 2024-01-15-new-release.md
Automatic Metadata
- Publication date is extracted from the filename
- Updated date is pulled from git history (last commit that modified the file)
- URL slug has the date prefix removed for clean URLs (
/blog/new-release/)
Implementation
See content.config.ts for the blog collection definition and utils/globWithParser.ts for the custom loader implementation.
2. Multi-Framework Documentation System
The most sophisticated part of the website is the documentation system, which adapts content based on:
- Framework (HTML, React)
- Styling approach (CSS, Tailwind, Styled-Components)
URL Structure
/docs/framework/{framework}/style/{style}/{slug}/
Example: /docs/framework/react/style/tailwind/concepts/state-management/
Framework/Style Matrix
| Framework | Available Styles |
|---|---|
| HTML | css, tailwind |
| React | css, tailwind, styled-components |
Content Filtering
Documentation pages can be restricted to specific frameworks or styles:
In sidebar config (config/docs/sidebar.ts):
{
title: 'React Concepts',
guides: [
{ slug: 'concepts/hooks' }, // Available to all
{
slug: 'concepts/styling',
frameworks: ['react'], // Only for React
styles: ['styled-components'] // Only for styled-components
}
]
}
Within MDX content (using conditional components):
<FrameworkCase frameworks={['react']}>This content only appears in React docs.</FrameworkCase>
<StyleCase styles={['tailwind']}>This content only appears when Tailwind is selected.</StyleCase>
Static Site Generation
The docs system generates all valid framework/style/slug combinations at build time:
- Filter sidebar based on framework/style
- Generate pages only for guides visible in that combination
- Each page is pre-rendered with the appropriate filtered sidebar
See pages/docs/framework/[framework]/style/[style]/[...slug].astro for implementation.
Smart Navigation
The framework/style selectors (components/docs/Selectors.tsx) attempt to preserve the current guide when switching:
- User switches from "React" to "HTML"
- System checks if current guide supports HTML
- If yes: Navigate to same guide with HTML/best-style
- If no: Navigate to first available guide for HTML
This creates a seamless experience where users don't lose their place when switching contexts.
Custom Utilities
globWithParser (utils/globWithParser.ts)
Wraps Astro's glob loader to provide access to both transformed entry IDs and original filenames. This is essential for extracting dates from date-prefixed blog post filenames while maintaining clean URLs.
How it works:
- Wraps the
generateIdfunction to capture ID transformations - Stores mapping:
transformed ID → original filename - Injects custom parser that receives both values
- Parser adds metadata to entry before schema validation
Why it's needed:
generateIdtransforms:2024-01-15-post.md→post- Parser needs access to
2024-01-15-post.mdto extract the date - Without this utility, the original filename is lost after transformation
Content Collections
Blog Collection
- Location:
src/content/blog/ - Formats: Markdown (
.md) and MDX (.mdx) - Required frontmatter:
title,description - Auto-injected:
pubDate(from filename),updatedDate(from git) - Optional:
heroImage
Docs Collection
- Location:
src/content/docs/ - Formats: MDX only (needs conditional components)
- Required frontmatter:
title,description - Auto-injected:
updatedDate(from git) - Visibility: Controlled by sidebar configuration
Layouts
Base Layout
Base HTML structure with:
- SEO meta tags (Open Graph, Twitter Cards)
- Font preloading
- Client-side routing (Astro Transitions)
BlogPost Layout
Extends Base with blog-specific elements:
- Hero image display
- Publication and updated dates
- Article formatting
Docs Layout
Extends Base with documentation features:
- Filtered sidebar navigation
- Framework/style selectors (React component with client-side routing)
- Two-column layout (sidebar + content)
Configuration
Site Configuration
astro.config.mjs includes:
- MDX integration for rich content authoring
- React integration for interactive components (selectors)
- Sitemap generation
- RSS feed generation
- Tailwind CSS via Vite plugin
Sidebar Configuration
config/docs/sidebar.ts defines the documentation structure:
- Hierarchical sections and subsections
- Guide definitions with framework/style restrictions
- Custom sidebar labels (overrides doc titles)
Type System
The documentation system is fully typed in TypeScript:
SupportedFramework- Union type of available frameworksSupportedStyle<F>- Style type specific to a frameworkGuide- Guide definition with optional restrictionsSection- Recursive type for sidebar sectionsSidebar- Array of top-level sections
See types/docs.ts for complete type definitions.
Development Workflow
Adding a Blog Post
- Create file:
src/content/blog/YYYY-MM-DD-slug.md - Add frontmatter:
title,description, optionalheroImage - Write content in Markdown or MDX
- The
pubDateis automatically extracted from filename - The
updatedDateis automatically pulled from git on subsequent commits
Adding a Documentation Page
-
Create file:
src/content/docs/category/page-name.mdx -
Add frontmatter:
title,description -
Add to sidebar in
src/config/docs/sidebar.ts:{ title: 'Category', guides: [ { slug: 'category/page-name', frameworks: ['react'], // optional styles: ['tailwind', 'css'] // optional } ] } -
Use conditional components for framework/style-specific content
Adding a New Framework
- Update
FRAMEWORK_STYLESin types/docs.ts - Add available styles for the framework
- Update documentation to include framework-specific guides
- The system will automatically generate all URL combinations
Adding a New Style
- Update
FRAMEWORK_STYLESin types/docs.ts - Add the style to appropriate framework(s)
- Update documentation guides to support the new style
- The system will automatically generate all URL combinations
Build Output
The site is statically generated with:
- Pre-rendered HTML for all pages
- Client-side routing for SPA-like navigation
- Optimized images via Astro's image optimization
- Sitemap at
/sitemap-index.xml - RSS feed at
/rss.xml
Dependencies
Core Framework
- Astro - Static site generator with island architecture
- React - For interactive components (framework/style selectors)
- TypeScript - Type safety throughout
Content Processing
- @astrojs/mdx - MDX support for rich content
- @astrojs/rss - RSS feed generation
- @astrojs/sitemap - Sitemap generation
Styling
- Tailwind CSS - Via @tailwindcss/vite plugin
- @astrojs/react - React component support
Git Integration
- simple-git - For extracting file modification dates from git history
Performance Considerations
- All pages are pre-rendered at build time
- Client-side routing eliminates full page reloads
- Images are optimized with Astro's built-in image optimization
- Fonts are preloaded to prevent layout shift
- Minimal JavaScript (only for interactive selectors)
Future Enhancements
Areas for potential improvement:
- Add search functionality
- Implement active link highlighting in sidebar
- Create custom 404 page with framework/style context
- Add automated testing for sidebar filtering logic
- Consider server-side rendering for dynamic content