Code Structure
The src/ directory contains the framework code. Generally, you won't need to modify these files unless creating custom layouts.
Directory Overview
src/
├── layouts/ # Layout components
│ ├── docs/ # Documentation layouts
│ ├── blogs/ # Blog layouts
│ ├── custom/ # Custom page layouts
│ ├── navbar/ # Navbar variants
│ ├── footer/ # Footer variants
│ └── BaseLayout.astro # Root HTML layout
│
├── loaders/ # Configuration & data loading
│ ├── index.ts # Main exports
│ ├── config.ts # YAML config loader
│ ├── data.ts # Content loader
│ ├── alias.ts # Path alias resolver (@data, @assets)
│ └── paths.ts # Path utilities from .env
│
├── parsers/ # Content parsing pipeline
│ ├── core/ # Base parser & pipeline
│ ├── preprocessors/ # Run before markdown (asset embed)
│ ├── renderers/ # Markdown → HTML (marked)
│ ├── transformers/ # Custom tags (callout, tabs)
│ ├── postprocessors/ # Run after HTML (heading IDs, links)
│ └── content-types/ # Docs vs Blog parsing
│
├── hooks/ # Reusable logic
│ └── useSidebar.ts # Sidebar tree building
│
├── pages/ # Astro routes
│ ├── [...slug].astro # Universal dynamic route
│ └── assets/ # Asset serving endpoint
│
└── styles/
└── globals.css # CSS variables & base styles
Core Flow
site.yaml (pages config)
↓
[...slug].astro (route handler)
↓
┌───┴───┐
↓ ↓
Layout Content
Resolver Loader
↓ ↓
└───┬───┘
↓
BaseLayout
+ Navbar
+ Content Layout
+ Footer
Layouts
Layout Organization
Each content type has a styles/ folder with complete layouts:
layouts/
├── docs/
│ ├── styles/
│ │ ├── doc_style1/ # Complete layout bundle
│ │ │ ├── Layout.astro # Main component
│ │ │ ├── layout.css # Styles
│ │ │ └── index.ts # Exports
│ │ └── doc_style2/
│ │
│ └── components/ # Shared components
│ ├── sidebar/default/
│ ├── body/default/
│ └── outline/default/
│
├── blogs/
│ └── styles/
│ └── blog_style1/
│ ├── IndexLayout.astro # Blog index
│ └── PostLayout.astro # Single post
│
└── custom/
└── styles/
├── home/
└── info/
Layout Resolution
The [...slug].astro route resolves layouts using glob imports:
// Auto-discover all layouts
const docsLayouts = import.meta.glob('/src/layouts/docs/styles/*/Layout.astro');
const blogIndexLayouts = import.meta.glob('/src/layouts/blogs/styles/*/IndexLayout.astro');
const customLayouts = import.meta.glob('/src/layouts/custom/styles/*/Layout.astro');
// Config reference
layout: "@docs/doc_style1" // → /src/layouts/docs/styles/doc_style1/Layout.astro
layout: "@blog/blog_style1" // → /src/layouts/blogs/styles/blog_style1/*.astro
layout: "@custom/home" // → /src/layouts/custom/styles/home/Layout.astro
Loaders
config.ts - Configuration Loading
Loads and validates YAML configuration:
import { loadSiteConfig, loadNavbarConfig, getSiteLogo } from '@loaders/config';
const site = loadSiteConfig(); // site.yaml → pages, metadata
const navbar = loadNavbarConfig(); // navbar.yaml → nav items
const logo = getSiteLogo(); // site.yaml → logo with resolved URLs
data.ts - Content Loading
Loads markdown content using the parser system:
import { loadContent, loadContentWithSettings } from '@loaders/data';
// Load docs (requires XX_ prefix)
const docs = await loadContent(dataPath, 'docs', {
pattern: '**/*.{md,mdx}',
sort: 'position',
requirePositionPrefix: true,
});
// Load blog posts (sorted by date)
const posts = await loadContent(dataPath, 'blog', {
pattern: '*.{md,mdx}',
sort: 'date',
order: 'desc',
});
alias.ts - Path Aliases
Resolves @ prefixed paths:
import { resolveAliasPath, resolveAssetUrl } from '@loaders/alias';
// Filesystem paths
resolveAliasPath('@data/docs'); // → /abs/path/to/dynamic_data/data/docs
resolveAliasPath('@docs/doc_style1'); // → /abs/path/to/src/layouts/docs/doc_style1
// Web URLs (for assets)
resolveAssetUrl('@assets/logo.svg'); // → /assets/logo.svg
Parser System
The modular parser processes markdown content through a pipeline:
Raw Markdown
↓
┌─────────────────────┐
│ Preprocessors │ ← Asset embedding [[./assets/code.py]]
└─────────────────────┘
↓
┌─────────────────────┐
│ Renderer │ ← Markdown → HTML (marked)
└─────────────────────┘
↓
┌─────────────────────┐
│ Postprocessors │ ← Heading IDs, external links
└─────────────────────┘
↓
Final HTML
Content Type Parsers
// docs.ts - Documentation parser
class DocsParser extends BaseContentParser {
// Pipeline: asset-embed → render → heading-ids → external-links
// Filename: 01_getting-started.md → position: 1, slug: getting-started
}
// blog.ts - Blog parser
class BlogParser extends BaseContentParser {
// Filename: 2024-01-15-hello.md → date: 2024-01-15, slug: hello
}
Hooks
useSidebar.ts
Builds sidebar navigation tree from flat content array:
import { buildSidebarTree, getPrevNext } from '@/hooks/useSidebar';
// Build hierarchical tree from flat content
const sections = buildSidebarTree(content, '/docs', dataPath);
// Get prev/next for pagination
const { prev, next } = getPrevNext(sections, currentPath);
Sorting: Uses XX_ prefix from folder/file names as the sole ordering mechanism.
Pages
[...slug].astro - Universal Route
Handles all page requests:
- getStaticPaths(): Generates all routes from
site.yamlpages config - Validates layout: Throws descriptive errors if layout missing
- Loads content: Uses appropriate parser (docs/blog)
- Renders: Composes BaseLayout + Navbar + Content Layout + Footer
assets/[...path].ts - Asset Endpoint
Serves static files from ASSETS_DIR:
- Reads files from configured assets directory
- Sets appropriate MIME types
- Enables caching headers
Key Files Reference
| File | Purpose |
|---|---|
layouts/BaseLayout.astro |
HTML structure, head meta, favicon, theme |
pages/[...slug].astro |
Universal route, layout resolution |
loaders/config.ts |
YAML config loading, validation |
loaders/data.ts |
Content loading with parser |
loaders/alias.ts |
@ prefix path resolution |
parsers/content-types/docs.ts |
Docs parsing (XX_ prefix) |
parsers/content-types/blog.ts |
Blog parsing (date prefix) |
hooks/useSidebar.ts |
Sidebar tree, pagination |