Skip to main content

Overview

The RenderService wraps the HTML template renderer and manages the asset map for cache-busted CSS/JS files. It provides methods for rendering different page types. Source: builder/services/interfaces.go:65-76

Interface

type RenderService interface {
    RenderPage(path string, data models.PageData)
    RenderIndex(path string, data models.PageData)
    Render404(path string, data models.PageData)
    RenderGraph(path string, data models.PageData)
    RegisterFile(path string)
    SetAssets(assets map[string]string)
    GetAssets() map[string]string
    GetRenderedFiles() map[string]bool
    ClearRenderedFiles()
}

Rendering Methods

RenderPage

Renders a standard content page (blog post or documentation page).
path
string
required
Destination file path (e.g., public/getting-started.html)
data
models.PageData
required
Page data including content, metadata, and template variables
Title
string
Page title
Content
template.HTML
Rendered HTML content
TOC
[]models.TOCEntry
Table of contents entries
SiteTree
[]*models.TreeNode
Sidebar navigation tree
PrevPage
*models.PostMetadata
Previous page in sequence
NextPage
*models.PostMetadata
Next page in sequence

RenderIndex

Renders the homepage or version landing page.
path
string
required
Destination file path (e.g., public/index.html)
data
models.PageData
required
Page data with posts list and pagination
Posts
[]models.PostMetadata
Posts to display on this page
PinnedPosts
[]models.PostMetadata
Posts pinned to top
Page
int
Current page number (1-indexed)
TotalPages
int
Total number of pages

Render404

Renders the 404 error page.
path
string
required
Destination file path (always public/404.html)
data
models.PageData
required
Minimal page data for error page

RenderGraph

Renders the knowledge graph visualization page.
path
string
required
Destination file path (e.g., public/graph.html)
data
models.PageData
required
Page data for graph page

Asset Management

SetAssets

Sets the asset map populated by esbuild (maps original paths to hashed paths).
assets
map[string]string
required
Map of original path to hashed path
{
    "/static/css/layout.css": "/static/css/layout-a1b2c3d4.css",
    "/static/js/theme.js":    "/static/js/theme-e5f6g7h8.js",
}

GetAssets

Retrieves the current asset map.
assets
map[string]string
Asset map for template use

File Tracking

RegisterFile

Registers a file as rendered/copied (used for VFS sync).
path
string
required
File path that was written

GetRenderedFiles

Returns all files registered during this build.
files
map[string]bool
Set of file paths that were rendered/copied

ClearRenderedFiles

Clears the rendered files map (called after VFS sync).

Implementation

The default implementation is renderServiceImpl:
type renderServiceImpl struct {
    rnd    *renderer.Renderer
    logger *slog.Logger
}

func NewRenderService(rnd *renderer.Renderer, logger *slog.Logger) RenderService
Source: builder/services/render_service.go:10-20

Usage Example

From builder/services/post_service.go:488-501:
// Render a post page
renderQueue[idx] = RenderContext{
    DestPath: destPath,
    Version:  version,
    Data: models.PageData{
        Title:          post.Title,
        Description:    post.Description,
        Content:        template.HTML(htmlContent),
        Meta:           metaData,
        BaseURL:        s.cfg.BaseURL,
        TabTitle:       post.Title + " | " + s.cfg.Title,
        Permalink:      post.Link,
        Image:          imagePath,
        TOC:            toc,
        Config:         s.cfg,
        CurrentVersion: version,
        IsOutdated:     s.isOutdatedVersion(version),
        Versions:       s.cfg.GetVersionsMetadata(version, cleanHtmlRelPath),
    },
}

// Later, with neighbors injected:
s.renderer.RenderPage(task.DestPath, task.Data)
From builder/services/asset_service.go:261:
// After esbuild completes, populate asset map
assets, err := utils.BuildAssetsEsbuild(
    s.sourceFs, s.destFs,
    s.cfg.StaticDir,
    destStaticDir,
    s.cfg.CompressImages,
    s.renderer.RegisterFile,
    s.cfg.CacheDir+"/assets",
    force,
)

s.renderer.SetAssets(assets)
From builder/run/build.go:307-309:
// Sync VFS to disk using registered files
if err := utils.SyncVFS(b.DestFs, b.cfg.OutputDir, b.renderService.GetRenderedFiles()); err != nil {
    b.logger.Error("Failed to sync VFS to disk", "error", err)
}
b.renderService.ClearRenderedFiles()

Template Access

Templates access the asset map via the Assets field:
<!-- In layout.html -->
<link rel="stylesheet" href="{{ index .Assets "/static/css/layout.css" }}">
<script src="{{ index .Assets "/static/js/theme.js" }}"></script>
The index function looks up the hashed path:
// Input:  /static/css/layout.css
// Output: /static/css/layout-a1b2c3d4.css

PageData Structure

The models.PageData struct passed to rendering methods:
type PageData struct {
    // Content
    Title       string
    Description string
    Content     template.HTML
    Meta        map[string]interface{}
    
    // Navigation
    SiteTree  []*TreeNode
    TOC       []TOCEntry
    PrevPage  *PostMetadata
    NextPage  *PostMetadata
    
    // Pagination
    Posts       []PostMetadata
    PinnedPosts []PostMetadata
    Page        int
    TotalPages  int
    
    // Assets
    Assets  map[string]string
    
    // Config
    BaseURL      string
    BuildVersion string
    TabTitle     string
    Permalink    string
    Image        string
    Config       *config.Config
    
    // Versioning
    CurrentVersion string
    IsOutdated     bool
    Versions       []VersionMetadata
}

Rendering Lifecycle

1

Asset Build

AssetService populates Assets map via SetAssets()
2

Post Rendering

PostService calls RenderPage() with populated PageData
3

Global Pages

Builder calls RenderIndex(), Render404(), RenderGraph()
4

VFS Sync

GetRenderedFiles() provides list for disk sync
5

Cleanup

ClearRenderedFiles() resets for next build

Build docs developers (and LLMs) love