Sol SSG
Experimental: Sol SSG is under active development. APIs may change.
Sol SSG is Luna's static site generator for documentation and content sites.
Features
Markdown-based - Write content in Markdown with frontmatter
Syntax Highlighting - Code blocks highlighted with Shiki
i18n Support - Multi-language documentation
Auto Sidebar - Automatic navigation generation from directory structure
Islands Architecture - Embed interactive Luna/MoonBit components
Dynamic Routes - Generate pages from
_slug_patterns with staticParamsISR - Incremental Static Regeneration with Stale-While-Revalidate
HMR - Fast development with Hot Module Replacement
Guides
Dynamic Routes - Generate static pages from parameters
Islands - Embed interactive components in static pages
Deploy - Deploy to various platforms
ISR - Incremental Static Regeneration for dynamic content
Components - Reusable UI components (Header, Footer, Blog, Themes)
Quick Start
1. Create a New Project
npx @luna_ui/sol new my-docs --ssg
cd my-docs
npm install
2. Start Development Server
npm run dev
Open http://localhost:3355 to preview your documentation with HMR.
3. Build for Production
npm run build
Static files are generated in dist-docs/.
CLI Reference
Sol SSG is now part of the unified sol CLI. When your project has an sol.config.json or sol.config.json with ssg section, Sol automatically runs in SSG mode.
# Create a new SSG project
sol new <name> --ssg [options]
-t, --title <text> Site title (default: project name)
-h, --help Show help
# Start development server with HMR
sol dev [options]
-p, --port <port> Port to listen on (default: 3355)
-c, --config <path> Config file path
-h, --help Show help
# Build static site
sol build [options]
-c, --config <path> Config file path (default: sol.config.json or sol.config.json)
-o, --output <dir> Output directory (overrides config)
-h, --help Show help
# Lint SSG content
sol lint [options]
-c, --config <path> Config file path
# Show help
sol --help
# Show version
sol --version
Configuration
Create sol.config.json in your project root:
{
"docs": "docs",
"output": "dist",
"title": "My Docs",
"base": "/",
"sidebar": "auto"
}
Basic Options
| Option | Type | Default | Description |
|---|---|---|---|
docs | string | "docs" | Source directory |
output | string | "dist" | Output directory |
title | string | "Documentation" | Site title |
base | string | "/" | Base URL path |
trailingSlash | boolean | true | Use trailing slashes in URLs |
exclude | string[] | [] | Directories to exclude |
Navigation
{
"nav": [
{ "text": "Guide", "link": "/guide/" },
{ "text": "API", "link": "/api/" },
{ "text": "GitHub", "link": "https://github.com/..." }
]
}
Sidebar
Auto Mode
{
"sidebar": "auto"
}
Generates sidebar from directory structure automatically.
Manual Mode
{
"sidebar": [
{
"text": "Introduction",
"items": [
{ "text": "Getting Started", "link": "/getting-started/" },
{ "text": "Installation", "link": "/installation/" }
]
},
{
"text": "Guide",
"collapsed": true,
"items": [
{ "text": "Basics", "link": "/guide/basics" },
{ "text": "Advanced", "link": "/guide/advanced" }
]
}
]
}
Internationalization (i18n)
{
"i18n": {
"defaultLocale": "en",
"locales": [
{ "code": "en", "label": "English", "path": "" },
{ "code": "ja", "label": "Japanese", "path": "ja" }
]
}
}
Directory structure for i18n:
docs/
โโโ index.md # English (default)
โโโ guide/
โ โโโ basics.md
โโโ ja/ # Japanese
โโโ index.md
โโโ guide/
โโโ basics.md
Theme
{
"theme": {
"primaryColor": "#6366f1",
"logo": "/logo.svg",
"footer": {
"message": "Released under the MIT License.",
"copyright": "Copyright 2024 Your Name"
},
"socialLinks": [
{ "icon": "github", "link": "https://github.com/..." }
]
}
}
OGP (Open Graph Protocol)
{
"ogp": {
"siteUrl": "https://example.com",
"image": "/og-image.png",
"twitterHandle": "@yourhandle",
"twitterCard": "summary_large_image"
}
}
Content Structure
docs/
โโโ index.md # Home page (/)
โโโ 00_introduction/ # /introduction/
โ โโโ index.md
โโโ 01_guide/ # /guide/
โ โโโ index.md
โ โโโ 01_basics.md # /guide/basics/
โ โโโ 02_advanced.md # /guide/advanced/
โโโ components/ # Web Components
โโโ my-counter.js
Numeric prefixes (00_, 01_) control ordering but are stripped from URLs.
Markdown Features
Frontmatter
---
title: Page Title
description: Page description for SEO
layout: doc
sidebar: true
---
# Content here
Frontmatter Options
| Option | Type | Default | Description |
|---|---|---|---|
title | string | - | Page title |
description | string | - | SEO description |
layout | string | "doc" | Layout type: doc, home |
sidebar | boolean | true | Show sidebar |
image | string | - | OGP image (overrides site default) |
revalidate | int | - | ISR TTL in seconds (details) |
Code Blocks
```typescript
const greeting = "Hello, World!";
```
```moonbit
fn main {
println("Hello, World!")
}
```
Web Components
Embed interactive Web Components in your static pages.
Creating a Component
Place components in docs/components/:
// docs/components/my-counter.js
export function hydrate(element, state, name) {
let count = parseInt(element.getAttribute('initial') || '0', 10);
const render = () => {
element.innerHTML = `<button>${count}</button>`;
element.querySelector("button").onclick = () => {
count++;
render();
};
};
render();
}
Using in Markdown
<my-counter initial="5" luna:trigger="load"></my-counter>
Trigger Types
| Trigger | Description |
|---|---|
load | Hydrate immediately on page load (default) |
idle | Hydrate when browser is idle |
visible | Hydrate when element enters viewport |
media | Hydrate when media query matches |
none | Manual hydration only |
Full Configuration Example
{
"docs": "docs",
"output": "dist",
"title": "My Documentation",
"base": "/",
"trailingSlash": true,
"exclude": ["internal", "drafts"],
"i18n": {
"defaultLocale": "en",
"locales": [
{ "code": "en", "label": "English", "path": "" },
{ "code": "ja", "label": "Japanese", "path": "ja" }
]
},
"nav": [
{ "text": "Guide", "link": "/guide/" },
{ "text": "API", "link": "/api/" }
],
"sidebar": "auto",
"theme": {
"primaryColor": "#6366f1",
"logo": "/logo.svg",
"footer": {
"message": "Released under the MIT License.",
"copyright": "Copyright 2024"
},
"socialLinks": [
{ "icon": "github", "link": "https://github.com/..." }
]
},
"ogp": {
"siteUrl": "https://example.com",
"image": "/og-image.png"
}
}