Topics and Catalogue
Help content is organised as Topic values managed by a Catalog. Topics can be created programmatically, loaded from Markdown files with YAML frontmatter, or provided by the built-in defaults.
Topic Structure
type Topic struct {
ID string // URL-safe slug
Title string // Human-readable title
Path string // Source file path (if parsed from file)
Content string // Markdown body
Sections []Section // Parsed headings
Tags []string // Searchable tags
Related []string // Related topic IDs
Order int // Sort priority
}
YAML Frontmatter
Markdown files can include YAML frontmatter delimited by ---:
---
title: Deployment Guide
tags:
- ops
- docker
- production
related:
- configuration
- monitoring
order: 10
---
# Deployment Guide
How to deploy the application to production...
The frontmatter is parsed into a Frontmatter struct:
type Frontmatter struct {
Title string `yaml:"title"`
Tags []string `yaml:"tags"`
Related []string `yaml:"related"`
Order int `yaml:"order"`
}
If title is provided in the frontmatter, it takes precedence. Otherwise the parser falls back to the first # heading in the document.
Parsing Markdown Files
ParseTopic processes a Markdown file into a structured topic:
content, _ := os.ReadFile("docs/deployment.md")
topic, err := help.ParseTopic("docs/deployment.md", content)
if err != nil {
log.Fatal(err)
}
fmt.Printf("ID: %s\n", topic.ID) // "deployment-guide"
fmt.Printf("Title: %s\n", topic.Title) // "Deployment Guide"
fmt.Printf("Sections: %d\n", len(topic.Sections))
fmt.Printf("Tags: %v\n", topic.Tags) // ["ops", "docker", "production"]
The parsing pipeline:
- Extract YAML frontmatter (if present)
- Generate an ID from the title using
GenerateID - Parse headings into
Sectionvalues withExtractSections - Fall back to the first H1 heading if no frontmatter title
Section Extraction
ExtractSections parses Markdown headings (# through ######) into structured sections:
sections := help.ExtractSections(markdownBody)
for _, s := range sections {
fmt.Printf("L%d [line %d] %s: %s...\n",
s.Level, s.Line, s.Title, s.Content[:50])
}
Each section captures:
- ID: URL-safe slug of the heading text
- Title: The heading text
- Level: 1-6 corresponding to
#through###### - Line: 1-indexed line number in the content
- Content: All text between this heading and the next
ID Generation
GenerateID converts titles to URL-safe slugs:
help.GenerateID("Getting Started") // "getting-started"
help.GenerateID("API Reference") // "api-reference"
help.GenerateID("FAQ & Tips!") // "faq-tips"
Rules: lowercase, letters/digits kept, spaces/hyphens/underscores become hyphens, other characters dropped, trailing hyphens trimmed.
Catalogue Management
The Catalog holds topics in a map and maintains a search index:
cat := help.DefaultCatalog()
// Add topics
cat.Add(&help.Topic{
ID: "troubleshooting",
Title: "Troubleshooting",
Content: "# Troubleshooting\n\nCommon issues and solutions...",
Tags: []string{"debug", "errors"},
})
// Retrieve by ID
topic, err := cat.Get("getting-started")
if err != nil {
fmt.Println("not found")
}
// List all
for _, t := range cat.List() {
fmt.Printf(" %s\n", t.Title)
}
Default Topics
DefaultCatalog() includes two built-in topics:
- getting-started -- Overview of common commands and next steps
- config -- Environment variables and config file locations
These serve as a baseline and can be supplemented with Add.
See also: Home | Search-Engine