index.md
bok
bok is a fast, minimal static site generator built with Bun. It converts Markdown files to HTML using TypeScript template literals, with a focus on documentation sites and books.
Features
- Fast - Built on Bun for quick builds and hot reloading
- Simple - Markdown in, HTML out, minimal configuration
- Flexible Templates - Use TypeScript template literals for layouts
- Live Reload - Auto-refresh browser on file changes
- Book Theme - Built-in theme inspired by mdBook/GitBook
- Table of Contents - Define page order with a simple TOC file
- Right-side Navigation - Auto-generated on-page heading navigation
- Front Matter - Add metadata to pages with simple key-value pairs
Quick Start
# Install bun if you haven't already
curl -fsSL https://bun.sh/install | bash
# Clone and install
git clone https://github.com/alajmo/bok
cd bok
bun install
# Create a new site
bun run mod.ts init
# Start development server
bun run mod.ts serve config.ts
How It Works
- Configuration - Define your site in
config.ts
- Content - Write pages in Markdown in the
content/ directory
- TOC - Define page order in
content/toc.md
- Build - Run
bok build to generate static HTML
- Serve - Run
bok serve for development with live reload
Philosophy
In the beginning, all you want is results.
In the end, all you want is control.
bok aims to be:
- Explicit over implicit - No magic, clear configuration
- Minimal core - Do one thing well: Markdown to HTML
- Extensible - Hooks and custom layouts for advanced use cases
getting-started.md
Getting Started
This guide will help you create your first bok site.
Prerequisites
You need Bun installed:
curl -fsSL https://bun.sh/install | bash
Installation
From Source
git clone https://github.com/alajmo/bok
cd bok
bun install
Global Install
After cloning, you can install bok globally:
make install
This creates a bok command you can run from anywhere.
Create a New Site
Interactive Mode
Run the init command and follow the prompts:
bok init
You'll be asked to:
- Choose extend (use existing theme) or create (copy theme files)
- Select a theme: basic or book
Non-Interactive Mode
# Extend the book theme
bok init --mode extend --theme book
Project Structure
After initialization, your project looks like this:
my-site/
├── config.ts # Site configuration
└── content/
├── toc.md # Table of contents (page order)
├── index.md # Home page
└── ... # Your markdown pages
Development Workflow
Start the Dev Server
bok serve config.ts
This will:
- Build your site to the output directory
- Start a local server at http://localhost:5000
- Watch for file changes and rebuild automatically
- Reload your browser when files change
Build for Production
bok build config.ts
The generated site will be in the site/ directory (or whatever you configured as paths.output).
Adding Pages
- Create a new
.md file in content/:
# My New Page
This is my new page content.
- Add it to
content/toc.md:
- [My New Page](my-new-page.md)
- Save and watch the browser reload with your new page.
Next Steps
usage.md
CLI Commands
bok provides a simple command-line interface for building and serving your site.
Usage
bok <command> [config]
All commands except init accept an optional path to your config file. If not provided, it defaults to config.ts in the current directory.
Available Commands
| Command |
Description |
| init |
Initialize a new site |
| build |
Build static HTML files |
| watch |
Build and rebuild on file changes |
| serve |
Build, serve, and live reload |
| clean |
Remove the output directory |
Global Options
bok --help # Show help
bok --version # Show version
Examples
# Initialize a new site
bok init
# Build using default config.ts
bok build
# Build with explicit config path
bok build ./my-site/config.ts
# Start development server
bok serve config.ts
# Start server with custom port
bok serve --port 3000 config.ts
init.md
init
Initialize a new bok site in the current directory.
Usage
bok init [options]
Options
| Option |
Description |
--mode <string> |
Create mode: extend or create |
--theme <string> |
Theme to use: basic, book, or path |
--theme-path <string> |
Path to custom theme config (when theme is path) |
Modes
Extend Mode (Recommended)
Extends an existing theme. Creates a minimal config.ts and copies the theme's content directory.
bok init --mode extend --theme book
This creates:
config.ts - References the theme, lets you override params
content/ - Copy of the theme's example content
Your config will look like:
export default {
extends: "book",
params: {
title: "My Site",
},
};
Create Mode
Copies all theme files into your project for full customization.
bok init --mode create --theme book
This creates:
config.ts - Full configuration
content/ - Content directory
layout/ - Template files
assets/ - CSS, JS, images
Interactive Mode
Run without options to use interactive prompts:
bok init
You'll be asked:
- Mode: Extend or create from scratch?
- Theme: Which theme to use?
Using a Custom Theme
Point to your own theme config:
bok init --mode extend --theme path --theme-path /path/to/theme/config.ts
Examples
# Interactive mode
bok init
# Quick start with book theme
bok init --mode extend --theme book
# Full theme customization
bok init --mode create --theme basic
build.md
build
Build your site into static HTML files.
Usage
bok build [config]
Arguments
| Argument |
Description |
Default |
config |
Path to config file |
config.ts |
What It Does
- Cleans the output directory
- Discovers pages based on your file discovery mode (walk, glob, or toc)
- Processes each page:
- Extracts front matter
- Converts Markdown to HTML
- Generates right-side table of contents
- Applies the layout template
- Copies assets (theme assets + public directories)
- Outputs a summary table
Output
After building, you'll see a summary:
[INFO] Building
┌─────────┬────┐
│ │ EN │
├─────────┼────┤
│ # Pages │ 12 │
└─────────┴────┘
Output Directory
By default, files are output to site/ relative to your config file. Configure this with paths.output:
export default {
paths: {
output: "dist", // Output to dist/ instead
},
};
URL Structure
Pretty URLs (default)
content/getting-started.md → site/getting-started/index.html
content/guide/intro.md → site/guide/intro/index.html
content/index.md → site/index.html
Ugly URLs
Set uglyURLs: true in your config:
content/getting-started.md → site/getting-started.html
content/guide/intro.md → site/guide/intro.html
Examples
# Build with default config
bok build
# Build with explicit config
bok build ./docs/config.ts
# Build and then deploy
bok build config.ts && rsync -av site/ server:/var/www/
watch.md
watch
Build your site and automatically rebuild when files change.
Usage
bok watch [config]
Arguments
| Argument |
Description |
Default |
config |
Path to config file |
config.ts |
What It Does
- Performs an initial build
- Watches these directories for changes:
content/ - Your markdown files
assets/ - Theme assets
layout/ - Template files
- Rebuilds when any file changes
Debouncing
Changes are debounced with a 500ms interval to prevent multiple rapid rebuilds when saving multiple files.
Differences from serve
| Feature |
watch |
serve |
| Builds on change |
Yes |
Yes |
| HTTP server |
No |
Yes |
| Live reload |
No |
Yes |
Use watch when you:
- Have your own HTTP server
- Just want to rebuild files
- Are building for deployment
Use serve when you:
- Want a complete development environment
- Need live reload in browser
Examples
# Watch with default config
bok watch
# Watch specific config
bok watch ./docs/config.ts
serve.md
serve
Build, serve, and live reload your site during development.
Usage
bok serve [options] [config]
Arguments
| Argument |
Description |
Default |
config |
Path to config file |
config.ts |
Options
| Option |
Description |
Default |
--port <port> |
HTTP server port |
5000 |
--ws-port <port> |
WebSocket port for live reload |
5001 |
--reload |
Enable live reload |
true |
What It Does
- Performs an initial build
- Starts an HTTP server to serve your site
- Starts a WebSocket server for live reload
- Watches for file changes and rebuilds
- Notifies the browser to reload after rebuilds
Live Reload
When --reload is enabled (default), bok:
- Injects a small JavaScript snippet into HTML pages
- Opens a WebSocket connection to the dev server
- Listens for build completion events
- Automatically reloads the page when content changes
Server Details
The HTTP server:
- Serves static files from the output directory
- Returns
index.html for directory requests
- Serves
404/index.html for missing pages (if it exists)
- Logs all requests to the console
Examples
# Start with defaults (port 5000)
bok serve config.ts
# Custom HTTP port
bok serve --port 3000 config.ts
# Custom WebSocket port
bok serve --ws-port 3001 config.ts
# Disable live reload
bok serve --reload=false config.ts
Configuration
You can also set serve options in your config file:
export default {
serve: {
reload: true,
port: 5000,
wsPort: 5001,
},
};
Command-line options override config file settings.
clean.md
clean
Remove the output directory.
Usage
bok clean [config]
Arguments
| Argument |
Description |
Default |
config |
Path to config file |
config.ts |
What It Does
Deletes the entire output directory (default: site/).
This is useful for:
- Cleaning up before a fresh build
- Removing stale files from deleted pages
- Resetting your project state
Note
The build command already cleans the output directory before building, so you typically don't need to run clean manually.
Examples
# Clean with default config
bok clean
# Clean specific project
bok clean ./docs/config.ts
configuration.md
Configuration
bok uses a TypeScript configuration file (config.ts) to define your site settings.
Basic Config
export default {
extends: "book",
paths: {
output: "site",
},
params: {
title: "My Documentation",
author: "Your Name",
},
};
Configuration Options
extends
Extend a built-in or custom theme.
extends: "book" // Built-in theme
extends: "basic" // Built-in theme
extends: "/path/to/theme/config.ts" // Custom theme
rootUrl
Base URL prefix for all links. Useful when deploying to a subdirectory.
rootUrl: "/docs" // Site served at example.com/docs/
rootUrl: "" // Site served at root (default)
uglyURLs
Use .html extensions instead of directory-based URLs.
uglyURLs: false // /about/ (default)
uglyURLs: true // /about.html
paths
Configure directory locations.
paths: {
content: "content", // Markdown files location
output: "site", // Build output directory
assets: "assets", // Theme assets (CSS, JS, images)
layout: "layout", // Template files
defaultLayout: "index.ts", // Default page template
public: ["public"], // Additional directories to copy
}
All paths are relative to the config file location.
files
Configure how pages are discovered.
// Table of contents mode (recommended for books)
files: {
type: "toc",
file: "toc.md",
}
// Walk all markdown files
files: {
type: "walk",
}
// Glob pattern
files: {
type: "glob",
glob: "**/*.md",
}
serve
Development server settings.
serve: {
reload: true, // Enable live reload
port: 5000, // HTTP server port
wsPort: 5001, // WebSocket port
}
hooks
Lifecycle hooks for custom processing.
hooks: {
async beforeSite(site, pages, opts) {
// Called before building any pages
},
async afterSite(site, pages, opts) {
// Called after all pages are built
},
async beforePage(site, page, index, pages, opts) {
// Called before each page is processed
},
async afterPage(site, page, index, pages, opts) {
// Called after each page is processed
},
}
params
Custom parameters passed to templates.
params: {
title: "My Site",
author: "Your Name",
description: "Site description",
// Any custom data you need in templates
}
Full Example
export default {
extends: "book",
rootUrl: "",
uglyURLs: false,
paths: {
output: "dist",
public: ["images", "downloads"],
},
serve: {
reload: true,
port: 3000,
wsPort: 3001,
},
params: {
title: "My Documentation",
author: "Your Name",
description: "Comprehensive guide",
rightToc: {
enabled: true,
title: "On this page",
minHeadings: 2,
levels: [2, 3],
},
},
};
site-config.md
Site Config
The config.ts file is the heart of your bok site. This page covers all configuration options in detail.
Config Structure
export default {
// Theme to extend
extends?: string,
// URL prefix
rootUrl?: string,
// URL style
uglyURLs?: boolean,
// Directory paths
paths?: {
content?: string,
output?: string,
assets?: string,
layout?: string,
defaultLayout?: string,
public?: string[],
},
// File discovery
files?: {
type: "walk" | "glob" | "toc",
file?: string, // for toc type
glob?: string, // for glob type
},
// Dev server
serve?: {
reload?: boolean,
port?: number,
wsPort?: number,
},
// Lifecycle hooks
hooks?: {
beforeSite?: Function,
afterSite?: Function,
beforePage?: Function,
afterPage?: Function,
},
// Custom data for templates
params?: Record<string, any>,
};
Path Resolution
All paths in the config are resolved relative to the config file's directory.
// If config is at /home/user/my-site/config.ts
paths: {
content: "content", // → /home/user/my-site/content
output: "../docs", // → /home/user/docs
public: ["images"], // → /home/user/my-site/images
}
Extending Themes
When you extend a theme:
- Theme's
hooks are used
- Theme's
paths.assets and paths.layout are used
- Theme's
files config is used (if not overridden)
- Theme's
params are merged with yours (yours take precedence)
// Theme config
params: {
title: "Default Title",
showToc: true,
}
// Your config
params: {
title: "My Title", // Overrides theme
author: "Me", // Added
// showToc: true // Inherited from theme
}
File Discovery Modes
TOC Mode
Best for books and documentation with a specific reading order.
files: {
type: "toc",
file: "toc.md", // Relative to content directory
}
The toc.md file defines:
- Page order
- Navigation structure
- Section groupings
See TOC Format for details.
Walk Mode
Recursively finds all markdown files.
files: {
type: "walk",
}
Good for blogs or sites without strict ordering.
Glob Mode
Find files matching a pattern.
files: {
type: "glob",
glob: "posts/**/*.md",
}
Hooks
Hooks let you customize the build process.
beforeSite
Called once before any pages are processed.
hooks: {
async beforeSite(site, pages, opts) {
// Generate sitemap data
// Set up shared resources
console.log(`Building ${pages.length} pages`);
},
}
afterSite
Called once after all pages are processed.
hooks: {
async afterSite(site, pages, opts) {
// Generate sitemap.xml
// Generate RSS feed
// Post-process output
},
}
beforePage / afterPage
Called for each page.
hooks: {
async beforePage(site, page, index, pages, opts) {
// Modify page before rendering
page.params.buildTime = new Date().toISOString();
},
async afterPage(site, page, index, pages, opts) {
// Post-process individual page
},
}
Params
The params object is passed to all templates. Use it for:
- Site metadata (title, author, description)
- Theme configuration
- Custom data
params: {
// Metadata
title: "My Site",
author: "Your Name",
description: "Site description",
url: "https://example.com",
// Theme options
rightToc: {
enabled: true,
title: "Contents",
levels: [2, 3, 4],
},
// Custom data
socialLinks: {
github: "https://github.com/you",
twitter: "https://twitter.com/you",
},
}
toc-format.md
## Elements
### Headers
Create section titles that appear in the sidebar.
```markdown
# Getting Started
# API Reference
# Advanced Topics
Links
Top-level links without list markers.
[Introduction](index.md)
[About](about.md)
List Items
Numbered chapters with nesting support.
- [Chapter 1](chapter-1.md)
- [Section 1.1](section-1-1.md)
- [Section 1.2](section-1-2.md)
- [Chapter 2](chapter-2.md)
Renders as:
- 1. Chapter 1
- 1.1. Section 1.1
- 1.2. Section 1.2
- 2. Chapter 2
Horizontal Rules
Visual separators between sections.
- [Chapter 1](chapter-1.md)
---
# New Section
- [Chapter 2](chapter-2.md)
Draft Pages
Empty parentheses create a draft entry (no link).
- [Coming Soon]()
This appears in the sidebar but isn't clickable.
Full Example
# My Book
[Introduction](index.md)
- [Getting Started](getting-started.md)
---
# Core Concepts
- [Installation](install.md)
- [macOS](install/macos.md)
- [Linux](install/linux.md)
- [Windows](install/windows.md)
- [Configuration](config.md)
- [Basic Setup](config/basic.md)
- [Advanced Options](config/advanced.md)
---
# API Reference
- [Functions](api/functions.md)
- [Types](api/types.md)
- [Examples](api/examples.md)
---
# Appendix
- [FAQ](faq.md)
- [Changelog](changelog.md)
- [Contributing](contributing.md)
File Paths
Paths are relative to the content/ directory.
# If content/ structure is:
# content/
# index.md
# guide/
# intro.md
# advanced.md
[Home](index.md)
- [Intro](guide/intro.md)
- [Advanced](guide/advanced.md)
Navigation
The TOC automatically generates:
- Left sidebar - Full navigation tree
- Previous/Next links - Based on page order
- Active highlighting - Current page is highlighted
Pages are ordered exactly as they appear in the TOC file.
Front Matter
Front Matter
Front matter lets you add metadata to individual pages.
Syntax
Add key-value pairs at the top of your markdown file, followed by ---:
title: My Page Title
layout: custom.ts
author: John Doe
---
# Page Content
Your markdown content here...
Available Properties
layout
Override the default layout template for this page.
layout: my-layout.ts
The path is relative to the layout/ directory.
Custom Properties
Add any custom properties you need:
title: Getting Started
description: Learn how to get started with bok
author: Your Name
date: 2024-01-15
tags: tutorial, beginner
draft: true
---
Access these in templates via page.params:
export default function(site, page, pages) {
return `
<article>
<h1>${page.params.title}</h1>
<p>By ${page.params.author}</p>
${page.htmlContent}
</article>
`;
}
Parser Details
The front matter parser:
- Reads lines until it hits
---
- Splits each line on the first
:
- Trims whitespace from keys and values
- All values are strings
key: value with spaces
another: value: with: colons
---
Results in:
{
key: "value with spaces",
another: "value: with: colons"
}
Examples
Blog Post
title: My First Post
date: 2024-01-15
author: Jane Doe
tags: announcement, news
---
# Welcome to My Blog
This is my first post...
Custom Layout
layout: landing.ts
---
# Welcome
This page uses a custom landing page layout.
Documentation Page
title: API Reference
description: Complete API documentation
order: 5
---
# API Reference
...
No Front Matter
Front matter is optional. If omitted, the page uses:
- Default layout from config
- Empty
params object
# Just Content
This page has no front matter.
themes.md
Themes
Themes control the look and feel of your bok site. They provide layouts, styles, and default configuration.
Built-in Themes
basic
A minimal theme with just the essentials.
export default {
extends: "basic",
};
Features:
- Simple HTML structure
- No styling
- Good starting point for custom themes
book
A documentation theme inspired by mdBook and GitBook.
export default {
extends: "book",
};
Features:
- Sidebar navigation
- Previous/next page links
- Right-side table of contents
- Responsive design
- Syntax highlighting
See Book Theme for details.
Theme Structure
A theme consists of:
my-theme/
├── config.ts # Theme configuration
├── layout/ # Template files
│ ├── index.ts # Default layout
│ └── base.ts # Base HTML wrapper
├── assets/ # Static assets
│ ├── css/
│ ├── js/
│ ├── img/
│ └── fonts/
└── content/ # Example content (for init)
├── toc.md
└── index.md
Extending vs Creating
Extend (Recommended)
Use the theme's layouts and assets, customize only what you need:
export default {
extends: "book",
params: {
title: "My Docs",
},
};
Create
Copy theme files for full customization:
bok init --mode create --theme book
This copies all theme files to your project.
Custom Themes
Create your own theme by:
- Creating a theme directory with the structure above
- Writing a
config.ts with theme defaults
- Creating layout templates
- Adding assets
Reference your custom theme:
export default {
extends: "/path/to/my-theme/config.ts",
};
See Creating Themes for a complete guide.
book-theme.md
Book Theme
The book theme provides a complete documentation experience similar to mdBook or GitBook.
Features
- Sidebar navigation - Collapsible table of contents
- Page navigation - Previous/next page arrows
- Right TOC - On-page heading navigation with scroll spy
- Responsive - Works on mobile and desktop
- Syntax highlighting - Via Prism.js
- Toggle sidebar - Hide/show for more reading space
Configuration
Basic Setup
export default {
extends: "book",
params: {
title: "My Documentation",
author: "Your Name",
description: "Project documentation",
},
};
Right Table of Contents
Configure the on-page heading navigation:
params: {
rightToc: {
enabled: true, // Show/hide right TOC
title: "On this page", // Section title
minHeadings: 2, // Minimum headings to show TOC
levels: [2, 3], // Which heading levels to include
},
}
Layout Structure
The book theme uses two layout files:
base.ts
The HTML wrapper with:
- Document head (meta, CSS, fonts)
- Script includes
- Body wrapper
index.ts
The page structure:
- Sidebar with TOC
- Main content area
- Previous/next navigation
- Right-side TOC
Styling
CSS Files
| File |
Purpose |
reset.css |
CSS reset |
variables.css |
CSS custom properties |
base.css |
Core layout styles |
typography.css |
Text and heading styles |
list.css |
List styling |
prism.css |
Code highlighting |
CSS Variables
Customize colors by overriding CSS variables:
:root {
--bg: #ffffff;
--fg: #333333;
--sidebar-bg: #f5f5f5;
--link-color: #0066cc;
}
JavaScript
index.js
Handles:
- Sidebar toggle
- Keyboard navigation (left/right arrows)
- Session storage for sidebar state
prism.min.js
Syntax highlighting for code blocks.
Keyboard Shortcuts
| Key |
Action |
← |
Previous page |
→ |
Next page |
s |
Toggle sidebar |
File Discovery
The book theme uses TOC mode by default:
files: {
type: "toc",
file: "toc.md",
}
Your content/toc.md defines the sidebar structure.
Example Site
See the examples/book/ directory for a complete example site using this theme.
creating-themes.md
Creating Themes
Build custom themes for your bok sites.
Theme Structure
my-theme/
├── config.ts # Required: theme configuration
├── layout/ # Required: template files
│ └── index.ts # Required: default layout
├── assets/ # Optional: static files
└── content/ # Optional: example content
Theme Config
Create config.ts:
export default {
name: "my-theme",
// File discovery mode
files: {
type: "walk", // or "toc", "glob"
},
// Path defaults (relative to this file)
paths: {
assets: "assets",
layout: "layout",
defaultLayout: "index.ts",
},
// Dev server defaults
serve: {
reload: true,
port: 5000,
wsPort: 5001,
},
// Lifecycle hooks
hooks: {
async beforeSite(site, pages, opts) {},
async afterSite(site, pages, opts) {},
async beforePage(site, page, i, pages, opts) {},
async afterPage(site, page, i, pages, opts) {},
},
// Default params (users can override)
params: {
title: "My Theme",
},
};
Layout Templates
Layouts are TypeScript files that export a function:
// layout/index.ts
export default function(site, page, pages) {
return `
<!DOCTYPE html>
<html>
<head>
<title>${page.params.title || site.params.title}</title>
<link rel="stylesheet" href="${site.rootUrl}/assets/css/style.css">
</head>
<body>
<main>
${page.htmlContent}
</main>
</body>
</html>
`;
}
Template Parameters
site
The site configuration object:
site.rootUrl // URL prefix
site.params // Site params from config
site.paths // Directory paths
site.uglyURLs // URL style boolean
page
The current page being rendered:
page.name // Filename
page.path // Full file path
page.link // URL path (e.g., "/getting-started")
page.params // Front matter data
page.htmlContent // Rendered markdown HTML
page.tokens // markdown-it AST tokens
page.toc // Left sidebar HTML (if using TOC mode)
page.rightToc // Right-side TOC HTML
page.prevPage // Previous page URL
page.nextPage // Next page URL
pages
Array of all pages in the site.
Composable Templates
Split templates into reusable parts:
// layout/base.ts
export default function({ title, rootUrl }, content) {
return `
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
<link rel="stylesheet" href="${rootUrl}/assets/css/style.css">
</head>
<body>
${content}
</body>
</html>
`;
}
// layout/index.ts
import base from "./base.ts";
export default function(site, page, pages) {
return base(
{ title: page.params.title, rootUrl: site.rootUrl },
`<main>${page.htmlContent}</main>`
);
}
Assets
Place static files in assets/:
assets/
├── css/
│ └── style.css
├── js/
│ └── main.js
├── img/
│ └── logo.svg
└── fonts/
└── ...
Reference in templates:
`<link rel="stylesheet" href="${site.rootUrl}/assets/css/style.css">`
`<script src="${site.rootUrl}/assets/js/main.js"></script>`
Hooks
Use hooks for advanced processing:
hooks: {
// Generate sitemap after build
async afterSite(site, pages, opts) {
const sitemap = pages
.map(p => `<url><loc>https://example.com${p.link}</loc></url>`)
.join("\n");
await Bun.write(
`${site.paths.output}/sitemap.xml`,
`<?xml version="1.0"?><urlset>${sitemap}</urlset>`
);
},
// Add build timestamp to each page
async beforePage(site, page, i, pages, opts) {
page.params.buildTime = new Date().toISOString();
},
}
Using Your Theme
Reference by path:
export default {
extends: "/path/to/my-theme/config.ts",
params: {
title: "My Site",
},
};
Or initialize with it:
bok init --mode extend --theme path --theme-path /path/to/my-theme/config.ts
contributing.md
Contributing
Contributions to bok are welcome!
Development Setup
# Clone the repository
git clone https://github.com/alajmo/bok
cd bok
# Install dependencies
bun install
# Run the example site
make serve-debug
Project Structure
bok/
├── mod.ts # CLI entry point
├── deps.ts # Centralized dependencies
├── src/
│ ├── mod.ts # Main exports
│ ├── core/
│ │ ├── build.ts # Build pipeline
│ │ ├── config.ts # Configuration loading
│ │ ├── init.ts # Site initialization
│ │ ├── server.ts # HTTP server
│ │ ├── watch.ts # File watching
│ │ ├── ws-server.ts # WebSocket server
│ │ └── utils.ts # Utilities
│ └── plugins/
│ └── toc.ts # TOC parser
├── themes/
│ ├── basic/ # Minimal theme
│ └── book/ # Documentation theme
└── examples/
└── book/ # Example site
Key Files
deps.ts
All external dependencies are centralized here. This makes it easy to swap implementations.
src/core/build.ts
The main build pipeline:
- Clean output directory
- Discover pages (walk/glob/toc)
- Process each page (front matter → markdown → template)
- Copy assets
src/core/config.ts
Configuration loading and merging:
- Read user config
- Apply defaults
- Merge with theme config
- Validate paths
src/plugins/toc.ts
Custom lexer and parser for the TOC format:
TocReader - Character stream
TocLexer - Tokenizer
TocParser - AST builder
TocRender - HTML generator
Making Changes
- Fork the repository
- Create a feature branch
- Make your changes
- Test with the example site
- Submit a pull request
Testing
Run the example site to test changes:
# Development server
make serve-debug
# Build only
make build
Code Style
- TypeScript for all source files
- Use template literals for HTML generation
- Keep dependencies minimal
- Prefer explicit over implicit
Reporting Issues
Open an issue on GitHub with:
- bok version
- Bun version
- Operating system
- Steps to reproduce
- Expected vs actual behavior