ssg

module
v1.4.2 Latest Latest
Warning

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

Go to latest
Published: Jan 18, 2026 License: BSD-3-Clause, BSD-3-Clause

README ΒΆ

SSG - Static Site Generator

Go Version Go Report Card License CI codecov GitHub Action GitHub issues GitHub stars GitHub Release Docker GitHub forks

πŸ„ SSG - A simple static site generator written in Go. Converts content from WordPress exports (Markdown format with YAML frontmatter) to static HTML, CSS, and JS files.

πŸ“‹ Table of Contents

✨ Features

  • πŸš€ Fast static site generation
  • πŸ“ Markdown support with YAML frontmatter
  • 🎨 Two templates: simple (dark theme) and krowy (green/natural theme)
  • πŸ“± Responsive design
  • β™Ώ WCAG 2.2 compliant
  • πŸ” SEO-friendly URLs (clean addresses)
  • πŸ“ Automatic media file copying
  • 🏷️ Category support
  • πŸ“„ Config file support (YAML, TOML, JSON)
  • πŸ”§ Multiple template engines - Go, Pongo2 (Jinja2), Mustache, Handlebars
  • 🌍 Online theme download - use Hugo themes from GitHub/GitLab
  • 🌐 Built-in HTTP server (--http flag)
  • πŸ‘€ Watch mode - auto-rebuild on file changes (--watch flag)
  • πŸ–ΌοΈ WebP conversion (--webp flag)
  • πŸ—„οΈ Minification - HTML, CSS, JS (--minify-all flag)
  • 🧹 Clean builds (--clean flag)
  • πŸ“¦ Cloudflare Pages deployment package (--zip flag)
  • 🐳 Docker support - minimal Alpine image (~15MB)
  • 🎬 GitHub Actions integration - Use as a step in CI/CD pipelines

πŸ“¦ Requirements

  • Go 1.25 or later
  • Make (optional, for Makefile)
  • cwebp (optional, for WebP conversion)

πŸš€ Installation

Quick Install (Linux/macOS)
curl -sSL https://raw.githubusercontent.com/spagu/ssg/main/install.sh | bash
Package Managers
Platform Command
Homebrew (macOS/Linux) brew install spagu/tap/ssg
Snap (Ubuntu) snap install ssg
Debian/Ubuntu wget https://github.com/spagu/ssg/releases/download/v1.3.0/ssg_1.3.0_amd64.deb && sudo dpkg -i ssg_1.3.0_amd64.deb
Fedora/RHEL sudo dnf install https://github.com/spagu/ssg/releases/download/v1.3.0/ssg-1.3.0-1.x86_64.rpm
FreeBSD pkg install ssg or from ports
OpenBSD From ports: /usr/ports/www/ssg
Binary Downloads

Download pre-built binaries from GitHub Releases:

Platform AMD64 ARM64
Linux ssg-linux-amd64.tar.gz ssg-linux-arm64.tar.gz
macOS ssg-darwin-amd64.tar.gz ssg-darwin-arm64.tar.gz
FreeBSD ssg-freebsd-amd64.tar.gz ssg-freebsd-arm64.tar.gz
Windows ssg-windows-amd64.zip ssg-windows-arm64.zip
From Source
git clone https://github.com/spagu/ssg.git
cd ssg
make build
sudo make install
Docker
# Pull image from GitHub Container Registry
docker pull ghcr.io/spagu/ssg:latest

# Run SSG in container
docker run --rm -v $(pwd):/site ghcr.io/spagu/ssg:latest \
    my-content krowy example.com --webp

# Or use docker-compose
docker compose run --rm ssg my-content krowy example.com

# Development server with watch mode
docker compose up dev

πŸ“– Full installation guide: docs/INSTALL.md

πŸ’» Usage

Syntax
ssg <source> <template> <domain> [options]
Arguments
Argument Description
source Source folder name (inside content-dir)
template Template name (inside templates-dir)
domain Target domain for the generated site
Configuration File

SSG supports configuration files in YAML, TOML, or JSON format. Auto-detects: .ssg.yaml, .ssg.toml, .ssg.json

# Use explicit config file
ssg --config .ssg.yaml

# Or just create .ssg.yaml and run ssg (auto-detected)
ssg

Example .ssg.yaml:

source: "my-content"
template: "krowy"
domain: "example.com"

http: true
watch: true
clean: true
webp: true
webp_quality: 80
minify_all: true

See .ssg.yaml.example for all options.

Options

Configuration:

Option Description
--config=FILE Load config from YAML/TOML/JSON file

Server & Development:

Option Description
--http Start built-in HTTP server (default port: 8888)
--port=PORT HTTP server port (default: 8888)
--watch Watch for changes and rebuild automatically
--clean Clean output directory before build

Output Control:

Option Description
--sitemap-off Disable sitemap.xml generation
--robots-off Disable robots.txt generation
--minify-all Minify HTML, CSS, and JS
--minify-html Minify HTML output
--minify-css Minify CSS output
--minify-js Minify JS output
--sourcemap Include source maps in output

Image Processing (Native Go - no external tools needed):

Option Description
--webp Convert images to WebP format (requires cwebp)
--webp-quality=N WebP compression quality 1-100 (default: 60)

Deployment:

Option Description
--zip Create ZIP file for Cloudflare Pages

Paths:

Option Description
--content-dir=PATH Content directory (default: content)
--templates-dir=PATH Templates directory (default: templates)
--output-dir=PATH Output directory (default: output)

Template Engine:

Option Description
--engine=ENGINE Template engine: go (default), pongo2, mustache, handlebars
--online-theme=URL Download theme from URL (GitHub, GitLab, or direct ZIP)

Other:

Option Description
--quiet, -q Suppress output (only exit codes)
--version, -v Show version
--help, -h Show help
Examples
# Development mode: HTTP server + auto-rebuild on changes
./build/ssg my-content krowy example.com --http --watch

# HTTP server on custom port
./build/ssg my-content krowy example.com --http --port=3000

# Generate site with krowy template
./build/ssg krowy.net.2026-01-13110345 krowy krowy.net

# Generate with simple template (dark theme)
./build/ssg krowy.net.2026-01-13110345 simple krowy.net

# Generate with WebP conversion and ZIP package
./build/ssg krowy.net.2026-01-13110345 krowy krowy.net --webp --zip

# Use custom directories
./build/ssg my-content my-template example.com \
  --content-dir=/data/content \
  --templates-dir=/data/templates \
  --output-dir=/var/www/html

# Or using Makefile
make generate        # krowy template
make generate-simple # simple template
make serve           # generate and run local server
make deploy          # generate with WebP + ZIP for Cloudflare Pages
Output

Generated files will be in the output/ folder:

output/
β”œβ”€β”€ index.html          # Homepage
β”œβ”€β”€ css/
β”‚   └── style.css       # Stylesheet
β”œβ”€β”€ js/
β”‚   └── main.js         # JavaScript
β”œβ”€β”€ media/              # Media files
β”œβ”€β”€ {slug}/             # Pages and posts (SEO URLs)
β”‚   └── index.html
β”œβ”€β”€ category/
β”‚   └── {category-slug}/
β”‚       └── index.html
β”œβ”€β”€ sitemap.xml         # Sitemap for search engines
β”œβ”€β”€ robots.txt          # Robots file
β”œβ”€β”€ _headers            # Cloudflare Pages headers
└── _redirects          # Cloudflare Pages redirects

πŸ”§ Template Engines

SSG supports multiple template engines. By default, Go templates are used, but you can switch to other engines:

Available Engines
Engine Flag Syntax Style
Go (default) --engine=go {{"{{"}}.Variable}}, {{"{{"}}.range .Items}}
Pongo2 --engine=pongo2 Jinja2/Django: {{"{{"}}.variable}}, {%raw%}{% for item in items %}{%endraw%}
Mustache --engine=mustache {{"{{"}}.variable}}, {{"{{#"}} items}}
Handlebars --engine=handlebars {{"{{"}}.variable}}, {{"{{#each"}} items}}
Usage Examples
# Use Pongo2 (Jinja2/Django syntax)
ssg my-content mytheme example.com --engine=pongo2

# Use Mustache
ssg my-content mytheme example.com --engine=mustache

# Use Handlebars
ssg my-content mytheme example.com --engine=handlebars
Online Themes

Download themes directly from GitHub, GitLab, or any ZIP URL:

# Download Hugo theme from GitHub
ssg my-content bearblog example.com --online-theme=https://github.com/janraasch/hugo-bearblog

# Download from any URL
ssg my-content mytheme example.com --online-theme=https://example.com/theme.zip

The theme will be downloaded and extracted to templates/{template-name}/.

Template Syntax Comparison

Go Templates:

{% raw %}

{{ range .Posts }}
  <h2>{{ .Title }}</h2>
  <p>{{ .Content }}</p>
{{ end }}

{% endraw %}

Pongo2 (Jinja2):

{% raw %}

{% for post in Posts %}
  <h2>{{ post.Title }}</h2>
  <p>{{ post.Content }}</p>
{% endfor %}

{% endraw %}

Mustache:

{% raw %}

{{#Posts}}
  <h2>{{Title}}</h2>
  <p>{{Content}}</p>
{{/Posts}}

{% endraw %}

Handlebars:

{% raw %}

{{#each Posts}}
  <h2>{{Title}}</h2>
  <p>{{Content}}</p>
{{/each}}

{% endraw %}

🎬 GitHub Actions

Use SSG as a GitHub Action in your CI/CD pipeline:

Versioning
Reference Description
spagu/ssg@main Latest from main branch (development)
spagu/ssg@v1 Latest stable v1.x release
spagu/ssg@v1.3.0 Specific version

Note: Use @main until a stable release is published.

Basic Usage
- name: Generate static site
  uses: spagu/ssg@main  # or @v1 after release
  with:
    source: 'my-content'
    template: 'krowy'
    domain: 'example.com'
Full Configuration

{% raw %}

- name: Generate static site
  id: ssg
  uses: spagu/ssg@v1
  with:
    source: 'my-content'           # Content folder (inside content/)
    template: 'krowy'              # Template: 'simple' or 'krowy'
    domain: 'example.com'          # Target domain
    version: 'latest'              # Optional: SSG version (default: latest)
    content-dir: 'content'         # Optional: content directory path
    templates-dir: 'templates'     # Optional: templates directory path
    output-dir: 'output'           # Optional: output directory path
    webp: 'true'                   # Optional: convert images to WebP
    webp-quality: '80'             # Optional: WebP quality 1-100 (default: 60)
    zip: 'true'                    # Optional: create ZIP for deployment
    minify: 'true'                 # Optional: minify HTML/CSS/JS
    clean: 'true'                  # Optional: clean output before build

- name: Show outputs
  run: |
    echo "Output path: ${{ steps.ssg.outputs.output-path }}"
    echo "ZIP file: ${{ steps.ssg.outputs.zip-file }}"
    echo "ZIP size: ${{ steps.ssg.outputs.zip-size }} bytes"

{% endraw %}

Action Inputs
Input Description Required Default
source Content source folder name βœ… -
template Template name βœ… simple
domain Target domain βœ… -
version SSG version to download ❌ latest
content-dir Path to content directory ❌ content
templates-dir Path to templates directory ❌ templates
output-dir Path to output directory ❌ output
webp Convert images to WebP ❌ false
webp-quality WebP compression quality 1-100 ❌ 60
zip Create ZIP file ❌ false
minify Minify HTML, CSS, and JS ❌ false
clean Clean output directory before build ❌ false
Action Outputs
Output Description
output-path Path to generated site directory
zip-file Path to ZIP file (if --zip used)
zip-size Size of ZIP file in bytes
Deploy to Cloudflare Pages

{% raw %}

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Generate site
        id: ssg
        uses: spagu/ssg@v1
        with:
          source: 'my-content'
          template: 'krowy'
          domain: 'example.com'
          webp: 'true'

      - name: Deploy to Cloudflare
        uses: cloudflare/pages-action@v1
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          projectName: 'my-site'
          directory: ${{ steps.ssg.outputs.output-path }}

{% endraw %}

πŸ“ Project Structure

ssg/
β”œβ”€β”€ cmd/
β”‚   └── ssg/
β”‚       └── main.go           # CLI entry point
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ generator/
β”‚   β”‚   β”œβ”€β”€ generator.go      # Generator logic
β”‚   β”‚   β”œβ”€β”€ generator_test.go # Generator tests
β”‚   β”‚   └── templates.go      # Default HTML templates
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   └── content.go        # Data models
β”‚   └── parser/
β”‚       β”œβ”€β”€ markdown.go       # Markdown parser
β”‚       └── markdown_test.go  # Parser tests
β”œβ”€β”€ content/                  # Source data
β”‚   └── {source}/
β”‚       β”œβ”€β”€ metadata.json
β”‚       β”œβ”€β”€ media/
β”‚       β”œβ”€β”€ pages/
β”‚       └── posts/
β”œβ”€β”€ templates/                # Templates
β”‚   β”œβ”€β”€ simple/
β”‚   β”‚   β”œβ”€β”€ css/
β”‚   β”‚   └── js/
β”‚   └── krowy/
β”‚       β”œβ”€β”€ css/
β”‚       └── js/
β”œβ”€β”€ output/                   # Generated site (gitignored)
β”œβ”€β”€ go.mod
β”œβ”€β”€ go.sum
β”œβ”€β”€ Makefile
β”œβ”€β”€ README.md
β”œβ”€β”€ CHANGELOG.md
β”œβ”€β”€ .gitignore
└── .dockerignore

🎨 Templates

simple - Modern Dark Theme

Elegant dark theme with glassmorphism and gradients:

  • Dark background: #0f0f0f
  • Cards: #222222
  • Accent: purple gradient #6366f1 β†’ #a855f7
  • Hover animations and micro-interactions
krowy - Green Farm Theme

Natural light theme inspired by krowy.net:

  • Light background: #f8faf5
  • Cards: #ffffff
  • Accent: green #2d7d32
  • Cow icon πŸ„ in logo
  • Nature and ecology focus

🎨 Styles/Colors

Color Guidelines (WCAG 2.2 Compliant)
Simple Template (Dark)
/* Background */
--color-bg-primary: #0f0f0f;
--color-bg-secondary: #1a1a1a;
--color-bg-card: #222222;

/* Text (minimum contrast 4.5:1) */
--color-text-primary: #ffffff;
--color-text-secondary: #b3b3b3;
--color-text-muted: #808080;

/* Accent */
--color-accent: #6366f1;
--gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%);
Krowy Template (Light)
/* Background */
--color-bg-primary: #f8faf5;
--color-bg-secondary: #ffffff;
--color-bg-card: #ffffff;

/* Text (minimum contrast 4.5:1) */
--color-text-primary: #1a2e1a;
--color-text-secondary: #3d5a3d;
--color-text-muted: #6b8a6b;

/* Accent */
--color-accent: #2d7d32;
--gradient-primary: linear-gradient(135deg, #2d7d32 0%, #43a047 50%, #66bb6a 100%);

Detailed style documentation: docs/STYLES.md

πŸ—οΈ Architecture

flowchart TB
    subgraph Input["πŸ“₯ Input"]
        A[content/source] --> B[metadata.json]
        A --> C[pages/*.md]
        A --> D[posts/**/*.md]
        A --> E[media/*]
    end

    subgraph Processing["βš™οΈ Processing"]
        F[Parser] --> G[Models]
        G --> H[Generator]
        T[Templates] --> H
    end

    subgraph Output["πŸ“€ Output"]
        H --> I[output/]
        I --> J[index.html]
        I --> K[pages/]
        I --> L[posts/]
        I --> M[category/]
        I --> N[css/]
        I --> O[js/]
        I --> P[media/]
    end

    B --> F
    C --> F
    D --> F
    E --> P

πŸ§ͺ Testing

# Run all tests
make test

# Tests with coverage
make test-coverage

# Open coverage report
open coverage.html

πŸ› οΈ Development

Available Make Commands
make help           # Show all commands
make all            # deps + lint + test + build
make build          # Build binary
make test           # Run tests
make lint           # Check code
make run            # Build and run
make generate       # Generate site (krowy template)
make generate-simple # Generate site (simple template)
make serve          # Generate and serve locally
make deploy         # Generate with WebP + ZIP for Cloudflare Pages
make clean          # Clean artifacts
make install        # Install binary to /usr/local/bin
Creating Your Own Template
  1. Create a folder in templates/your-template-name/
  2. Add files:
    • css/style.css
    • js/main.js (optional)
    • index.html, page.html, post.html, category.html (optional)
  3. HTML templates are generated automatically if missing

πŸ“„ License

BSD 3-Clause License - see LICENSE

πŸ‘₯ Authors

Directories ΒΆ

Path Synopsis
cmd
ssg command
Package main provides the entry point for the SSG (Static Site Generator) CLI tool.
Package main provides the entry point for the SSG (Static Site Generator) CLI tool.
internal
config
Package config handles SSG configuration file parsing
Package config handles SSG configuration file parsing
engine
Package engine provides multiple template engine implementations
Package engine provides multiple template engine implementations
generator
Package generator handles static site generation
Package generator handles static site generation
models
Package models defines data structures for content parsing
Package models defines data structures for content parsing
parser
Package parser handles parsing of content files (Markdown with YAML frontmatter)
Package parser handles parsing of content files (Markdown with YAML frontmatter)
theme
Package theme provides theme downloading and management
Package theme provides theme downloading and management
webp
Package webp provides WebP image conversion using the cwebp command-line tool.
Package webp provides WebP image conversion using the cwebp command-line tool.

Jump to

Keyboard shortcuts

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