sailfish

A simple, small, and extremely fast compiled template engine for Rust, inspired by EJS syntax.

Library
Cargo
v0.11.4
990stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
78/100Good
Development Activity84
Maintenance72
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
81/100Excellent
Architecture85
Code Quality88
Innovation80
Learning Curve70

Sailfish is a Rust template engine that compiles .stpl template files into native Rust code at build time via a derive macro, rather than interpreting templates at runtime. Templates use an EJS-inspired syntax (<% %> for statements, <%= %> for escaped output, <%- %> for raw output) and can directly reference struct fields and call methods on self, giving full compile-time type checking of template expressions.

The project is organized as a workspace of focused crates: sailfish (the public API and runtime, including a SIMD-accelerated HTML escaper with AVX2/SSE2 code paths and a scalar fallback), sailfish-compiler (parser, analyzer, optimizer, and code generator shared by the proc-macro crates), and sailfish-macros (the #[derive(Template)], TemplateOnce, TemplateMut, and TemplateSimple proc-macros). This split keeps the runtime dependency surface minimal — fewer than 15 crates in total — while the heavier compiler logic only runs at build time.

What You Get

  • Four derive macros (Template, TemplateOnce, TemplateMut, TemplateSimple) covering by-reference, consuming, mutable, and self-less rendering styles
  • A runtime module exposing Buffer, the Render trait for custom types, and a SizeHint mechanism that pre-allocates output buffers based on previously observed render sizes
  • SIMD-accelerated HTML escaping with dedicated AVX2 and SSE2 code paths plus a portable fallback, selected automatically at compile/runtime
  • Built-in filters (including an optional json filter behind a feature flag) and support for including one template from another
  • Optional sailfish.toml configuration file support (via the config feature) for customizing template directories and escaping behavior
  • Compile-time error messages that point at the offending line in the original .stpl file, not the generated Rust code

Common Use Cases

  • Server-rendered HTML views in Rust web frameworks such as Actix Web, where response bodies are built from struct data with zero runtime template parsing
  • High-throughput services where template rendering is on the hot path and interpreted engines (Handlebars, Tera) introduce measurable overhead
  • Generating static site output or documentation pages ahead of time, using TemplateOnce for one-shot rendering
  • Email or report generation where structured data needs to be turned into HTML with predictable, type-checked output
  • Projects that want compile-time guarantees that referenced fields and methods actually exist on the template’s context struct

Under The Hood

Architecture The workspace separates concerns cleanly across four crates: sailfish (public traits Template/TemplateOnce/TemplateMut/TemplateSimple in sailfish/src/lib.rs plus the runtime module), sailfish-compiler (the actual template pipeline: parser.rs tokenizes .stpl syntax, analyzer.rs and optimizer.rs transform the parsed tree, translator.rs emits Rust source, and procmacro.rs wires this into the four derive entry points), sailfish-macros (a thin proc_macro_derive shim that forwards into sailfish-compiler::procmacro), and sailfish-tests/integration-tests (a dedicated workspace member for end-to-end and compile-fail testing). Because template compilation happens entirely inside sailfish-compiler at macro-expansion time, the runtime crate (sailfish) stays free of parsing/codegen dependencies, and changing the compiler internals cannot affect the rendering hot path directly — only the code it generates.

Tech Stack The core sailfish crate targets Rust edition 2024 (minimum supported Rust version 1.89) and keeps runtime dependencies minimal: itoap and ryu for fast integer/float formatting, with serde/serde_json gated behind an optional json feature. sailfish-macros builds on proc-macro2, syn, and quote, standard tooling for Rust procedural macros, and forwards derive logic into sailfish-compiler. A build-dependencies entry on version_check lets the crate adapt codegen to the detected rustc version. The project ships Cargo feature flags (config, derive, json, perf-inline, hermetic) to let consumers opt in or out of proc-macro and configuration-file support.

Code Quality The project has a dedicated sailfish-tests/integration-tests workspace crate with both positive tests (template.rs, template_simple.rs, config.rs, compile.rs) and a tests/fails/ directory of trybuild-style compile-fail fixtures with .stderr golden files, verifying that malformed templates (unclosed delimiters, missing semicolons, unbalanced braces, unknown options) produce the intended compiler diagnostics. Error handling is explicit and typed: sailfish-compiler/src/error.rs defines a non-exhaustive ErrorKind enum with From conversions from fmt::Error, io::Error, and syn::Error, and an Error struct that tracks source file, offending source text, and byte offset for precise diagnostics. CI (.github/workflows/test.yml) runs the test suite across Linux, macOS, and Windows on stable, beta, and nightly toolchains plus a 32-bit target, and a separate coverage.yml workflow tracks code coverage — indicating a mature, cross-platform-tested codebase.

What Makes It Unique Unlike interpreted Rust template engines, Sailfish compiles templates to native Rust code ahead of time via proc-macros, so template logic gets full compiler type-checking and there is no runtime template-parsing cost — this is the basis for its consistently strong results in the community template-benchmarks-rs suite. It further differentiates itself with hand-written SIMD HTML-escaping routines (separate AVX2 and SSE2 implementations with automatic fallback), a level of low-level performance engineering uncommon among templating libraries in any language.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search