Files
v10/website

🚀 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:

  1. Blog - News, updates, and announcements about Video.js
  2. 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:

  1. Filter sidebar based on framework/style
  2. Generate pages only for guides visible in that combination
  3. 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:

  1. User switches from "React" to "HTML"
  2. System checks if current guide supports HTML
  3. If yes: Navigate to same guide with HTML/best-style
  4. 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:

  1. Wraps the generateId function to capture ID transformations
  2. Stores mapping: transformed ID → original filename
  3. Injects custom parser that receives both values
  4. Parser adds metadata to entry before schema validation

Why it's needed:

  • generateId transforms: 2024-01-15-post.mdpost
  • Parser needs access to 2024-01-15-post.md to 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 frameworks
  • SupportedStyle<F> - Style type specific to a framework
  • Guide - Guide definition with optional restrictions
  • Section - Recursive type for sidebar sections
  • Sidebar - Array of top-level sections

See types/docs.ts for complete type definitions.

Development Workflow

Adding a Blog Post

  1. Create file: src/content/blog/YYYY-MM-DD-slug.md
  2. Add frontmatter: title, description, optional heroImage
  3. Write content in Markdown or MDX
  4. The pubDate is automatically extracted from filename
  5. The updatedDate is automatically pulled from git on subsequent commits

Adding a Documentation Page

  1. Create file: src/content/docs/category/page-name.mdx

  2. Add frontmatter: title, description

  3. Add to sidebar in src/config/docs/sidebar.ts:

    {
      title: 'Category',
      guides: [
        {
          slug: 'category/page-name',
          frameworks: ['react'], // optional
          styles: ['tailwind', 'css'] // optional
        }
      ]
    }
    
  4. Use conditional components for framework/style-specific content

Adding a New Framework

  1. Update FRAMEWORK_STYLES in types/docs.ts
  2. Add available styles for the framework
  3. Update documentation to include framework-specific guides
  4. The system will automatically generate all URL combinations

Adding a New Style

  1. Update FRAMEWORK_STYLES in types/docs.ts
  2. Add the style to appropriate framework(s)
  3. Update documentation guides to support the new style
  4. 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