Files
herolib/lib/web/site/readme.md
2025-12-01 05:27:29 +01:00

329 lines
8.7 KiB
Markdown

# Site Module
The Site module provides a structured way to define website configurations, navigation menus, pages, and sections using HeroScript. It's designed to work with static site generators like Docusaurus.
## Purpose
The Site module allows you to:
- Define website structure and configuration in a declarative way using HeroScript
- Organize pages into sections/categories
- Configure navigation menus and footers
- Manage page metadata (title, description, slug, etc.)
- Support multiple content collections
- Define build and publish destinations
## Quick Start
```v
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
import incubaid.herolib.develop.gittools
import incubaid.herolib.web.site
import incubaid.herolib.core.playcmds
// Clone or use existing repository with HeroScript files
mysitepath := gittools.path(
git_url: 'https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech'
git_pull: true
)!
// Process all HeroScript files in the path
playcmds.run(heroscript_path: mysitepath.path)!
// Get the configured site
mut mysite := site.get(name: 'tfgrid_tech')!
println(mysite)
```
## HeroScript Syntax
### Basic Configuration
```heroscript
!!site.config
name: "my_site"
title: "My Documentation Site"
description: "Comprehensive documentation"
tagline: "Your awesome documentation"
favicon: "img/favicon.png"
image: "img/site-image.png"
copyright: "© 2024 My Organization"
url: "https://docs.example.com"
base_url: "/"
```
### Navigation Menu
```heroscript
!!site.navbar
title: "My Site"
logo_alt: "Site Logo"
logo_src: "img/logo.svg"
logo_src_dark: "img/logo-dark.svg"
!!site.navbar_item
label: "Documentation"
to: "docs/intro"
position: "left"
!!site.navbar_item
label: "GitHub"
href: "https://github.com/myorg/myrepo"
position: "right"
```
### Footer Configuration
```heroscript
!!site.footer
style: "dark"
!!site.footer_item
title: "Docs"
label: "Introduction"
to: "intro"
!!site.footer_item
title: "Docs"
label: "Getting Started"
href: "https://docs.example.com/getting-started"
!!site.footer_item
title: "Community"
label: "Discord"
href: "https://discord.gg/example"
```
## Page Organization
### Example 1: Simple Pages Without Categories
When you don't need categories, pages are added sequentially. The collection only needs to be specified once, then it's reused for subsequent pages.
```heroscript
!!site.page src: "mycelium_tech:introduction"
description: "Introduction to ThreeFold Technology"
slug: "/"
!!site.page src: "vision"
description: "Our Vision for the Future Internet"
!!site.page src: "what"
description: "What ThreeFold is Building"
!!site.page src: "presentation"
description: "ThreeFold Technology Presentation"
!!site.page src: "status"
description: "Current Development Status"
```
**Key Points:**
- First page specifies collection as `tech:introduction` (collection:page_name format)
- Subsequent pages only need the page name (e.g., `vision`) - the `tech` collection is reused
- If `title` is not specified, it will be extracted from the markdown file itself
- Pages are ordered by their appearance in the HeroScript file
- `slug` can be used to customize the URL path (e.g., `"/"` for homepage)
### Example 2: Pages with Categories
Categories (sections) help organize pages into logical groups with their own navigation structure.
```heroscript
!!site.page_category
name: "first_principle_thinking"
label: "First Principle Thinking"
!!site.page src: "first_principle_thinking:hardware_badly_used"
description: "Hardware is not used properly, why it is important to understand hardware"
!!site.page src: "internet_risk"
description: "Internet risk, how to mitigate it, and why it is important"
!!site.page src: "onion_analogy"
description: "Compare onion with a computer, layers of abstraction"
```
**Key Points:**
- `!!site.page_category` creates a new section/category
- `name` is the internal identifier (snake_case)
- `label` is the display name (automatically derived from `name` if not specified)
- Category name is converted to title case: `first_principle_thinking` → "First Principle Thinking"
- Once a category is defined, all subsequent pages belong to it until a new category is declared
- Collection persistence works the same: specify once (e.g., `first_principle_thinking:hardware_badly_used`), then reuse
### Example 3: Advanced Page Configuration
```heroscript
!!site.page_category
name: "components"
label: "System Components"
position: 100
!!site.page src: "mycelium_tech:mycelium"
title: "Mycelium Network"
description: "Peer-to-peer overlay network"
slug: "mycelium-network"
position: 1
draft: false
hide_title: false
!!site.page src: "fungistor"
title: "Fungistor Storage"
description: "Distributed storage system"
position: 2
```
**Available Page Parameters:**
- `src`: Source reference as `collection:page_name` (required for first page in collection)
- `title`: Page title (optional, extracted from markdown if not provided)
- `description`: Page description for metadata
- `slug`: Custom URL slug
- `position`: Manual ordering (auto-incremented if not specified)
- `draft`: Mark page as draft (default: false)
- `hide_title`: Hide the page title in rendering (default: false)
- `path`: Custom path for the page (defaults to category name)
- `category`: Override the current category for this page
## File Organization
HeroScript files should be organized with numeric prefixes to control execution order:
```
docs/
├── 0_config.heroscript # Site configuration
├── 1_menu.heroscript # Navigation and footer
├── 2_intro_pages.heroscript # Introduction pages
├── 3_tech_pages.heroscript # Technical documentation
└── 4_api_pages.heroscript # API reference
```
**Important:** Files are processed in alphabetical order, so use numeric prefixes (0_, 1_, 2_, etc.) to ensure correct execution sequence.
## Import External Content
```heroscript
!!site.import
url: "https://github.com/example/external-docs"
dest: "external"
replace: "PROJECT_NAME:My Project,VERSION:1.0.0"
visible: true
```
## Publish Destinations
```heroscript
!!site.publish
path: "/var/www/html/docs"
ssh_name: "production_server"
!!site.publish_dev
path: "/tmp/docs-preview"
```
## Factory Methods
### Create or Get a Site
```v
import incubaid.herolib.web.site
// Create a new site
mut mysite := site.new(name: 'my_docs')!
// Get an existing site
mut mysite := site.get(name: 'my_docs')!
// Get default site
mut mysite := site.default()!
// Check if site exists
if site.exists(name: 'my_docs') {
println('Site exists')
}
// List all sites
sites := site.list()
println(sites)
```
### Using with PlayBook
```v
import incubaid.herolib.core.playbook
import incubaid.herolib.web.site
// Create playbook from path
mut plbook := playbook.new(path: '/path/to/heroscripts')!
// Process site configuration
site.play(mut plbook)!
// Access the configured site
mut mysite := site.get(name: 'my_site')!
```
## Data Structures
### Site
```v
pub struct Site {
pub mut:
pages []Page
sections []Section
siteconfig SiteConfig
}
```
### Page
```v
pub struct Page {
pub mut:
name string // Page identifier
title string // Display title
description string // Page description
draft bool // Draft status
position int // Sort order
hide_title bool // Hide title in rendering
src string // Source as collection:page_name
path string // URL path (without page name)
section_name string // Category/section name
title_nr int // Title numbering level
slug string // Custom URL slug
}
```
### Section
```v
pub struct Section {
pub mut:
name string // Internal identifier
position int // Sort order
path string // URL path
label string // Display name
}
```
## Best Practices
1. **File Naming**: Use numeric prefixes (0_, 1_, 2_) to control execution order
2. **Collection Reuse**: Specify collection once, then reuse for subsequent pages
3. **Category Organization**: Group related pages under categories for better navigation
4. **Title Extraction**: Let titles be extracted from markdown files when possible
5. **Position Management**: Use automatic positioning unless you need specific ordering
6. **Description**: Always provide descriptions for better SEO and navigation
7. **Draft Status**: Use `draft: true` for work-in-progress pages
## Complete Example
See `examples/web/site/site_example.vsh` for a complete working example.
For a real-world example, check: <https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech>