#static-site #framework #site #static #ssg #web-page #web


A static site generation framework for Rust using Handlebars and Scss

37 releases (6 breaking)

0.7.0 Jun 30, 2023
0.6.1 Jun 27, 2023
0.5.5 Apr 15, 2023
0.4.2 Apr 5, 2023
0.1.3 Nov 9, 2022

#1453 in Web programming

Download history 11/week @ 2024-02-26 2/week @ 2024-03-04 24/week @ 2024-03-11 18/week @ 2024-04-01 340/week @ 2024-04-15

358 downloads per month

MIT license



A static site generation framework for Rust using Handlebars and Scss.

Submit issue here


For a quick start, check out Unreact Template

Add the latest version to your Cargo.toml dependencies

unreact = "*"

Using "dev" feature


  • unreact/dev - Creates local dev server to host files.
  • unreact/watch - Superset of unreact/dev. Also listens for file changes and reloads server.

Run with --dev or -d arguments, for unreact::is_dev() function to return true. Only works if unreact/dev or unreact/watch features are enabled.

# Run with `watch` feature, and dev mode
cargo run --features unreact/watch -- --dev

# Run without `watch` (for a production server)
cargo run

Hot-reloading in dev mode

With the "watch" feature enabled, the dev server will watch for changes in asset folders (templates, styles, and public; Can be changed with config). The client will reload if a change was detected.

NOTE: This will NOT reload the client if Rust files (in src) were changed! (See below)

Watching router in dev mode

This will watch file in src, and reload the program. The client should automatically try to reconnect.

cargo watch -x "run --features unreact/watch -- --dev" -w src -w Cargo.toml

Small Example

Create an site with a single index page

use unreact::prelude::*;

fn main() -> Result<(), Error> {
   // Create the app
   // Using default config, not in dev mode, and an example url
   let mut app = Unreact::new(Config::default(), false, "https://example.com")?;
   // Create an index route
   // This uses the template 'page.hbs' in 'templates/'
   // A json object with a value for 'foo' is passed into the template
   app.index("page", object! { foo: "World!" })?;
   // Compile it!

Larger Example

use unreact::prelude::*;

fn large_example() -> Result<(), Error> {
    // Custom config
    let config = Config {
        strict: true,

    // Run with `is_dev`
    let mut app = Unreact::new(config, is_dev(), "https://example.com")?;

    // Set the global variable 'smiley'
    app.globalize(object! {
        smiley: "(^_^)"

    // Create some routes
    // Note that these methods will never return an error in dev mode. The error will be handled on `app.run()`
    app.index("page", object! {message: "World!"})?
        .not_found("404", object! {})?
        .route_raw("hello", "this is my hello page".to_string())
        .route("article", "other/article", object! {})?;

    // Compiles normally, or opens a dev server and listens if in dev mode

Automatic Compilation with Github Pages

In .github/workflows/build.yaml:

name: Build

    # Triggers the workflow on push or pull request events but only for the "main" branch
        branches: ["main"]
        branches: ["main"]

        runs-on: ubuntu-latest

            # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
            - name: Checkout 🛎️
              uses: actions/checkout@v3

            # Run compilation script with Rust
            - name: Build 🔧
              run: cargo run

            # Push changes with plugin
            - name: Deploy 🚀
              uses: JamesIves/github-pages-deploy-action@v4
                  # This must be the build directory
                  folder: ./build

Unreact Icon


~300K SLoC