s3gen

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2026 License: MIT Imports: 41 Imported by: 0

README

s3gen

A simple, flexible, rule-based static site generator for Go developers.

S3Gen is a simple static site generator written in Go. It lets you do some frequent things very easily:

  1. Compile your posts and content written in markdown (.md) into html files to be served statically.
  2. Use Go templating and a rich set of "builtin" functions for you to use.
  3. Use custom templates for different pages in your website/blog.
  4. Generates an RSS feed so your site can be consumed via a feed reader
  5. Generates a sitemap useable by search engines
  6. Library mode to programatically serve static sites inside another binary

Key Features

  • Rule-based build system: Process files exactly how you want.
  • Four-phase build pipeline: Discover → Transform → Generate → Finalize
  • Powerful Go-based templating: with includes, custom functions, and more.
  • Parametric Routes: Generate multiple pages from a single template (e.g., for tags or categories).
  • Co-located Assets: Place images next to your markdown files.
  • Transform Rules: SCSS, TypeScript, CSS minification, and more.
  • Generators: Sitemap, RSS feed, and custom site-wide artifacts.
  • Live Reloading for rapid development.
  • Extensible: Add your own content types and build rules.
  • Library-first: Use it as a standalone CLI or embed it in your own Go application.

Examples

My Personal Blog - Source

Getting Started

With a Go compiler
go install github.com/panyam/s3gen@latest
Precompiled Binary

TBD

Setup and Usage

This library is mainly for developers who are interested in hosting a blog but want control and customization easily. There are very few conventions needed for this.

A typical s3gen project has a content directory for the site's content, a templates directory for the Go templates, and a static directory for assets like CSS, JavaScript, and images. A main.go file configures the s3gen.Site object.

A minimal main.go showing how to configure and run a s3gen.Site:

package main

import (
	"log"
	"os"

	s3 "github.com/panyam/s3gen"
)

var Site = s3.Site{
	OutputDir:   "./public",
	ContentRoot: "./content",
	PathPrefix:  "/",
	TemplateFolders: []string{
		"./templates",
	},
	StaticFolders: []string{
		"/static/", "static",
	},
	DefaultBaseTemplate: s3.BaseTemplate{
		Name: "base.html",
	},
	// Co-located asset patterns
	AssetPatterns: []string{
		"*.png", "*.jpg", "*.jpeg", "*.gif", "*.svg",
	},
}

// Generators for site-wide artifacts
var sitemapGen = &s3.SitemapGenerator{
	BaseURL:    "https://example.com",
	OutputPath: "sitemap.xml",
}

var rssGen = &s3.RSSGenerator{
	Title:       "My Blog",
	Description: "Latest posts",
	BaseURL:     "https://example.com",
	OutputPath:  "feed.xml",
}

func main() {
	// Register generators
	sitemapGen.Register(&Site)
	rssGen.Register(&Site)

	if os.Getenv("APP_ENV") != "production" {
		log.Println("Starting watcher...")
		Site.Watch()
		select {}
	} else {
		Site.Rebuild(nil)
	}
}

A minimal content/index.html with some front matter:

---
title: "Home"
---

<h1>Welcome to my website!</h1>

A minimal templates/base.html to render the content:

<!DOCTYPE html>
<html>
<head>
    <title>{{.FrontMatter.title}}</title>
</head>
<body>
     {{ BytesToString .Content | HTML }}
</body>
</html>

To run the build:

go run main.go

Documentation

For detailed documentation, see the /docs directory:

Document Description
01-introduction.md Philosophy and use cases
02-core-concepts.md Site, Resources, Rules, Build Process
03-templating-guide.md Template functions and syntax
04-creating-content.md Front matter, parametric pages, JSON data
05-advanced-usage.md Custom rules, programmatic use
06-phase-based-architecture.md The four-phase build pipeline
07-co-located-assets.md Images and files next to content
08-transform-rules.md CSS minification, SCSS, TypeScript
09-generators-and-hooks.md Sitemap, RSS, custom generators

Architecture Overview

s3gen uses a four-phase build pipeline:

Discover → Transform → Generate → Finalize
    │          │           │          │
    │          │           │          └─ Sitemap, RSS, search index
    │          │           └─ MD→HTML, HTML→HTML, parametric expansion
    │          └─ SCSS→CSS, image optimization, bundling
    └─ Find all resources, identify types, load metadata
Built-in Rules

Transform Phase:

  • CSSMinifier - Minify CSS files
  • ExternalTransform - Run any command-line tool
  • CopyRule - Copy static files
  • NewSCSSTransform() - SCSS compilation
  • NewTypeScriptTransform() - TypeScript compilation

Generate Phase:

  • MDToHtml - Markdown to HTML
  • HTMLToHtml - HTML template processing
  • ParametricPages - Generate multiple pages from one template

Finalize Phase:

  • SitemapGenerator - Generate sitemap.xml
  • RSSGenerator - Generate RSS feed

Contributing & License

Contributions are welcome! Please open an issue or submit a pull request.

This project is licensed under the MIT License.

Documentation

Overview

Package s3gen is a simple, flexible, rule-based static site generator for Go developers.

Index

Constants

View Source
const (
	// ResourceStatePending is the initial state of a resource before it is loaded.
	ResourceStatePending = iota

	// ResourceStateLoaded is the state of a resource that has been successfully loaded.
	ResourceStateLoaded

	// ResourceStateDeleted is the state of a resource that has been deleted.
	ResourceStateDeleted

	// ResourceStateNotFound is the state of a resource that could not be found.
	ResourceStateNotFound

	// ResourceStateFailed is the state of a resource that failed to load.
	ResourceStateFailed
)

Variables

View Source
var DefaultFormats []*frontmatter.Format = []*frontmatter.Format{

	&frontmatter.Format{"---", "---", yaml.Unmarshal, false, false},
	&frontmatter.Format{"---yaml", "---", yaml.Unmarshal, false, false},

	&frontmatter.Format{"+++", "+++", toml.Unmarshal, false, false},
	&frontmatter.Format{"---toml", "---", toml.Unmarshal, false, false},

	&frontmatter.Format{";;;", ";;;", json.Unmarshal, false, false},
	&frontmatter.Format{"---json", "---", json.Unmarshal, false, false},
}

Functions

func ContentHashShort added in v0.1.0

func ContentHashShort(res *Resource) string

ContentHashShort returns the first 8 characters of the content hash. This is typically used for generating unique asset directory names.

func GetAllTags added in v0.0.18

func GetAllTags(resources []*Resource) (tagCount map[string]int)

GetAllTags returns a map of all tags and the number of pages that use them.

func GetAssetURL added in v0.1.0

func GetAssetURL(site *Site, res *Resource, filename string) string

GetAssetURL returns the URL for an asset relative to the current resource. This can be used in templates to reference co-located assets.

Types

type AssetAction added in v0.1.0

type AssetAction int

AssetAction specifies how to handle a co-located asset.

const (
	// AssetCopy copies the asset to the destination as-is.
	AssetCopy AssetAction = iota

	// AssetProcess runs the asset through transform rules.
	AssetProcess

	// AssetSkip ignores the asset.
	AssetSkip
)

type AssetAwareRule added in v0.1.0

type AssetAwareRule interface {
	Rule

	// HandleAssets is called with co-located assets for a resource.
	// Returns mappings describing how each asset should be processed.
	HandleAssets(site *Site, res *Resource, assets []*Resource) ([]AssetMapping, error)
}

AssetAwareRule is an optional interface for rules that handle co-located assets. When a content file has assets (images, data files in the same directory), rules implementing this interface can specify how those assets should be handled.

type AssetMapping added in v0.1.0

type AssetMapping struct {
	Source *Resource
	Dest   string // Path relative to output directory
	Action AssetAction
}

AssetMapping describes how to handle a single co-located asset.

type BaseTemplate added in v0.0.18

type BaseTemplate struct {
	// Name is the name of the template file to use as the root.
	Name string

	// Entry is the name of the template to use as the entry point within the
	// template file. This is useful when a single file contains multiple
	// template definitions.
	Entry string

	// Params is a map of parameters to pass to the template.
	Params map[any]any
}

BaseTemplate defines the data needed to render a page, including the template name and any parameters it requires.

type BaseToHtmlRule added in v0.0.18

type BaseToHtmlRule struct {
	// Extensions is a list of file extensions that this rule can handle.
	Extensions []string
}

BaseToHtmlRule is a base rule that can be embedded in other rules that convert a resource to HTML.

func (*BaseToHtmlRule) HandleAssets added in v0.1.2

func (h *BaseToHtmlRule) HandleAssets(site *Site, res *Resource, assets []*Resource) ([]AssetMapping, error)

HandleAssets implements AssetAwareRule for co-located asset handling. Assets are copied to the same directory as the output HTML file. For parametric pages, assets go to a shared folder with content-hash deduplication.

func (*BaseToHtmlRule) LoadResource added in v0.0.27

func (h *BaseToHtmlRule) LoadResource(site *Site, r *Resource) error

LoadResource loads a resource and sets its basic properties, such as whether it's an index page or a parametric page.

func (*BaseToHtmlRule) TargetsFor added in v0.0.18

func (m *BaseToHtmlRule) TargetsFor(s *Site, r *Resource) (siblings []*Resource, targets []*Resource)

TargetsFor determines the output target for a resource that is being converted to HTML.

type BuildContext added in v0.1.0

type BuildContext struct {
	Site         *Site
	CurrentPhase BuildPhase

	// All resources discovered
	Resources []*Resource

	// Resources created in each phase
	CreatedInPhase map[BuildPhase][]*Resource

	// All targets generated (for Finalize phase access)
	GeneratedTargets []*Resource

	// Errors accumulated during build (allows continuing on non-fatal errors)
	Errors []error
	// contains filtered or unexported fields
}

BuildContext holds state that persists across phases during a single build.

func (*BuildContext) AddError added in v0.1.0

func (ctx *BuildContext) AddError(err error)

AddError adds an error to the build context.

func (*BuildContext) AddTarget added in v0.1.0

func (ctx *BuildContext) AddTarget(target *Resource)

AddTarget adds a generated target to the context.

type BuildPhase added in v0.1.0

type BuildPhase int

BuildPhase represents a stage in the build pipeline. Phases execute in order: Discover → Transform → Generate → Finalize

const (
	// PhaseDiscover finds all resources, identifies types, loads metadata
	PhaseDiscover BuildPhase = iota

	// PhaseTransform handles asset transformations (SCSS→CSS, image optimization, etc.)
	PhaseTransform

	// PhaseGenerate produces final outputs (MD→HTML, HTML→HTML, parametric expansion)
	PhaseGenerate

	// PhaseFinalize runs after all content is generated (sitemap, RSS, search index)
	PhaseFinalize
)

func (BuildPhase) String added in v0.1.0

func (p BuildPhase) String() string

type CSSMinifier added in v0.1.1

type CSSMinifier struct {
	// Command is the external minifier command (e.g., "lightningcss", "csso", "cleancss")
	// If empty, uses a simple built-in minifier
	Command string

	// Args are additional arguments to pass to the command
	// The input file will be appended as the last argument
	Args []string

	// OutputSuffix is appended before .css extension (e.g., ".min" produces file.min.css)
	// If empty, the file is minified in-place (same name)
	OutputSuffix string

	// SourcePatterns are glob patterns to match CSS files (default: ["**/*.css"])
	SourcePatterns []string

	// ExcludePatterns are glob patterns to exclude (e.g., ["**/*.min.css"])
	ExcludePatterns []string
}

CSSMinifier minifies CSS files during the Transform phase. It can use external tools (like lightningcss, csso, or clean-css) or a simple built-in minifier.

func (*CSSMinifier) DependsOn added in v0.1.1

func (m *CSSMinifier) DependsOn() []string

func (*CSSMinifier) Phase added in v0.1.1

func (m *CSSMinifier) Phase() BuildPhase

func (*CSSMinifier) Produces added in v0.1.1

func (m *CSSMinifier) Produces() []string

func (*CSSMinifier) Run added in v0.1.1

func (m *CSSMinifier) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

func (*CSSMinifier) TargetsFor added in v0.1.1

func (m *CSSMinifier) TargetsFor(site *Site, res *Resource) ([]*Resource, []*Resource)

type CopyRule added in v0.1.1

type CopyRule struct {
	// Patterns are glob patterns to match files
	Patterns []string

	// ExcludePatterns are glob patterns to exclude
	ExcludePatterns []string

	// FlattenDir if true, copies all files to a single directory
	FlattenDir string
}

CopyRule copies files matching patterns from content to output. Useful for static assets that don't need transformation.

func (*CopyRule) DependsOn added in v0.1.1

func (c *CopyRule) DependsOn() []string

func (*CopyRule) Phase added in v0.1.1

func (c *CopyRule) Phase() BuildPhase

func (*CopyRule) Produces added in v0.1.1

func (c *CopyRule) Produces() []string

func (*CopyRule) Run added in v0.1.1

func (c *CopyRule) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

func (*CopyRule) TargetsFor added in v0.1.1

func (c *CopyRule) TargetsFor(site *Site, res *Resource) ([]*Resource, []*Resource)

type DefaultAssetHandler added in v0.1.0

type DefaultAssetHandler struct{}

DefaultAssetHandler provides default asset handling for content resources. It copies assets to the same directory as the output HTML, or to a shared assets directory for parametric pages.

func (*DefaultAssetHandler) HandleAssets added in v0.1.0

func (h *DefaultAssetHandler) HandleAssets(site *Site, res *Resource, assets []*Resource) ([]AssetMapping, error)

HandleAssets implements AssetAwareRule for default asset handling.

type DefaultResourceBase added in v0.0.18

type DefaultResourceBase struct {
	// Slug is the URL-friendly slug for the page.
	Slug string

	// Title is the title of the page.
	Title string

	// Link is the permalink to the page.
	Link string

	// Summary is a short summary of the page.
	Summary string

	// CreatedAt is the creation timestamp of the page.
	CreatedAt time.Time
	// UpdatedAt is the last modification timestamp of the page.
	UpdatedAt time.Time

	// IsDraft is true if the page is a draft.
	IsDraft bool

	// CanonicalUrl is the canonical URL for the page.
	CanonicalUrl string

	// Tags is a list of tags for the page.
	Tags []string

	// Res is the resource that this base is associated with.
	Res *Resource

	// State is the current state of the resource.
	State int

	// Error holds any error that occurred while processing the resource.
	Error error
}

DefaultResourceBase is the default implementation of the ResourceBase interface.

func (*DefaultResourceBase) LoadFrom added in v0.0.18

func (page *DefaultResourceBase) LoadFrom(res *Resource) error

LoadFrom loads the data for the DefaultResourceBase from a resource's front matter.

type Document added in v0.0.18

type Document struct {
	// Loaded is true if the document has been loaded and parsed.
	Loaded bool

	// LoadedAt is the time the document was loaded.
	LoadedAt time.Time

	// Root is the root of the parsed document tree.
	Root any

	// Metadata is a map for storing extra metadata about the document,
	// such as a table of contents.
	Metadata map[string]any
}

Document represents the parsed content of a resource (e.g., an AST).

func (*Document) SetMetadata added in v0.0.18

func (d *Document) SetMetadata(k string, v any)

SetMetadata sets a metadata key-value pair on the document.

type ExternalTransform added in v0.1.1

type ExternalTransform struct {
	// Name is a descriptive name for this transform (for logging)
	Name string

	// Command is the command to run
	Command string

	// Args are arguments to the command.
	// Special placeholders:
	//   {input}  - replaced with input file path
	//   {output} - replaced with output file path
	// If neither placeholder is used, input is piped via stdin and output read from stdout.
	Args []string

	// SourceExtension is the file extension to match (e.g., ".scss", ".ts")
	SourceExtension string

	// TargetExtension is the output file extension (e.g., ".css", ".js")
	TargetExtension string

	// SourcePatterns are additional glob patterns to match (optional)
	SourcePatterns []string

	// ExcludePatterns are glob patterns to exclude
	ExcludePatterns []string

	// WorkingDir is the working directory for the command (default: site root)
	WorkingDir string
}

ExternalTransform runs an external command to transform files. This is a generic transform rule that can be used for any command-line tool.

func NewSCSSTransform added in v0.1.1

func NewSCSSTransform() *ExternalTransform

NewSCSSTransform creates an ExternalTransform for SCSS to CSS compilation. Requires `sass` or `dart-sass` to be installed.

func NewTailwindTransform added in v0.1.1

func NewTailwindTransform(inputFile, outputFile string) *ExternalTransform

NewTailwindTransform creates an ExternalTransform for Tailwind CSS. Requires `tailwindcss` CLI to be installed.

func NewTypeScriptTransform added in v0.1.1

func NewTypeScriptTransform() *ExternalTransform

NewTypeScriptTransform creates an ExternalTransform for TypeScript compilation. Requires `tsc` or `esbuild` to be installed.

func (*ExternalTransform) DependsOn added in v0.1.1

func (t *ExternalTransform) DependsOn() []string

func (*ExternalTransform) Phase added in v0.1.1

func (t *ExternalTransform) Phase() BuildPhase

func (*ExternalTransform) Produces added in v0.1.1

func (t *ExternalTransform) Produces() []string

func (*ExternalTransform) Run added in v0.1.1

func (t *ExternalTransform) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

func (*ExternalTransform) TargetsFor added in v0.1.1

func (t *ExternalTransform) TargetsFor(site *Site, res *Resource) ([]*Resource, []*Resource)

type FrontMatter

type FrontMatter struct {
	// Loaded is true if the front matter has been loaded and parsed.
	Loaded bool

	// Data is a map containing the parsed front matter data.
	Data map[string]any

	// Length is the length of the front matter in bytes.
	Length int64
}

FrontMatter represents the parsed front matter of a resource.

type HTMLToHtml added in v0.0.18

type HTMLToHtml struct {
	BaseToHtmlRule
}

A rule that converts <ContentRoot>/a/b/c.html -> <OutputDir>/a/b/c/index.html by applying the root template defined in c.html as is

func (*HTMLToHtml) DependsOn added in v0.1.0

func (h *HTMLToHtml) DependsOn() []string

DependsOn returns nil - HTMLToHtml doesn't depend on other rules.

func (*HTMLToHtml) LoadResourceTemplate added in v0.0.19

func (h *HTMLToHtml) LoadResourceTemplate(site *Site, r *Resource) ([]byte, error)

func (*HTMLToHtml) Phase added in v0.1.0

func (h *HTMLToHtml) Phase() BuildPhase

Phase returns PhaseGenerate - HTML template conversion happens in the generate phase.

func (*HTMLToHtml) Produces added in v0.1.0

func (h *HTMLToHtml) Produces() []string

Produces returns the patterns of files this rule generates.

func (*HTMLToHtml) Run added in v0.0.18

func (m *HTMLToHtml) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

Generate the output resource for a related set of "input" targets

func (*HTMLToHtml) TargetsFor added in v0.0.18

func (h *HTMLToHtml) TargetsFor(s *Site, r *Resource) (siblings []*Resource, targets []*Resource)

type HookRegistry added in v0.1.0

type HookRegistry struct {
	// contains filtered or unexported fields
}

HookRegistry manages lightweight hooks for build observation. This is simpler than a full EventBus - just callbacks organized by phase.

func NewHookRegistry added in v0.1.0

func NewHookRegistry() *HookRegistry

NewHookRegistry creates a new hook registry.

func (*HookRegistry) OnPhaseEnd added in v0.1.0

func (h *HookRegistry) OnPhaseEnd(phase BuildPhase, fn func(*BuildContext))

OnPhaseEnd registers a callback to run when a phase ends.

func (*HookRegistry) OnPhaseStart added in v0.1.0

func (h *HookRegistry) OnPhaseStart(phase BuildPhase, fn func(*BuildContext))

OnPhaseStart registers a callback to run when a phase starts.

func (*HookRegistry) OnResourceProcessed added in v0.1.0

func (h *HookRegistry) OnResourceProcessed(fn func(*BuildContext, *Resource, []*Resource))

OnResourceProcessed registers a callback to run after each resource is processed. The callback receives the source resource and all targets it generated.

type LegacyRuleAdapter added in v0.1.0

type LegacyRuleAdapter struct {
	Wrapped Rule
}

LegacyRuleAdapter wraps a Rule that doesn't implement PhaseRule, allowing it to work in the phase-based pipeline.

func (*LegacyRuleAdapter) DependsOn added in v0.1.0

func (l *LegacyRuleAdapter) DependsOn() []string

DependsOn returns nil - legacy rules don't declare dependencies.

func (*LegacyRuleAdapter) Phase added in v0.1.0

func (l *LegacyRuleAdapter) Phase() BuildPhase

Phase returns PhaseGenerate - legacy rules run in the generate phase.

func (*LegacyRuleAdapter) Produces added in v0.1.0

func (l *LegacyRuleAdapter) Produces() []string

Produces returns nil - legacy rules don't declare what they produce.

func (*LegacyRuleAdapter) Run added in v0.1.0

func (l *LegacyRuleAdapter) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

Run delegates to the wrapped rule.

func (*LegacyRuleAdapter) TargetsFor added in v0.1.0

func (l *LegacyRuleAdapter) TargetsFor(site *Site, res *Resource) ([]*Resource, []*Resource)

TargetsFor delegates to the wrapped rule.

type MDToHtml added in v0.0.18

type MDToHtml struct {
	BaseToHtmlRule
}

A rule that converts <ContentRoot>/a/b/c.md -> <OutputDir>/a/b/c/index.html by Applying the root template defined in c.md as is

func (*MDToHtml) DependsOn added in v0.1.0

func (m *MDToHtml) DependsOn() []string

DependsOn returns nil - MDToHtml doesn't depend on other rules.

func (*MDToHtml) LoadResourceTemplate added in v0.0.18

func (m *MDToHtml) LoadResourceTemplate(site *Site, r *Resource) ([]byte, error)

func (*MDToHtml) MD added in v0.0.18

func (m *MDToHtml) MD() (md goldmark.Markdown, tocTransformer *TOCTransformer)

func (*MDToHtml) Phase added in v0.1.0

func (m *MDToHtml) Phase() BuildPhase

Phase returns PhaseGenerate - markdown conversion happens in the generate phase.

func (*MDToHtml) Produces added in v0.1.0

func (m *MDToHtml) Produces() []string

Produces returns the patterns of files this rule generates.

func (*MDToHtml) Run added in v0.0.18

func (m *MDToHtml) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

Generate the output resource for a related set of "input" targets

func (*MDToHtml) TargetsFor added in v0.0.18

func (m *MDToHtml) TargetsFor(s *Site, r *Resource) (siblings []*Resource, targets []*Resource)

type ParametricPages added in v0.0.33

type ParametricPages struct {
	// Renderers is a map of file extensions to the Rule that should be used
	// for rendering that file type. For example:
	// {
	//   ".md": &MDToHtml{},
	//   ".html": &HTMLToHtml{},
	// }
	Renderers map[string]Rule
}

ParametricPages is a rule that handles the discovery and generation of pages from a single parametric template (e.g., content/tags/[tag].html). It acts as a dispatcher, delegating the final rendering to a sub-rule based on the file extension.

func (*ParametricPages) DependsOn added in v0.1.0

func (p *ParametricPages) DependsOn() []string

DependsOn returns nil - ParametricPages doesn't depend on other rules.

func (*ParametricPages) Phase added in v0.1.0

func (p *ParametricPages) Phase() BuildPhase

Phase returns PhaseGenerate - parametric page expansion happens in the generate phase.

func (*ParametricPages) Produces added in v0.1.0

func (p *ParametricPages) Produces() []string

Produces returns the patterns of files this rule generates.

func (*ParametricPages) Run added in v0.0.33

func (p *ParametricPages) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) (err error)

Run finds the correct renderer based on the input file's extension and delegates the rendering job to it.

func (*ParametricPages) TargetsFor added in v0.0.33

func (p *ParametricPages) TargetsFor(s *Site, r *Resource) (siblings []*Resource, targets []*Resource)

TargetsFor first checks if the resource's extension is supported by one of its renderers. If so, it performs a "discovery" render to populate the resource's ParamValues, then generates a target resource for each of those values.

type PhaseRule added in v0.1.0

type PhaseRule interface {
	Rule

	// Phase returns which build phase this rule runs in.
	Phase() BuildPhase

	// DependsOn returns glob patterns of files this rule needs as input.
	// Used to order rules within a phase.
	DependsOn() []string

	// Produces returns glob patterns of files this rule creates.
	// Used to order rules within a phase.
	Produces() []string
}

PhaseRule is an optional interface that rules can implement to participate in the phase-based build pipeline. Rules that don't implement this interface are wrapped in LegacyRuleAdapter and run in PhaseGenerate.

type RSSGenerator added in v0.1.0

type RSSGenerator struct {
	// Title is the feed title
	Title string

	// Description is the feed description
	Description string

	// BaseURL is the base URL for the site (e.g., "https://example.com")
	BaseURL string

	// FeedPath is the URL path for the feed (default: "/feed.xml")
	FeedPath string

	// OutputPath is the file path to write the feed (default: "feed.xml")
	OutputPath string

	// ContentPattern is a glob pattern to match content files for the feed
	// Default: "blog/**/*.html"
	ContentPattern string

	// MaxItems is the maximum number of items in the feed (default: 20)
	MaxItems int
	// contains filtered or unexported fields
}

RSSGenerator generates an RSS feed in the Finalize phase. It collects blog posts and outputs them as an RSS 2.0 feed.

func (*RSSGenerator) DependsOn added in v0.1.0

func (g *RSSGenerator) DependsOn() []string

DependsOn returns patterns for HTML files.

func (*RSSGenerator) Phase added in v0.1.0

func (g *RSSGenerator) Phase() BuildPhase

Phase returns PhaseFinalize - RSS generation happens after all content is generated.

func (*RSSGenerator) Produces added in v0.1.0

func (g *RSSGenerator) Produces() []string

Produces returns the feed.xml pattern.

func (*RSSGenerator) Register added in v0.1.0

func (g *RSSGenerator) Register(site *Site)

Register adds the RSS generator to a site.

func (*RSSGenerator) Run added in v0.1.0

func (g *RSSGenerator) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

Run is a no-op - actual work is done via hooks.

func (*RSSGenerator) TargetsFor added in v0.1.0

func (g *RSSGenerator) TargetsFor(site *Site, res *Resource) ([]*Resource, []*Resource)

TargetsFor returns nil - RSSGenerator uses hooks instead of per-resource targets.

type Resource

type Resource struct {
	// Base is the underlying data structure for the resource.
	Base ResourceBase

	// Site is the site that this resource belongs to.
	Site *Site

	// Loader is the loader responsible for loading the resource's document.
	Loader ResourceLoader
	// Renderer is the renderer responsible for rendering the resource.
	Renderer ResourceRenderer

	// FullPath is the absolute path to the resource file.
	FullPath string

	// CreatedAt is the timestamp when the resource was created on disk.
	CreatedAt time.Time

	// UpdatedAt is the timestamp when the resource was last updated on disk.
	UpdatedAt time.Time

	// LoadedAt is the timestamp when the resource was loaded and parsed.
	LoadedAt time.Time

	// State is the current state of the resource in the build process.
	State int

	// Error holds any error that occurred while processing the resource.
	Error error

	// Metadata is a map for storing arbitrary metadata about the resource.
	Metadata map[string]any
	// Document is the parsed document of the resource.
	Document Document

	// Source is the resource that this resource was derived from. This is
	// only set for output resources.
	Source *Resource

	// IsParametric is true if the resource is a parametric page.
	IsParametric bool

	// ParamValues is the list of parameter values for a parametric page.
	ParamValues []string
	// ParamName is the name of the parameter for a parametric page.
	ParamName string

	// NeedsIndex is true if the resource should be rendered as an index page.
	NeedsIndex bool
	// IsIndex is true if the resource is an index page.
	IsIndex bool

	// Assets is a list of co-located assets (images, data files) for this resource.
	// These are identified during the Discover phase based on AssetPatterns.
	Assets []*Resource

	// AssetOf is the parent resource if this resource is a co-located asset.
	// If non-nil, this resource should not be processed as standalone content.
	AssetOf *Resource

	// ProducedBy is the rule that generated this resource (for output resources).
	ProducedBy Rule

	// ProducedAt is the build phase in which this resource was generated.
	ProducedAt BuildPhase
	// contains filtered or unexported fields
}

Resource represents a single file in the site, such as a content file, a template, or a static asset.

func (*Resource) AddParam

func (r *Resource) AddParam(param string) *Resource

AddParam adds a new parameter value to a parametric resource. This is used during the parameter discovery phase of rendering a parametric page.

func (*Resource) AddParams

func (r *Resource) AddParams(params []string) *Resource

AddParams adds a list of parameter values to a parametric resource.

func (*Resource) DirName

func (r *Resource) DirName() string

DirName returns the resource's directory.

func (*Resource) EnsureDir

func (r *Resource) EnsureDir()

EnsureDir ensures that the resource's parent directory exists.

func (*Resource) Ext

func (r *Resource) Ext() string

Ext returns the extension of the resource's path.

func (*Resource) FrontMatter

func (r *Resource) FrontMatter() *FrontMatter

FrontMatter returns the parsed front matter of the resource, loading it if necessary.

func (*Resource) Info

func (r *Resource) Info() os.FileInfo

Info returns the os.FileInfo for the resource.

func (*Resource) IsDir

func (r *Resource) IsDir() bool

IsDir returns true if the resource is a directory.

func (*Resource) ReadAll

func (r *Resource) ReadAll() ([]byte, error)

ReadAll reads all the content of the resource after the front matter.

func (*Resource) Reader

func (r *Resource) Reader() (io.ReadCloser, error)

Reader returns a reader for the content of the resource after the front matter.

func (*Resource) RelPath

func (r *Resource) RelPath() string

RelPath returns the path of the resource relative to the content root.

func (*Resource) Reset

func (r *Resource) Reset()

Reset resets the resource's state to Pending so it can be reloaded.

func (*Resource) SetMetadata added in v0.0.19

func (r *Resource) SetMetadata(key string, value any, kvpairs ...any) any

SetMetadata sets a metadata key-value pair on the resource.

func (*Resource) WithoutExt

func (r *Resource) WithoutExt(all bool) string

WithoutExt returns the resource's path without the extension.

type ResourceBase added in v0.0.18

type ResourceBase interface {
	LoadFrom(*Resource) error
}

ResourceBase is an interface for the base data structure of a resource.

type ResourceFilterFunc

type ResourceFilterFunc func(res *Resource) bool

ResourceFilterFunc is a function type for filtering resources.

type ResourceLoader

type ResourceLoader interface {
	Load(res *Resource) error
}

ResourceLoader is an interface for loading and parsing a resource.

type ResourceProcessor added in v0.0.18

type ResourceProcessor interface {
	GenerateTargets(res *Resource, deps map[string]*Resource) error
}

ResourceProcessor is an interface for generating target resources from a source resource.

type ResourceRenderer added in v0.0.18

type ResourceRenderer interface {
	Render(res *Resource, w io.Writer) error
}

ResourceRenderer is an interface for rendering a resource to an output stream.

type ResourceSortFunc

type ResourceSortFunc func(a *Resource, b *Resource) bool

ResourceSortFunc is a function type for sorting resources.

type Rule added in v0.0.18

type Rule interface {
	// TargetsFor determines if the rule can be applied to a given resource and,
	// if so, what the output file (or "target") should be. It can also identify
	// any "sibling" resources that are needed to process the input resource.
	TargetsFor(site *Site, res *Resource) (siblings []*Resource, targets []*Resource)

	// Run contains the logic for processing the resource. It takes the input
	// resources (the original resource and any siblings) and the target
	// resources and generates the output.
	Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error
}

Rule is an interface that defines how to process a resource. s3gen's build system is based on a set of rules that are applied to resources in a specific order. This allows for a flexible and extensible build process.

type Site

type Site struct {
	// Templates is the template group that holds all the parsed templates
	// and their functions.
	Templates *tmplr.TemplateGroup

	// CommonFuncMap is a map of functions that will be available in all templates.
	CommonFuncMap map[string]any

	// TemplateFolders is a list of directories where s3gen will look for templates.
	TemplateFolders []string

	// LoaderList is the list of template loaders.
	LoaderList *tmplr.LoaderList

	// ContentRoot is the root directory of your website's content. s3gen will
	// walk this directory to find all the files to process.
	ContentRoot string

	// OutputDir is the directory where the generated static files will be written.
	OutputDir string

	// PathPrefix is the URL path prefix for the site. For example, if your site
	// is served at mydomain.com/blog, your PathPrefix would be "/blog".
	PathPrefix string

	// StaticFolders is a list of directories that will be served as-is. It's
	// a slice of strings in the format [path1, dir1, path2, dir2, ...].
	StaticFolders []string

	// IgnoreDirFunc is a function that determines whether a directory should be
	// ignored during the build process.
	IgnoreDirFunc func(dirpath string) bool

	// IgnoreFileFunc is a function that determines whether a file should be
	// ignored during the build process.
	IgnoreFileFunc func(filepath string) bool

	// PriorityFunc is a function that determines the order in which resources
	// are processed. This is crucial for handling dependencies.
	PriorityFunc func(res *Resource) int

	// LiveReload enables or disables live reloading during development.
	LiveReload bool

	// LazyLoad enables or disables lazy loading of resources.
	LazyLoad bool

	// DefaultBaseTemplate is the default template to use for rendering pages.
	DefaultBaseTemplate BaseTemplate

	// GetTemplate is a function that can be used to override the default
	// template for a specific resource.
	GetTemplate func(res *Resource, out *BaseTemplate)

	// CreateResourceBase is a function that creates the base data structure
	// for a resource.
	CreateResourceBase func(res *Resource)

	// BuildRules is a list of rules that define how to process different
	// types of files.
	BuildRules []Rule

	// DefaultRule is the rule that will be used if no other rule matches a
	// resource.
	DefaultRule Rule

	// BuildFrequency is the interval at which the site will be rebuilt when
	// in watch mode.
	BuildFrequency time.Duration

	// AssetPatterns defines glob patterns for files that should be treated
	// as assets of co-located content files. Patterns are relative to the
	// content file's directory. Example: []string{"*.png", "*.jpg", "*.svg"}
	AssetPatterns []string

	// PhaseRules organizes rules by the phase they run in.
	// This is populated during Init() from BuildRules.
	PhaseRules map[BuildPhase][]Rule

	// Hooks provides callbacks for observing build events.
	Hooks *HookRegistry

	// SharedAssetsDir is the directory name for shared assets (used by parametric pages).
	// Defaults to "_assets" if not set.
	SharedAssetsDir string
	// contains filtered or unexported fields
}

Site is the central object in s3gen. It contains all the configuration and metadata for the website, and it orchestrates the build process.

func (*Site) AddEdge added in v0.0.12

func (s *Site) AddEdge(srcpath string, destpath string) bool

Add a dependency edge between two resources identified by their full paths. Returns true if edge was added without incurring a cycle, returns false if edge would have resulted in a cycle.

func (*Site) DefaultFuncMap added in v0.0.4

func (s *Site) DefaultFuncMap() map[string]any

DefaultFuncMap returns a map of the default template functions available in s3gen.

func (*Site) EdgeExists added in v0.0.12

func (s *Site) EdgeExists(srcpath string, destpath string) bool

Returns true if an edge exists between a source and a destination resource

func (*Site) GenerateSitemap added in v0.0.14

func (s *Site) GenerateSitemap() map[string]any

GenerateSitemap generates a sitemap for the site.

func (*Site) GetPagesByDate added in v0.0.18

func (s *Site) GetPagesByDate(hideDrafts bool, desc bool, offset, count any) (out []*Resource)

GetPagesByDate returns a list of pages, sorted by date.

func (*Site) GetPagesByTag added in v0.0.18

func (s *Site) GetPagesByTag(tag string, hideDrafts bool, desc bool, offset, count any) (out []*Resource)

GetPagesByTag returns a list of pages that have a specific tag.

func (*Site) GetResource

func (s *Site) GetResource(fullpath string) *Resource

Loads a resource and validates it. Note that a resources may not necessarily be in memory just because it is loaded. Just a Resource pointer is kept and it can be streamed etc

func (*Site) HandleStatic added in v0.0.6

func (s *Site) HandleStatic(path, folder string) *Site

HandleStatic adds a new static path to the site's router.

func (*Site) Handler added in v0.0.21

func (s *Site) Handler() http.Handler

Handler returns an http.Handler that can be used to serve the site.

func (*Site) Init

func (s *Site) Init() *Site

Init initializes the Site object with default values.

func (*Site) Json added in v0.0.4

func (s *Site) Json(path string, fieldpath string) (any, error)

Json reads and parses a JSON file from the content directory.

func (*Site) KeysForTagMap added in v0.0.18

func (s *Site) KeysForTagMap(tagmap map[string]int, orderby string) []string

KeysForTagMap returns a sorted list of keys from a tag map.

func (*Site) LeafPages added in v0.0.18

func (s *Site) LeafPages(hideDrafts bool, orderby string, offset, count any) (out []*Resource)

LeafPages returns a list of "leaf" pages (i.e., pages that are not index pages). It can be filtered by draft status and sorted by date or title.

func (*Site) ListResources

func (s *Site) ListResources(filterFunc ResourceFilterFunc,
	sortFunc ResourceSortFunc,
	offset int, count int) (foundResources []*Resource)

ListResources returns a list of resources in the site, with optional filtering and sorting.

func (*Site) LoadParamValues added in v0.0.18

func (s *Site) LoadParamValues(res *Resource) (err error)

LoadParamValues loads the parameter values for a parametric resource.

func (*Site) PathExists added in v0.0.12

func (s *Site) PathExists(srcpath string, destpath string) bool

func (*Site) PathRelUrl

func (s *Site) PathRelUrl(path string) string

PathRelUrl returns the full URL for a path relative to the site's path prefix.

func (*Site) Rebuild

func (s *Site) Rebuild(rs []*Resource)

Rebuild rebuilds the entire site using a 4-phase pipeline. If a list of resources is provided, only those resources will be rebuilt. Phases: Discover → Transform → Generate → Finalize

func (*Site) RemoveEdge added in v0.0.12

func (s *Site) RemoveEdge(srcpath string, destpath string) bool

Removes a dependency edge between two resources identified by their full paths

func (*Site) RemoveEdgesFrom added in v0.0.12

func (s *Site) RemoveEdgesFrom(srcpath string)

Remove all resources depended by a given path

func (*Site) RemoveEdgesTo added in v0.0.12

func (s *Site) RemoveEdgesTo(destpath string)

Removes all resources that a given path depends on

func (*Site) RemoveResource added in v0.0.12

func (s *Site) RemoveResource(path string) *Resource

Remove a resources from this graph along with all its dependencies

func (*Site) RenderHtmlTemplate added in v0.0.18

func (s *Site) RenderHtmlTemplate(templateFile, templateName string, params any) (out template.HTML, err error)

RenderHtmlTemplate renders a Go template as HTML.

func (*Site) RenderTextTemplate added in v0.0.18

func (s *Site) RenderTextTemplate(templateFile, templateName string, params any) (out string, err error)

RenderTextTemplate renders a Go template as plain text.

func (*Site) Serve added in v0.0.34

func (s *Site) Serve(address string) error

func (*Site) ServeHTTP

func (s *Site) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the http.Handler interface.

func (*Site) StopWatching

func (s *Site) StopWatching()

Disables/Stops watching for changes to content files.

func (*Site) Watch added in v0.0.2

func (s *Site) Watch()

Starts watching for changes to content files so that the site can be rebuilt.

type SitemapGenerator added in v0.1.0

type SitemapGenerator struct {
	// BaseURL is the base URL for the site (e.g., "https://example.com")
	BaseURL string

	// OutputPath is the path to write the sitemap (default: "sitemap.xml")
	OutputPath string

	// ChangeFreq is the default change frequency for pages (default: "weekly")
	ChangeFreq string

	// Priority is the default priority for pages (default: 0.5)
	Priority float64

	// ExcludePatterns are glob patterns for paths to exclude from the sitemap
	ExcludePatterns []string
	// contains filtered or unexported fields
}

SitemapGenerator generates a sitemap.xml in the Finalize phase. It collects all generated HTML pages and outputs them as a sitemap.

func (*SitemapGenerator) DependsOn added in v0.1.0

func (g *SitemapGenerator) DependsOn() []string

DependsOn returns patterns for HTML files - sitemap needs all pages generated first.

func (*SitemapGenerator) Phase added in v0.1.0

func (g *SitemapGenerator) Phase() BuildPhase

Phase returns PhaseFinalize - sitemap generation happens after all content is generated.

func (*SitemapGenerator) Produces added in v0.1.0

func (g *SitemapGenerator) Produces() []string

Produces returns the sitemap.xml pattern.

func (*SitemapGenerator) Register added in v0.1.0

func (g *SitemapGenerator) Register(site *Site)

Register adds the sitemap generator to a site. This sets up hooks to collect URLs during the build and write the sitemap at the end.

func (*SitemapGenerator) Run added in v0.1.0

func (g *SitemapGenerator) Run(site *Site, inputs []*Resource, targets []*Resource, funcs map[string]any) error

Run is a no-op - actual work is done via hooks.

func (*SitemapGenerator) TargetsFor added in v0.1.0

func (g *SitemapGenerator) TargetsFor(site *Site, res *Resource) ([]*Resource, []*Resource)

TargetsFor returns nil - SitemapGenerator uses hooks instead of per-resource targets.

type TOCNode added in v0.0.18

type TOCNode struct {
	ID       string    `json:"id"`
	Level    int       `json:"level"`
	Text     string    `json:"text"`
	Children []TOCNode `json:"children,omitempty"`
}

type TOCTransformer added in v0.0.18

type TOCTransformer struct {
	TOC        []TOCNode
	CurrentIDs map[string]int
}

func NewTOCTransformer added in v0.0.18

func NewTOCTransformer() *TOCTransformer

func (*TOCTransformer) Transform added in v0.0.18

func (t *TOCTransformer) Transform(doc *ast.Document, reader text.Reader, pc parser.Context)

Transform traverses the AST and collects heading elements

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL