Website · Discussions · Issues · Installation · Contributing · Migrating
fugo is a static site generator written in Rust. It began as a fork of another static site generator, written in Go, and was rewritten in Rust (Origin and attribution): it keeps that generator's project layout, content model and configuration keys, and its tests compare its output with the Go implementation's, but its layouts are Tera templates. With its templating system and fast asset pipelines, fugo renders a complete site in seconds, often less.
With its multilingual support and taxonomy system, fugo suits:
- Corporate, government, nonprofit, education, news, event, and project sites
- Documentation sites
- Image portfolios
- Landing pages
- Business, professional, and personal blogs
- Resumes and CVs
Use fugo's built-in web server (fugo server) during development to instantly see changes to content, structure, behavior, and presentation. Then deploy the site to your host, or push changes to your Git provider for automated builds and deployment.
Fugo's fast asset pipelines include:
- Image processing – Convert, resize, crop, rotate, adjust colors, apply filters, overlay text and images, and extract EXIF data
- JavaScript bundling – Transpile TypeScript and JSX to JavaScript, bundle, tree shake, minify, create source maps, and perform SRI hashing.
- Sass processing – Transpile Sass to CSS, bundle, tree shake, minify (with vendor prefixes for your browserslist), purge unused rules per page, create source maps, and perform SRI hashing
- npm packages – Install the packages of
package.jsonfor bundling and Sass imports, without Node.js or npm
Fugo reads its configuration from config.toml (or config.yaml, config.yml, config.json), with the Go build's configuration keys and project layout, and uses its own names throughout: the build template object, config.toml and .env files. Its templates are Tera 2 with the Go build's layout names (those of v0.146 and later) instead of Go templates; Upgrading from the Go build says what else changed with v1.0.0. The known differences from the Go implementation are listed in §7 of docs/rust-port/HANDOFF.md.
fugo's documentation is the site in docs/, built with fugo: getting started, content management, templates, asset pipelines, configuration, a generated reference of every template function, object and command, and a guide for migrating from Go templates. See Documentation.
Minified CSS (--minify, resources.Minify) is prepared for the browsers of the project's browserslist configuration (.browserslistrc, a browserslist file or the browserslist key of package.json; the section named like the environment applies, else the default queries): vendor prefixes those browsers need are added, newer syntax they lack is lowered and prefixes none of them needs are removed, as autoprefixer does, so PostCSS is not needed for that. A style rule declaring a property twice (a value and its fallback) is kept as written. Without a browserslist configuration, prefixes stay as written.
purge_css cuts a stylesheet down, for each page, to the rules that page uses (its elements' tags, classes and ids, the words of its scripts), with PurgeCSS's safelist, greedy, blocklist, content and variables options: <style>{{ get_asset(path="main.scss") | to_css | minify | purge_css(content=[get_asset(path="js/main.js")]) }}</style>. It needs no stats file and no PostCSS, and pages are written as they are rendered. See template-api.md.
Download the archive for your platform from the releases page. Releases are tagged v<version> and start at v1.0.0, the Rust implementation named fugo; the releases of the former Go implementation (v0.148.2 and earlier, under the project's former name) are no longer published. The archives are named fugo_<version>_<os>-<arch>.tar.gz (.zip for Windows), and hold the fugo binary, README.md, LICENSE, NOTICE, THIRD_PARTY_NOTICES.txt, PROVENANCE.md and THIRD_PARTY/:
linux-amd64,linux-arm64(glibc 2.35 or later)darwin-amd64,darwin-arm64windows-amd64
Check a download with sha256sum -c fugo_<version>_checksums.txt --ignore-missing (on macOS: shasum -a 256 -c fugo_<version>_checksums.txt --ignore-missing), then put fugo on your PATH:
fugo version
fugo -s <site> # build into the publish directory
fugo server -s <site> # development server with live reload
The commands and flags (the Go build's, in kebab case, with its camelCase spellings as aliases) are listed in crates/cli/README.md.
The container image ghcr.io/getfugo/fugo (linux/amd64, linux/arm64) holds each release's Linux binary on Debian slim, with git, ca-certificates and tzdata. It is tagged <version>, <major>.<minor>, <major> and latest; its entry point is fugo and its working directory /src, so mount the site there (--user makes the files written yours on Linux):
docker run --rm -v "$PWD:/src" --user "$(id -u):$(id -g)" ghcr.io/getfugo/fugo --minify
docker run --rm -v "$PWD:/src" --user "$(id -u):$(id -g)" -p 1313:1313 ghcr.io/getfugo/fugo server --bind 0.0.0.0
v1.0.0 replaces the Go build, under a new name and its own version numbers. What a site or a script may have to change:
-
The name is fugo, and the source code avoids the program's name: the binary is
fugo(fugo versionprintsfugo v<version> …), the release archives arefugo_<version>_…, and the repository is getfugo/fugo. The names a site uses carry no program name: the configuration file isconfig.toml(orconfig.yaml,config.yml,config.json; no file named after a program is read), the template object isbuild(build.environment,build.is_server,build.generator; it replaces the Go build's objects named after the program), and Sass imports the template's variables asbuild:vars. Settings are not read from environment variables: they come from the configuration files and the command line. The environment comes from--environment; secrets for templates go in the project's.envfiles (get_env), andsecurity.funcs.getenvallows^FUGO_by default. -
No PostCSS, Babel or Tailwind CSS pipeline, and no stats file (
css.PostCSS,js.Babel,css.TailwindCSS,[build.buildStats]): fugo runs no external programs (External tools).[build] buildStatsandwriteStatsprint a warning and are ignored;[security.exec]is accepted and has no effect. -
Layouts are Tera 2 templates, not Go templates, with the layout names of v0.146 and later (
home.html,single.html,_partials/,_shortcodes/,_markup/). A layout with Go template syntax or a legacy name is an error that says what to change. docs/rust-port/template-api.md lists every function, filter and test with its Go-template name and how Go-template idioms translate;fugo templates check -s <site>checks a site's templates against it. Output is escaped by output format (HTML and XML), not by context as in Go'shtml/template: in<script>usejsonify | safe, in query stringsurlencode. -
Commands and flags:
build(also with no command),server,templates check,configandversion; the Go build'senv,new,mod,deploy,list,gen,convert,import,release,server trustandconfig mounts, and thecompletionandhelpcommands are not available (--helpprints the help). Of the Go build's flags, those crates/cli/README.md lists are accepted (--noChmodand--noTimesincluded); the logging and housekeeping flags (--gc,--logLevel,--noBuildLock,--printI18nWarnings,--printPathWarnings,--printUnusedTemplates,--templateMetrics,--templateMetricsHints) and the server's--disableFastRenderand--disableBrowserErrorare not, so drop them from command lines such as--gc --minify. Boolean flags take an explicit value as before (--minify=false,--buildDrafts=true), and=falseoverrides the configuration as before (-D=falseagainstbuildDrafts = true).--quiet(also-qin fugo) only hides the build summary: warnings and errors are still printed, where the Go build discarded them too. Another, such as--enableGitInfo,--contentDir,--disableKinds,--panicOnWarningor the build's-w/--watch, is an error. As before, flags may come before or after the command (fugo -s <site> server), and every command takes the persistent flags (-s,-d,-e,--config,--themesDir,--clock,--quiet,-M).--confignames one file, not a comma-separated list, and--configDiris an error: the configuration is one file (see Configuration below). A build prints one summary line (pages … | files … | … | static files …, thenTotal in N ms) instead of the Go build's per-language statistics table.configprints fugo's resolved configuration model (snake_case fields, one entry per site undersites, the merged user keys underraw), not the Go build's lower-cased keys (baseurl,publishdir, …), so a script that reads its output must change; it prints JSON by default (the Go build: TOML) and takes--format jsonortoml, notyaml,--langor--printZero. A usage error exits with 2 (the Go build exited with 1 on every error), and error messages start witherror:(usage) orERROR(build) instead ofError:. -
serverrenders into memory by default. The Go build wrote the site to the publish directory and served it from there (-M/--renderToMemoryrendered into memory). For the Go behaviour add--render-to-disk, a flag of fugo, not of the Go build;-d/--destinationwithout it is an error. -
Modules are not downloaded (no
go.modresolution): themes and modules come from the themes directory,_vendoror an absolute path. -
js.Buildbundles in process with rolldown (the Go build linked esbuild 0.25.6): nothing to install, and the options are the same. Scripts behave as before, but their bytes differ, so fingerprinted names,Data.Integrityand source maps change. Other visible differences: the IIFE wrapper is(function() { … })();; legal comments stay where they are instead of moving to the end; error texts are rolldown's, except unresolved imports (Could not resolve "x") and thees5target's errors, which keep esbuild's wording and positions. As with esbuild, TC39 decorators are lowered,target: es5checks and lowers the bundle, and CSS imported from scripts is dropped (local-cssmodules give their class names). Sass is compiled in process with dart-sass semantics, whatevertranspilersays. -
The Docker images of the Go build, published under the former name, are no longer updated; they stay at the last Go build. fugo's image is
ghcr.io/getfugo/fugo(Installation): its entry point isfugo(docker run … ghcr.io/getfugo/fugo server, not… <image> <program> server), it runs as the user 1000 and has no Node.js, Dart Sass or image tools, which fugo does not use. -
The website getfugo.github.io is now fugo's documentation,
docs/, a site with its own theme built by fugo (tools/docs/build.sh): the repository getfugo/getfugo.github.io publishes it daily from the latest release, with the benchmark charts. The Go build's documentation site is kept as the test fixturetestdata/legacy-docs/:tools/legacy-docs/build.shbuilds it with fugo (Tera layouts insites/docs), and gate A-D3 checks every page of that build against the published one.
Prerequisites to build fugo from source:
- Rust 1.99 or later (
rust-versioninCargo.toml, which CI builds with) - A C compiler (libwebp and ring are compiled with the
cccrate)
Build fugo:
cargo build --release --locked -p ssg-cli
The binary is target/release/fugo. DEVELOPMENT.md describes the workspace, its tests and the CI and release workflow.
None: every asset pipeline runs in process, and fugo runs no programs (only git, when enableGitInfo is on). It installs the npm packages of a project's package.json itself, for js_build and Sass imports. There is no PostCSS, Babel or Tailwind CSS pipeline: minify adds the vendor prefixes for the project's browserslist, purge_css purges per page, js_build compiles TypeScript and JSX and lowers modern JavaScript for the browser targets, and Tailwind's own CLI runs next to fugo (docs/content/asset-pipelines/tailwind-css.md).
- docs/: fugo's documentation site. Build it with
tools/docs/build.sh(or preview it withfugo server -s docs);docs/content/is readable as Markdown too. - crates/cli/README.md: the commands and flags.
- docs/rust-port/template-api.md: every template function, filter and test, with its Go-template name and how Go-template idioms translate.
- Upgrading from the Go build, above, and the known differences from the Go implementation in §7 of docs/rust-port/HANDOFF.md.
- The website getfugo.github.io: this documentation (
docs/) for the latest release, and the benchmarks.
Please do not use the issue tracker for questions or troubleshooting: ask in fugo's discussions. Use the issue tracker for defects of fugo and for feature requests. Report only fugo issues here.
You can contribute to fugo by answering questions in the discussions, reporting and fixing bugs, improving the documentation and proposing features. Before you work on a feature, open an issue with the feature request template so that it can be discussed first. The Contribution Guide covers the code guidelines, the commit messages and the checks a pull request must pass.
The code is the Cargo workspace at the repository root: DEVELOPMENT.md has the layout, the commands and the CI and release workflow, and docs/rust-port/HANDOFF.md the crate map, the parity gates, the deviations from the Go implementation and the open items.
fugo began as a fork of another static site generator and was rewritten in Rust: v0.148.2 and earlier were that generator's Go code with the fork's changes, released under the project's former name, and v1.0.0 and later are the Rust rewrite. Parts of fugo derive from the original project, which is licensed under the Apache License 2.0: templates rewritten from its embedded templates, its LiveReload plugin, behaviour transcribed from its Go sources, and its test data and documentation used as test fixtures. Each of these is listed in PROVENANCE.md, and NOTICE carries the attribution of the derived material.
fugo is developed independently: it is not affiliated with, sponsored by or endorsed by the original project, its maintainers or its sponsors.
fugo is licensed under the Apache License 2.0; NOTICE holds the attribution notices of the work it derives from. It stands on the shoulders of great open source libraries. The Rust crates it uses are declared in Cargo.toml ([workspace.dependencies], locked by Cargo.lock); material taken from other projects is listed in PROVENANCE.md, with licences cargo cannot see in THIRD_PARTY. The THIRD_PARTY_NOTICES.txt of each release archive holds the licences of the crates linked into that binary.
