SSG is a fast static site generator written in Go. It turns Markdown with YAML frontmatter into a complete website with clean URLs, templates, feeds, search, image processing and optional native deployment.
It works especially well for blogs and WordPress migrations, but can also build documentation, company sites, portfolios and landing pages.
Quick start · Content model · Configuration · Templates · Deployment · Documentation
- Fast, deterministic builds with a single Go binary
- Markdown content with YAML frontmatter
- Built-in
simple,krowyandapidoc(documentation) themes - Go, Pongo2, Mustache and Handlebars template engines
- Sitemap, robots.txt, Atom feeds, search index and SEO metadata
- WebP conversion, responsive images, SCSS, minification and fingerprinting
- Local server with automatic rebuilds
- Redirects engine with chain flattening and a
redirects()-config importer - Cloudflare Pages Functions integration for payments, forms and dynamic endpoints
- Native deployment to Cloudflare Pages, GitHub Pages, Netlify, Vercel, FTP and SFTP
- GitHub Action and multi-architecture Docker images
Most advanced features are opt-in. A basic command only reads content, renders
HTML and writes the result to output/.
Linux and macOS:
curl -sSL https://raw.githubusercontent.com/spagu/ssg/main/install.sh | bash
# verifies the download against the release's checksums.sha256 before installingOther supported installation methods:
| Method | Command or location |
|---|---|
| Homebrew | brew install spagu/tap/ssg |
| Snap | snap install static-site-generator && sudo snap alias static-site-generator ssg |
| Release binaries and packages | GitHub Releases |
| Docker Hub | docker pull tradik/ssg:latest |
| GitHub Container Registry | docker pull ghcr.io/spagu/ssg:latest |
| Build from source | make build |
For platform-specific instructions, see docs/INSTALL.md. Already running an older SSG? docs/UPGRADING.md lists every step between your version and this one — most upgrades need none.
The fastest way is ssg init, which scaffolds a ready-to-build project —
config, a content source with a sample page and post, a static/ folder and a
.gitignore — without overwriting anything that already exists:
ssg init my-blog --domain blog.example.com
ssg --config .ssg.yaml --http --watchOr lay it out by hand:
content/
└── my-blog/
├── metadata.json
├── pages/
│ └── about.md
└── posts/
└── general/
└── hello.md
content/my-blog/metadata.json:
{
"title": "My Blog",
"description": "Thoughts and notes",
"url": "https://example.com",
"language": "en",
"categories": [{ "id": 1, "name": "General", "slug": "general" }],
"users": [{ "id": 1, "name": "Editor", "slug": "editor" }],
"media": []
}content/my-blog/pages/about.md:
---
title: About
slug: about
status: publish
type: page
---
This is my first page.content/my-blog/posts/general/hello.md:
---
title: Hello World
slug: hello-world
status: publish
type: post
date: 2026-04-01
categories: [General]
author: 1
---
This is my first post.ssg my-blog simple example.com --http --watchOpen http://127.0.0.1:8888. SSG rebuilds the site when its files change.
The generated site is written to output/; do not edit that directory by hand.
The simple, krowy and apidoc themes are embedded in the binary and scaffolded when
first used, so this example does not require a local templates/simple/ folder.
ssg <source> <template> <domain> [options]
| Argument | Meaning | Default location or use |
|---|---|---|
source |
Content collection name | content/<source>/ |
template |
Theme name | templates/<template>/ or an embedded theme |
domain |
Canonical host without a scheme | Canonical URLs, feeds, sitemap and SEO |
Example:
ssg my-blog krowy example.com --clean --minify-allThis reads content/my-blog/, uses the krowy theme, treats
https://example.com as the canonical site root and writes to output/.
All three values may instead be provided by a configuration file. In MDDB mode, content is fetched remotely and the source argument is optional.
SSG uses explicit locations and predictable output rules. These rules are useful both when authoring a site manually and when generating one programmatically.
project/
├── .ssg.yaml # optional configuration
├── content/
│ └── <source>/
│ ├── metadata.json # required for a local content source
│ ├── pages/ # recursively loaded pages
│ ├── posts/
│ │ └── <group>/ # at least one directory below posts/
│ │ └── post.md # deeper nesting is allowed
│ └── media/ # optional content media
├── templates/
│ └── <template>/ # optional when using an embedded theme
├── data/ # optional YAML/JSON template data
├── static/ # optional files copied verbatim
└── output/ # generated; safe to delete and rebuild
Important invariants:
- Pages are loaded recursively from
pages/. - Posts must be inside at least one subdirectory of
posts/. Files directly inposts/are ignored. Below the first subdirectory, nesting is recursive. - A post's category comes from its
categoriesfrontmatter, not its directory. - Local builds require
metadata.jsonat the root of the selected source. - Files with frontmatter are rendered only when
status: publishis present. - A plain Markdown file without frontmatter is treated as published content.
output/contains generated artifacts and must not be used as source content.
The directory names can be changed with pages_path, posts_path,
content_dir, templates_dir, data_dir, static_dir and output_dir.
For predictable results, pages and posts should define title, status and
type. Posts should additionally define date.
| Field | Type | Meaning |
|---|---|---|
title |
string | Display title |
slug |
string | URL segment; defaults to the Markdown filename |
status |
string | Only publish is rendered when frontmatter exists |
type |
string | page or post; affects templates and URL generation |
date |
date | Post publication date in YYYY-MM-DD form |
modified |
date | Last modification date |
categories |
list | Category IDs, names or slugs from metadata.json |
author |
integer/string | Author ID, name or slug from metadata.json |
tags |
list | Free-form tags; generates /tag/<slug>/ listings |
series |
string | Generates a /series/<slug>/ listing and navigation |
excerpt |
string | Summary for listings, feeds and metadata |
description |
string | SEO description; falls back to the excerpt |
link |
string | Explicit URL path; overrides normal URL rules |
canonical |
string | Explicit canonical URL |
aliases |
list | Previous paths that 301 to this item (and, by default, get a redirect stub) |
alias_stubs |
bool | Per-page override: false = 301 only (no duplicate copy), true = force a stub |
schema |
map | Override/extend this page's generated JSON-LD (deep-merged, per-page wins) |
featured_image |
string | Hero image; also the og:image, twitter:image and JSON-LD image (follows WebP conversion) |
layout |
string | Page layout name; redirect also marks sitemap exclusion |
template |
string | Page template file override |
robots |
string | Robots directive; noindex also excludes from sitemap |
sitemap |
string | Set to no to exclude from sitemap.xml |
lang |
string | Content language for multilingual builds |
Unknown frontmatter keys are preserved and exposed to templates. Author and category matching is case-insensitive; unresolved values are ignored.
Markdown can use explicit export-style sections:
## Excerpt
A short description used in listings.
## Content
The complete article starts here.Without these exact markers, all Markdown after the frontmatter becomes content.
SSG automatically detects .ssg.yaml, .ssg.toml or .ssg.json:
ssgAn explicit file can be selected with:
ssg --config path/to/site.yamlMinimal .ssg.yaml:
source: my-blog
template: simple
domain: example.com
clean: true
minify_all: trueCommon options:
| Goal | Configuration key | CLI flag |
|---|---|---|
| Development server | http: true |
--http |
| Automatic rebuilds | watch: true |
--watch |
| Cloudflare Wrangler | watch_runner: wrangler |
--wrangler |
| Cloudflare Workerd | watch_runner: workerd |
--workerd |
| Custom watch command | watch_runner: "cmd" |
--watch-runner="cmd" |
| Runner config outside the project | watch_runner_config: deploy/wrangler.toml |
--wrangler-config=deploy/wrangler.toml |
| Worker in a monorepo subdirectory | watch_runner_dir: booking/apps/api |
--wrangler-dir=booking/apps/api |
| Clean output first | clean: true |
--clean |
| Minify HTML/CSS/JS | minify_all: true |
--minify-all |
| Convert images to WebP | webp: true |
--webp |
| Responsive images | image_sizes: [480, 960] |
--image-sizes=480,960 |
| Fingerprint CSS/JS | fingerprint: true |
--fingerprint |
| Compile SCSS | scss: true |
--scss |
| Generate Atom feeds | feed: true |
--feed |
| Generate search index | search_index: true |
--search-index |
| Declare the site's tools to a browser agent | webmcp: true |
--webmcp |
| Add SEO metadata | seo: true |
--seo |
| Validate frontmatter contracts | content_schemas: {post: {required: [title, date]}} |
config only |
| Fail the build on any violation | strict: true |
--strict |
Emit a route manifest (routes.json) |
route_manifest: true |
--route-manifest |
| Publish a build report (version, duration, pages) | build_report: build.json |
--build-report |
Publish the site's model for agents (site-graph.json + MCP site_*) |
site_graph: true |
config only |
| Report where the build's time went | profile: text |
--profile[=json] |
| Rebuild only what a change reaches | incremental: true |
--incremental |
| Keep converted Markdown between builds | markdown_cache: true |
--markdown-cache |
| See what a change rebuilds, and why | — | ssg graph [file], MCP site_dependencies |
| Read and edit the config from the CLI | — | ssg config view|set|unset |
| Turn records from a file or API into pages | mode: content + content_map: |
config only |
| Edit frontmatter and body text in the browser, with AI proposals that never save | — | --http --watch --edit |
| Declare tracking ids (GTM both halves, GA4) | analytics_ids: {gtm: GTM-…} |
config only |
| Typed content components with a props schema | a components/ directory |
--components-dir=DIR |
| Decide the markup for images, links, headings, code | render_hooks: {image: …} |
config only |
| Name relations between pages, and version a document | relations: / version_of: in frontmatter |
config only |
| Publish a page as JSON, Markdown, text or your own format | outputs: {page: [html, json]} |
--outputs=html,json |
| Validate internal links | check_links: strict |
--check-links=strict |
| Fail on unrenderable shortcodes | shortcode_errors: strict |
--shortcode-errors=strict |
| Pull Markdown from other folders | content_sources: [{path: docs}] |
--content-source=docs |
| Derive missing excerpts | auto_excerpt: true |
--auto-excerpt |
| Rewrite links to repository files | link_rewrites: {"../examples/": "https://…"} |
config only |
| Create ZIP package | zip: true |
--zip |
WebP output requires the optional cwebp executable. SCSS compilation requires
the optional Dart Sass sass executable. Other native image operations use Go,
but selecting WebP as their output format also requires cwebp.
The canonical configuration reference is .ssg.yaml.example. The CLI also provides an installed-version reference:
ssg --help| Task | Command |
|---|---|
| Preview while editing | ssg my-blog simple example.com --http --watch |
| Let a client edit a page in the browser | ssg my-blog simple example.com --http --watch --edit |
| See what editing one file rebuilds | ssg graph content/my-blog/posts/hello.md |
| Production build | ssg my-blog simple example.com --clean --minify-all |
| WebP and responsive images | ssg my-blog simple example.com --webp --image-sizes=480,960,1600 |
| Feed, search and SEO | ssg my-blog simple example.com --feed --search-index --seo |
| Immutable asset names | ssg my-blog simple example.com --minify-all --fingerprint |
| Strict link validation | ssg my-blog simple example.com --check-links=strict |
| Create deployment archives | ssg my-blog simple example.com --zip --targz --tarxz |
| Use a Pongo2 theme | ssg my-blog my-theme example.com --engine=pongo2 |
| Use only configuration | ssg --config .ssg.yaml |
Options are composable unless a specific option documents otherwise.
This is a discovery index, not a second configuration reference. Exact defaults and accepted values live in .ssg.yaml.example.
| Area | Available capabilities |
|---|---|
| Authoring | Shortcodes, table of contents, syntax highlighting, KaTeX math, raw HTML sanitization; a file dropped for a missing status: or unparseable frontmatter is named with the likely cause (strict: true fails the build on the latter) (docs/CONTENT.md) |
| Blog | Pagination, tags, categories, series, reading time, Atom feeds, related content |
| API docs from code | api_docs: reads JavaScript (and TypeScript declarations) with their doc comments into pages of the site — packages, modules, classes, cross-links, source links — plus api.json, check_api, and MCP/WebMCP tools for agents; no Node needed for JS. @example blocks can run in the browser (playground:) (docs/API_DOCS.md) |
| API docs for Go, PHP, Python | The same pages from Go (standard library parser), PHP and Python (built-in declaration scanners): nothing to install, language detected from go.mod, composer.json, pyproject.toml (docs/API_LANGUAGES.md) |
| Web Stories | Google Web Stories (AMP) from your posts: cover, captioned photo pages, a link back to the article, a hub page and sitemap entries (docs/WEB_STORIES.md) |
| Print / PDF and Cook Mode | A print button with a clean print stylesheet and a printable recipe card, and a full-screen step-by-step recipe view that keeps the screen awake; every theme, built from the Recipe structured data (docs/PRINT_AND_COOK_MODE.md) |
| Résumé / CV | A Schema Resume JSON document as a page in any theme, with ProfilePage/Person JSON-LD and the document at /cv/resume.json; contact details stay private by default (docs/RESUME.md) |
| Recipes and structured data | Recipe fields from the post (ingredients, method, category), faq: → FAQPage, ItemList on listings, ProfilePage for authors, Organization from marketing: (docs/CONFIGURATION.md) |
| REST API docs from OpenAPI | api_docs: - openapi: openapi.yaml turns an OpenAPI 3.0/3.1 file into pages: endpoints by tag, parameters, bodies, responses, schemas, and a "Try it" console that sends real requests with keys kept in memory only (docs/REST_API_DOCS.md) |
apidoc theme |
A documentation-only theme: guides and references in one sidebar, search, "On this page", light/dark, WCAG 2.2 AA (templates/apidoc/README.md) |
| Read aloud | A "Listen" button with the visitor's own browser voice, and/or an MP3 per article from a TTS API at build time — cached, with a jingle, a fallback when the API is down, a podcast feed, and a self-hostable Docker TTS server (docs/AUDIO.md) |
| Taxonomies | Custom dynamic taxonomies with term archives, metadata, per-term feeds and template helpers (docs/TAXONOMIES.md) |
| SEO and migration | Sitemap, robots.txt, aliases, configurable permalinks, canonical URLs, link checking, .md link rewriting |
| Site migration | ssg migrate wordpress <url> — scaffold + content pull (wpexporter) + build in one command; completes title/description/timezone/colors from the source site; pages, posts, media, a theme's own post types and reader comments; --watch --http migrates live in the browser (docs/MIGRATE.md) |
| Front page | A content page at / (what a WordPress static front page exports as) becomes the site's front page; posts_page: gives the generated listing a home of its own |
| Content repair | ssg repair --fix rewrites source Markdown a page-builder export left indented or fenced into a code block; check_markup reports both on every build (docs/CONFIGURATION.md) |
| Several projects at once | ssg daemon watches every project in .ssg_projects from one process; editing the file reloads the fleet in place, leaving untouched projects running (docs/DAEMON.md) |
| Staying current | Every build's first line names the binary that produced it; ssg self-update-check says whether a newer release is out and prints the upgrade command for your install — snap, Homebrew, apt, dnf, Docker or the releases page. It never self-updates and never contacts the network on its own (docs/INSTALL.md) |
| Redirects | redirects: → real Cloudflare/Netlify _redirects (splats, chain flattening, aliases as 301s), served by the built-in preview so a rule can be checked before it ships, ssg import redirects from a JS redirects() config (docs/DEPLOYMENT.md) |
| Dynamic endpoints | Cloudflare Pages Functions via worker: + ssg new worker templates (contact form, Stripe, dynamic pricing, conversions proxy, cookie consent, comments, newsletter sign-up, rate limit, republish trigger), configurable _headers (docs/WORKERS.md) |
| Assets | WebP, responsive variants, build-time image helpers, SCSS, bundles, minification, source maps, fingerprinting |
| Data | YAML/JSON data files, custom variables and static passthrough files |
| External sources | Unified .ExternalData from local files (YAML/JSON/TOML/CSV/XML), HTTP APIs with a hardened client + disk cache, read-only SQL (MySQL/MariaDB/PostgreSQL/SQLite) and CMS imports (WordPress, Drupal, Movable Type) (docs/EXTERNAL_SOURCES.md) |
| Localisation | Full i18n: translation keys, dictionaries + t, language routing, hreflang/x-default in the head and in the sitemap (front pages and post listings included), per-language feeds each advertised on its own language's pages, search, language_sections: to assign a language to a whole directory, upper/lower/title for a switcher's labels (docs/I18N.md) |
| Content sources | Local Markdown or MDDB over HTTP/gRPC, including watched remote content |
| Output | Directory/flat pages, JSON output, feeds, search index, ZIP, tar.gz and tar.xz |
| Server | File watching, gzip, TLS, automatic certificates, HTTP/2, HTTP/3, resource limits, basic/JWT auth, IP allow/block lists and per-IP rate limiting |
| Automation | Lifecycle hooks, Git-derived modification dates, GitHub Action and native deployment |
| AI assistance | Build-time [ai …] shortcode (models + agents with rules/skills, cached answers), ssg mcp development server with designer and content-manager roles, find-then-edit tools that cost the size of the change rather than the file, an optional MDDB-backed search, and an approve-then-PR git flow (docs/MCP.md) |
| Engine | Value | Syntax family |
|---|---|---|
| Go templates | go |
Go html/template; default and full helper support |
| Pongo2 | pongo2 |
Jinja2/Django |
| Mustache | mustache |
Logic-less Mustache |
| Handlebars | handlebars |
Handlebars blocks and helpers |
Select an engine with --engine=<value> or engine: <value>. Non-Go themes must
contain templates authored in their selected syntax; they do not receive the Go
template FuncMap or Go block inheritance.
A typical Go theme contains:
templates/my-theme/
├── base.html
├── index.html
├── page.html
├── post.html
├── category.html
├── css/
├── js/
├── layouts/
└── partials/
Missing standard templates receive built-in fallbacks. Themes may also be
downloaded with --online-theme=<URL>.
Common Go template values:
| Value | Meaning |
|---|---|
.Title, .Content, .Excerpt |
Current page/post content |
.URL, .CanonicalURL |
Relative and canonical URLs |
.Date, .Modified |
Content dates |
.Site.Pages, .Site.Posts |
Site collections |
.Data |
Data loaded from data/ |
.Vars |
Custom configuration variables |
.Pager |
Pagination state when enabled |
For collection helpers, conditionals and image functions, see docs/TEMPLATE_HELPERS.md and docs/IMAGES.md.
Depending on enabled features, output/ can contain:
output/
├── index.html
├── <page-slug>/index.html
├── <year>/<month>/<day>/<post-slug>/index.html
├── category/<category-slug>/index.html
├── tag/<tag-slug>/index.html
├── series/<series-slug>/index.html
├── css/
├── js/
├── media/
├── sitemap.xml
├── robots.txt
├── feed.xml
└── search-index.json
URL layouts can be changed with page_format, post_url_format, explicit
permalink patterns or an item's link field.
SSG can deploy the generated output without provider-specific CLIs. Credentials are read from environment variables, never from content files.
| Provider | Flag | Required environment |
|---|---|---|
| Cloudflare Pages | --deploy=cloudflare |
CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID |
| GitHub Pages | --deploy=github-pages |
GITHUB_TOKEN or SSH credentials |
| Netlify | --deploy=netlify |
NETLIFY_AUTH_TOKEN |
| Vercel | --deploy=vercel |
VERCEL_TOKEN (optional VERCEL_ORG_ID for team scope) |
| FTP | --deploy=ftp |
FTP_USERNAME, FTP_PASSWORD |
| SFTP | --deploy=sftp |
SSH_USERNAME + SSH_PASSWORD or SSH_KEY_FILE |
Example:
CLOUDFLARE_API_TOKEN=... CLOUDFLARE_ACCOUNT_ID=... \
ssg my-blog simple example.com \
--deploy=cloudflare --deploy-project=my-siteDeployment runs after generation and post-processing.
name: Build site
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: spagu/ssg@v1
with:
source: my-blog
template: simple
domain: example.com
clean: "true"
minify: "true"
For a site configured by .ssg.yaml — redirects, workers, variables — point the
action at the file instead; source/template/domain then come from it:
- uses: spagu/ssg@v1
with:
config: .ssg.yaml
deploy: cloudflare
deploy-project: my-siteAll supported inputs and outputs are defined in action.yml. Deployment workflow examples are available in examples/workflows.
Building SSG itself requires Go 1.27.3 or newer — the version the go directive
in go.mod asks for. 1.27.2 carries GO-2026-6809 (crypto/x509), which
ssg reaches through every TLS connection. The floor was 1.26.6 before 1.27, because earlier
Go 1.26 releases contain standard-library vulnerabilities relevant to this
project.
git clone https://github.com/spagu/ssg.git
cd ssg
make allUseful targets — make help lists every one of them:
| Command | Purpose |
|---|---|
make build |
Build build/ssg |
make build-all |
Cross-compile for Linux, macOS, Windows, FreeBSD and OpenBSD |
make install / make uninstall |
Install or remove the binary and its man page |
make test |
Run tests |
make test-coverage |
Run tests and generate coverage |
make lint |
Run static checks |
make security |
Run security scanners |
make golden |
Check generated output against the recorded baseline |
make golden-update |
Re-record the baseline after an intended output change |
make determinism |
Check the worker count does not change the output |
make bench |
Measure build throughput on a synthetic corpus |
make site |
Build this project's own documentation site into .site/ |
make site-watch |
Serve the documentation site and rebuild on change |
make site-edit |
The same, with the browser editor on — edits land on a branch |
make version-check |
Fail if any packaging file drifts from VERSION |
make version-sync |
Propagate VERSION into every file that states it |
make package-all |
Build the DEB, RPM and Snap packages |
make release VERSION=v1.2.3 |
Tag and push a release |
CI holds a 96% statement-coverage floor twice: on the module as a whole and
on every package individually, both computed without the generated protobuf. A
pull request that drops either fails the Test job — see
CONTRIBUTING.md for the exact check and how to run it
locally. BENCH_INCREMENTAL=1 make bench times a one-post edit under
--incremental beside a full build.
| make all | Dependencies, lint, tests and build |
| make install | Install the binary and manual page |
make golden and make determinism guard the two properties the test suite
cannot express as unit tests: that a change did not alter generated output, and
that parallel rendering produces the same site as a sequential build. Both run in
CI. After an intended output change, re-record the baseline with
make golden-update and commit it.
Development workflow and review requirements are in CONTRIBUTING.md. Please follow CODE_OF_CONDUCT.md. Existing contributors are listed in CONTRIBUTORS.md.
| Document | Scope |
|---|---|
| .ssg.yaml.example | Complete configuration reference |
| docs/INSTALL.md | Platform installation guide |
| docs/API_DOCS.md | API documentation from JavaScript/TypeScript code: configuration, doc comments, links, live examples, themes, api.json, agents |
| docs/API_LANGUAGES.md | API docs for Go, PHP and Python: what each reader understands and its limits |
| docs/WEB_STORIES.md | Google Web Stories from posts: what is generated, images, theming, validation |
| docs/PRINT_AND_COOK_MODE.md | The Print / PDF button, the printable recipe card and Cook Mode |
| docs/RESUME.md | A CV from a Schema Resume document: page, structured data, privacy |
| docs/REST_API_DOCS.md | REST API documentation from OpenAPI: pages, the Try it console, checks, theming |
| docs/AUDIO.md | Articles read aloud: the browser button, build-time MP3 through a TTS API, the podcast feed |
| services/tts-server/README.md | Self-hosted TTS API (Docker, Swagger, espeak-ng and Piper voices) that ssg's generic provider talks to |
| docs/MCP.md | MCP server for AI agents: roles, tools, find-then-edit, MDDB search, git write-back |
| docs/RENDER_HOOKS.md | Render hooks: responsive images for content, an external-link policy, wrapping code blocks |
| docs/COMPONENTS.md | Typed content components: the props schema, the call syntax, assets per page, components.json |
| docs/INCREMENTAL.md | --incremental and ssg graph: what a change rebuilds, when a build is full anyway, what it saves |
| docs/EDITING.md | --edit: editing frontmatter in the browser — what a theme marks, where a save goes, the security rules |
| docs/UPGRADING.md | Version-to-version upgrade steps, with a picker for your current version |
| docs/CONTENT.md | Content structure, frontmatter and URL rules |
| docs/MIGRATE.md | ssg migrate: providers, content selection, live --watch --http mode |
| docs/DAEMON.md | ssg daemon: several projects watched by one process, reloaded in place |
| docs/MCP_TRANSPORTS.md | ssg mcp over stdio and Streamable HTTP, and how to expose it safely |
| docs/CONFIGURATION.md | Configuration and advanced feature guide |
| docs/I18N.md | Internationalisation: translations, dictionaries, language routing |
| docs/TAXONOMIES.md | Dynamic taxonomies: definitions, term metadata, archives, helpers |
| docs/EXTERNAL_SOURCES.md | External data: files, HTTP APIs, SQL, CMS imports, cache, security |
| docs/TEMPLATES.md | Theme files, engines and rendering contexts |
| docs/TEMPLATE_HELPERS.md | Go template helper reference |
| docs/IMAGES.md | Build-time image processing |
| docs/DEPLOYMENT.md | Native providers, archives and GitHub Actions |
| docs/STYLES.md | Built-in theme style guide |
| examples/README.md | Example projects and workflows |
| CONTRIBUTING.md | Development and contribution workflow |
| CHANGELOG.md | Release history and migration notes |
| SECURITY.md | Vulnerability reporting policy |
Three posts cover 1.8.60 for the people who maintain client sites: what an agency does between builds, what breaks if I change this and the paragraph you clicked is not in the file.
The project blog also covers the reasoning behind recent MCP work, including smaller context for targeted edits authentication for HTTP MCP, preserving URLs during WordPress migration and deployment-aware local preview.
SSG is distributed under the BSD 3-Clause License.