This commit is contained in:
2025-10-14 11:41:16 +04:00
parent 25eb9bbb86
commit 081aafa8c6
3 changed files with 886 additions and 276 deletions

View File

@@ -1,20 +1,99 @@
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
import os
import incubaid.herolib.develop.gittools
import incubaid.herolib.web.site
import incubaid.herolib.core.playcmds
// Example 1: Load site configuration from a Git repository
println('=== Example 1: Loading from Git Repository ===')
url := 'https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech'
mysitepath := gittools.path(
// git_pull: true
// git_reset: true
git_url: url
// git_root: '/tmp/code'
git_pull: true
// git_reset: true // Uncomment to reset to latest
)!
// Process all HeroScript files in the repository
playcmds.run(heroscript_path: mysitepath.path)!
// Get the configured site
mut mysite := site.get(name: 'tfgrid_tech')!
println(mysite)
println('Site loaded: ${mysite.siteconfig.name}')
println('Title: ${mysite.siteconfig.title}')
println('Pages: ${mysite.pages.len}')
println('Sections: ${mysite.sections.len}')
println('')
// Example 2: Inspect site structure
println('=== Example 2: Site Structure ===')
println('Sections:')
for section in mysite.sections {
println(' - ${section.label} (${section.name})')
}
println('')
println('Pages (first 5):')
for i, page in mysite.pages {
if i >= 5 {
break
}
println(' - ${page.name}: ${page.description}')
println(' Section: ${page.section_name}, Position: ${page.position}')
}
println('')
// Example 3: Access menu configuration
println('=== Example 3: Navigation Menu ===')
println('Menu Title: ${mysite.siteconfig.menu.title}')
println('Menu Items:')
for item in mysite.siteconfig.menu.items {
if item.href != '' {
println(' - ${item.label} -> ${item.href} (external)')
} else {
println(' - ${item.label} -> ${item.to} (internal)')
}
}
println('')
// Example 4: Access footer configuration
println('=== Example 4: Footer Configuration ===')
println('Footer Style: ${mysite.siteconfig.footer.style}')
println('Footer Links:')
for link in mysite.siteconfig.footer.links {
println(' ${link.title}:')
for item in link.items {
if item.href != '' {
println(' - ${item.label} -> ${item.href}')
} else {
println(' - ${item.label} -> ${item.to}')
}
}
}
println('')
// Example 5: List all configured sites
println('=== Example 5: All Configured Sites ===')
all_sites := site.list()
println('Total sites: ${all_sites.len}')
for site_name in all_sites {
println(' - ${site_name}')
}
println('')
// Example 6: Check if a site exists
println('=== Example 6: Site Existence Check ===')
if site.exists(name: 'tfgrid_tech') {
println('Site "tfgrid_tech" exists')
} else {
println('Site "tfgrid_tech" does not exist')
}
if site.exists(name: 'nonexistent_site') {
println('Site "nonexistent_site" exists')
} else {
println('Site "nonexistent_site" does not exist')
}
println('')
println('=== Example Complete ===')

View File

@@ -0,0 +1,536 @@
# AI Instructions for Site Module HeroScript
This document provides comprehensive instructions for AI agents working with the Site module's HeroScript format.
## HeroScript Format Overview
HeroScript is a declarative configuration language with the following characteristics:
### Basic Syntax
```heroscript
!!actor.action
param1: "value1"
param2: "value2"
multiline_param: "
This is a multiline value.
It can span multiple lines.
"
arg1 arg2 // Arguments without keys
```
**Key Rules:**
1. Actions start with `!!` followed by `actor.action` format
2. Parameters are indented and use `key: "value"` or `key: value` format
3. Values with spaces must be quoted
4. Multiline values are supported with quotes
5. Arguments without keys are space-separated
6. Comments start with `//`
## Site Module Actions
### 1. Site Configuration (`!!site.config`)
**Purpose:** Define the main site configuration including title, description, and metadata.
**Required Parameters:**
- `name`: Site identifier (will be normalized to snake_case)
**Optional Parameters:**
- `title`: Site title (default: "Documentation Site")
- `description`: Site description
- `tagline`: Site tagline
- `favicon`: Path to favicon (default: "img/favicon.png")
- `image`: Default site image (default: "img/tf_graph.png")
- `copyright`: Copyright text
- `url`: Main site URL
- `base_url`: Base URL path (default: "/")
- `url_home`: Home page path
**Example:**
```heroscript
!!site.config
name: "my_documentation"
title: "My Documentation Site"
description: "Comprehensive technical documentation"
tagline: "Learn everything you need"
url: "https://docs.example.com"
base_url: "/"
```
**AI Guidelines:**
- Always include `name` parameter
- Use descriptive titles and descriptions
- Ensure URLs are properly formatted with protocol
### 2. Metadata Configuration (`!!site.config_meta`)
**Purpose:** Override specific metadata for SEO purposes.
**Optional Parameters:**
- `title`: SEO-specific title (overrides site.config title for meta tags)
- `image`: SEO-specific image (overrides site.config image for og:image)
- `description`: SEO-specific description
**Example:**
```heroscript
!!site.config_meta
title: "My Docs - Complete Guide"
image: "img/social-preview.png"
description: "The ultimate guide to using our platform"
```
**AI Guidelines:**
- Use only when SEO metadata needs to differ from main config
- Keep titles concise for social media sharing
- Use high-quality images for social previews
### 3. Navigation Bar (`!!site.navbar` or `!!site.menu`)
**Purpose:** Configure the main navigation bar.
**Optional Parameters:**
- `title`: Navigation title (defaults to site.config title)
- `logo_alt`: Logo alt text
- `logo_src`: Logo image path
- `logo_src_dark`: Dark mode logo path
**Example:**
```heroscript
!!site.navbar
title: "My Site"
logo_alt: "My Site Logo"
logo_src: "img/logo.svg"
logo_src_dark: "img/logo-dark.svg"
```
**AI Guidelines:**
- Use `!!site.navbar` for modern syntax (preferred)
- `!!site.menu` is supported for backward compatibility
- Provide both light and dark logos when possible
### 4. Navigation Items (`!!site.navbar_item` or `!!site.menu_item`)
**Purpose:** Add items to the navigation bar.
**Required Parameters (one of):**
- `to`: Internal link path
- `href`: External URL
**Optional Parameters:**
- `label`: Display text (required in practice)
- `position`: "left" or "right" (default: "right")
**Example:**
```heroscript
!!site.navbar_item
label: "Documentation"
to: "docs/intro"
position: "left"
!!site.navbar_item
label: "GitHub"
href: "https://github.com/myorg/repo"
position: "right"
```
**AI Guidelines:**
- Use `to` for internal navigation
- Use `href` for external links
- Position important items on the left, secondary items on the right
### 5. Footer Configuration (`!!site.footer`)
**Purpose:** Configure footer styling.
**Optional Parameters:**
- `style`: "dark" or "light" (default: "dark")
**Example:**
```heroscript
!!site.footer
style: "dark"
```
### 6. Footer Items (`!!site.footer_item`)
**Purpose:** Add links to the footer, grouped by title.
**Required Parameters:**
- `title`: Group title (items with same title are grouped together)
- `label`: Link text
**Required Parameters (one of):**
- `to`: Internal link path
- `href`: External URL
**Example:**
```heroscript
!!site.footer_item
title: "Docs"
label: "Introduction"
to: "intro"
!!site.footer_item
title: "Docs"
label: "API Reference"
to: "api"
!!site.footer_item
title: "Community"
label: "Discord"
href: "https://discord.gg/example"
```
**AI Guidelines:**
- Group related links under the same title
- Use consistent title names across related items
- Provide both internal and external links as appropriate
### 7. Page Categories (`!!site.page_category`)
**Purpose:** Create a section/category to organize pages.
**Required Parameters:**
- `name`: Category identifier (snake_case)
**Optional Parameters:**
- `label`: Display name (auto-generated from name if not provided)
- `position`: Manual sort order (auto-incremented if not specified)
- `path`: URL path segment (defaults to normalized label)
**Example:**
```heroscript
!!site.page_category
name: "getting_started"
label: "Getting Started"
position: 100
!!site.page_category
name: "advanced_topics"
label: "Advanced Topics"
```
**AI Guidelines:**
- Use descriptive snake_case names
- Let label be auto-generated when possible (name_fix converts to Title Case)
- Categories persist for all subsequent pages until a new category is declared
- Position values should leave gaps (100, 200, 300) for future insertions
### 8. Pages (`!!site.page`)
**Purpose:** Define individual pages in the site.
**Required Parameters:**
- `src`: Source reference as `collection:page_name` (required for first page in a collection)
**Optional Parameters:**
- `name`: Page identifier (extracted from src if not provided)
- `title`: Page title (extracted from markdown if not provided)
- `description`: Page description for metadata
- `slug`: Custom URL slug
- `position`: Manual sort order (auto-incremented if not specified)
- `draft`: Mark as draft (default: false)
- `hide_title`: Hide title in rendering (default: false)
- `path`: Custom path (defaults to current category name)
- `category`: Override current category
- `title_nr`: Title numbering level
**Example:**
```heroscript
!!site.page src: "docs:introduction"
description: "Introduction to the platform"
slug: "/"
!!site.page src: "quickstart"
description: "Get started in 5 minutes"
!!site.page src: "installation"
title: "Installation Guide"
description: "How to install and configure"
position: 10
```
**AI Guidelines:**
- **Collection Persistence:** Specify collection once (e.g., `docs:introduction`), then subsequent pages only need page name (e.g., `quickstart`)
- **Category Persistence:** Pages belong to the most recently declared category
- **Title Extraction:** Prefer extracting titles from markdown files
- **Position Management:** Use automatic positioning unless specific order is required
- **Description Required:** Always provide descriptions for SEO
- **Slug Usage:** Use slug for special pages like homepage (`slug: "/"`)
### 9. Import External Content (`!!site.import`)
**Purpose:** Import content from external sources.
**Optional Parameters:**
- `name`: Import identifier
- `url`: Git URL or HTTP URL
- `path`: Local file system path
- `dest`: Destination path in site
- `replace`: Comma-separated key:value pairs for variable replacement
- `visible`: Whether imported content is visible (default: true)
**Example:**
```heroscript
!!site.import
url: "https://github.com/example/docs"
dest: "external"
replace: "VERSION:1.0.0,PROJECT:MyProject"
visible: true
```
**AI Guidelines:**
- Use for shared documentation across multiple sites
- Replace variables using `${VARIABLE}` syntax in source content
- Set `visible: false` for imported templates or partials
### 10. Publish Destinations (`!!site.publish` and `!!site.publish_dev`)
**Purpose:** Define where to publish the built site.
**Optional Parameters:**
- `path`: File system path or URL
- `ssh_name`: SSH connection name for remote deployment
**Example:**
```heroscript
!!site.publish
path: "/var/www/html/docs"
ssh_name: "production_server"
!!site.publish_dev
path: "/tmp/docs-preview"
```
**AI Guidelines:**
- Use `!!site.publish` for production deployments
- Use `!!site.publish_dev` for development/preview deployments
- Can specify multiple destinations
## File Organization Best Practices
### Naming Convention
Use numeric prefixes to control execution order:
```
0_config.heroscript # Site configuration
1_navigation.heroscript # Menu and footer
2_intro.heroscript # Introduction pages
3_guides.heroscript # User guides
4_reference.heroscript # API reference
```
**AI Guidelines:**
- Always use numeric prefixes (0_, 1_, 2_, etc.)
- Leave gaps in numbering (0, 10, 20) for future insertions
- Group related configurations in the same file
- Process order matters: config → navigation → pages
### Execution Order Rules
1. **Configuration First:** `!!site.config` must be processed before other actions
2. **Categories Before Pages:** Declare `!!site.page_category` before pages in that category
3. **Collection Persistence:** First page in a collection must specify `collection:page_name`
4. **Category Persistence:** Pages inherit the most recent category declaration
## Common Patterns
### Pattern 1: Simple Documentation Site
```heroscript
!!site.config
name: "simple_docs"
title: "Simple Documentation"
!!site.navbar
title: "Simple Docs"
!!site.page src: "docs:index"
description: "Welcome page"
slug: "/"
!!site.page src: "getting-started"
description: "Getting started guide"
!!site.page src: "api"
description: "API reference"
```
### Pattern 2: Multi-Section Documentation
```heroscript
!!site.config
name: "multi_section_docs"
title: "Complete Documentation"
!!site.page_category
name: "introduction"
label: "Introduction"
!!site.page src: "docs:welcome"
description: "Welcome to our documentation"
!!site.page src: "overview"
description: "Platform overview"
!!site.page_category
name: "tutorials"
label: "Tutorials"
!!site.page src: "tutorial_basics"
description: "Basic tutorial"
!!site.page src: "tutorial_advanced"
description: "Advanced tutorial"
```
### Pattern 3: Complex Site with External Links
```heroscript
!!site.config
name: "complex_site"
title: "Complex Documentation Site"
url: "https://docs.example.com"
!!site.navbar
title: "My Platform"
logo_src: "img/logo.svg"
!!site.navbar_item
label: "Docs"
to: "docs/intro"
position: "left"
!!site.navbar_item
label: "API"
to: "api"
position: "left"
!!site.navbar_item
label: "GitHub"
href: "https://github.com/example/repo"
position: "right"
!!site.footer
style: "dark"
!!site.footer_item
title: "Documentation"
label: "Getting Started"
to: "docs/intro"
!!site.footer_item
title: "Community"
label: "Discord"
href: "https://discord.gg/example"
!!site.page_category
name: "getting_started"
!!site.page src: "docs:introduction"
description: "Introduction to the platform"
slug: "/"
!!site.page src: "installation"
description: "Installation guide"
```
## Error Prevention
### Common Mistakes to Avoid
1. **Missing Collection on First Page:**
```heroscript
# WRONG - no collection specified
!!site.page src: "introduction"
# CORRECT
!!site.page src: "docs:introduction"
```
2. **Category Without Name:**
```heroscript
# WRONG - missing name
!!site.page_category
label: "Getting Started"
# CORRECT
!!site.page_category
name: "getting_started"
label: "Getting Started"
```
3. **Missing Description:**
```heroscript
# WRONG - no description
!!site.page src: "docs:intro"
# CORRECT
!!site.page src: "docs:intro"
description: "Introduction to the platform"
```
4. **Incorrect File Ordering:**
```
# WRONG - pages before config
pages.heroscript
config.heroscript
# CORRECT - config first
0_config.heroscript
1_pages.heroscript
```
## Validation Checklist
When generating HeroScript for the Site module, verify:
- [ ] `!!site.config` includes `name` parameter
- [ ] All pages have `description` parameter
- [ ] First page in each collection specifies `collection:page_name`
- [ ] Categories are declared before their pages
- [ ] Files use numeric prefixes for ordering
- [ ] Navigation items have either `to` or `href`
- [ ] Footer items are grouped by `title`
- [ ] External URLs include protocol (https://)
- [ ] Paths don't have trailing slashes unless intentional
- [ ] Draft pages are marked with `draft: true`
## Integration with V Code
When working with the Site module in V code:
```v
import incubaid.herolib.web.site
import incubaid.herolib.core.playbook
// Process HeroScript files
mut plbook := playbook.new(path: '/path/to/heroscripts')!
site.play(mut plbook)!
// Access configured site
mut mysite := site.get(name: 'my_site')!
// Iterate through pages
for page in mysite.pages {
println('Page: ${page.name} - ${page.description}')
}
// Iterate through sections
for section in mysite.sections {
println('Section: ${section.label}')
}
```
## Summary
The Site module's HeroScript format provides a declarative way to configure websites with:
- Clear separation of concerns (config, navigation, content)
- Automatic ordering and organization
- Collection and category persistence for reduced repetition
- Flexible metadata and SEO configuration
- Support for both internal and external content
Always follow the execution order rules, use numeric file prefixes, and provide complete metadata for best results.

View File

@@ -1,329 +1,324 @@
# Site Module
This module has the structure of a website, which menus to use, which pages, etc.
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.
example see https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech
## Purpose
## example how to get started
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
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
import os
import incubaid.herolib.develop.gittools
import incubaid.herolib.web.site
import incubaid.herolib.core.playcmds
url := "https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech"
// Clone or use existing repository with HeroScript files
mysitepath := gittools.path(
// git_pull: true
// git_reset: true
git_url: url
git_root: '/tmp/code'
git_url: 'https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech'
git_pull: true
)!
playcmds.run(heroscript_path:mysitepath.path)!
// Process all HeroScript files in the path
playcmds.run(heroscript_path: mysitepath.path)!
mut mysite:=site.get(name:"tfgrid_tech")!
// Get the configured site
mut mysite := site.get(name: 'tfgrid_tech')!
println(mysite)
```
## config heroscript
## HeroScript Syntax
```yaml
### Basic Configuration
```heroscript
!!site.config
name:"ThreeFold DePIN Tech"
description:"ThreeFold is laying the foundation for a geo aware Web 4, the next generation of the Internet."
tagline:"Geo Aware Internet Platform"
favicon:"img/favicon.png"
image:"img/tf_graph.png"
copyright:"ThreeFold"
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: "/"
```
!!site.menu
title:"ThreeFold DePIN Tech"
logo_alt:"ThreeFold Logo"
logo_src:"img/logo.svg"
logo_src_dark:"img/new_logo_tft.png"
### Navigation Menu
!!site.menu_item
label:"ThreeFold.io"
href:"https://threefold.io"
position:"right"
```heroscript
!!site.navbar
title: "My Site"
logo_alt: "Site Logo"
logo_src: "img/logo.svg"
logo_src_dark: "img/logo-dark.svg"
!!site.menu_item
label:"Mycelium Network"
href:"https://mycelium.threefold.io/"
position:"right"
!!site.navbar_item
label: "Documentation"
to: "docs/intro"
position: "left"
!!site.menu_item
label:"AI Box"
href:"https://aibox.threefold.io/"
position:"right"
!!site.navbar_item
label: "GitHub"
href: "https://github.com/myorg/myrepo"
position: "right"
```
### Footer Configuration
```heroscript
!!site.footer
style:"dark"
style: "dark"
!!site.footer_item
title:"Docs"
label:"Introduction"
href:"https://docs.threefold.io/docs/introduction"
title: "Docs"
label: "Introduction"
to: "intro"
!!site.footer_item
title:"Docs"
label:"Litepaper"
href:"https://docs.threefold.io/docs/litepaper/"
title: "Docs"
label: "Getting Started"
href: "https://docs.example.com/getting-started"
!!site.footer_item
title:"Features"
label:"Become a Farmer"
href:"https://docs.threefold.io/docs/category/become-a-farmer"
!!site.footer_item
title:"Features"
label:"Components"
href:"https://docs.threefold.io/docs/category/components"
!!site.footer_item
title:"Web"
label:"ThreeFold.io"
href:"https://threefold.io"
!!site.footer_item
title:"Web"
label:"Dashboard"
href:"https://dashboard.grid.tf"
!!site.collections
url:"https://github.com/example/external-docs"
replace:"PROJECT_NAME:My Project, VERSION:1.0.0"
title: "Community"
label: "Discord"
href: "https://discord.gg/example"
```
## site structure
## Page Organization
```yaml
!!site.page name:intro
description:"ThreeFold is laying the foundation for a geo aware Web 4, the next generation of the Internet."
### Example 1: Simple Pages Without Categories
#next is example where we use all properties, folder is where the page is located, prio is the order of the page, if not used the filled in from order in which we parse this config file
!!site.page name:mycelium draft:true folder:"/specs/components" prio:4
content:"the page content itself, only for small pages"
title:"Mycelium as Title"
description:"..."
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.
!!site.page name:fungistor folder:"/specs/components" prio:1
src:"mycollection:mycelium.md"
title:"fungistor as Title"
description:"...."
```heroscript
!!site.page src: "tech:introduction"
description: "Introduction to ThreeFold Technology"
slug: "/"
!!site.page name:fungistor folder:"/specs/components" prio:1
src:"mycollection:mycelium" //can be without .md
title:"fungistor as Title"
description:"..."
!!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"
```
## factory
**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: "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
mut mysite := site.new()!
// 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)
```
## how to use with plbook
### Using with PlayBook
```v
import incubaid.herolib.core.playbook
import incubaid.herolib.web.site
// path string
// text string
// git_url string
// git_pull bool
// git_branch string
// git_reset bool
// session ?&base.Session is optional
mut plbook := playbook.new( "....")!
// 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')!
```
## example json
## Data Structures
```json
{
"name": "depin",
"title": "Documentation Site",
"description": "ThreeFold is laying the foundation for a geo aware Web 4, the next generation of the Internet.",
"tagline": "Geo Aware Internet Platform",
"favicon": "img/favicon.png",
"image": "img/tf_graph.png",
"copyright": "ThreeFold",
"footer": {
"style": "dark",
"links": [
{
"title": "Docs",
"items": [
{
"label": "Introduction",
"to": "intro",
"href": ""
},
{
"label": "Litepaper",
"to": "",
"href": "https://docs.threefold.io/docs/litepaper/"
},
{
"label": "Roadmap",
"to": "",
"href": "https://docs.threefold.io/docs/roadmap"
},
{
"label": "Manual",
"to": "",
"href": "https://manual.grid.tf/"
}
]
},
{
"title": "Features",
"items": [
{
"label": "Become a Farmer",
"to": "",
"href": "https://docs.threefold.io/docs/category/become-a-farmer"
},
{
"label": "Components",
"to": "",
"href": "https://docs.threefold.io/docs/category/components"
},
{
"label": "Technology",
"to": "",
"href": "https://threefold.info/tech/"
},
{
"label": "Tokenomics",
"to": "",
"href": "https://docs.threefold.io/docs/tokens/tokenomics"
}
]
},
{
"title": "Web",
"items": [
{
"label": "ThreeFold.io",
"to": "",
"href": "https://threefold.io"
},
{
"label": "Dashboard",
"to": "",
"href": "https://dashboard.grid.tf"
},
{
"label": "GitHub",
"to": "",
"href": "https://github.com/threefoldtech/home"
},
{
"label": "Mycelium Network",
"to": "",
"href": "https://mycelium.threefold.io/"
},
{
"label": "AI Box",
"to": "",
"href": "https://www2.aibox.threefold.io/"
}
]
}
]
},
"menu": {
"title": "ThreeFold DePIN Tech",
"items": [
{
"href": "https://threefold.io",
"to": "",
"label": "ThreeFold.io",
"position": "right"
},
{
"href": "https://mycelium.threefold.io/",
"to": "",
"label": "Mycelium Network",
"position": "right"
},
{
"href": "https://aibox.threefold.io/",
"to": "",
"label": "AI Box",
"position": "right"
}
]
},
"import_collections": [
{
"url": "https://github.com/example/external-docs",
"path": "",
"dest": "",
"replace": {
"PROJECT_NAME": "My Project",
"VERSION": "1.0.0"
},
"visible": false
}
],
"pages": [
{
"name": "intro",
"content": "",
"title": "",
"description": "ThreeFold is laying the foundation for a geo aware Web 4, the next generation of the Internet.",
"draft": false,
"folder": "",
"prio": 0,
"src": ""
},
{
"name": "mycelium",
"content": "the page content itself, only for small pages",
"title": "Mycelium as Title",
"description": "...",
"draft": true,
"folder": "/specs/components",
"prio": 4,
"src": ""
},
{
"name": "fungistor",
"content": "",
"title": "fungistor as Title",
"description": "....",
"draft": false,
"folder": "/specs/components",
"prio": 1,
"src": "mycollection:mycelium.md"
},
{
"name": "fungistor",
"content": "",
"title": "fungistor as Title",
"description": "...",
"draft": false,
"folder": "/specs/components",
"prio": 1,
"src": "mycollection:mycelium"
}
]
### 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