sppl
sppl (supple) — embed static Svelte apps into your Rust binary.
A Svelte/SvelteKit app, built with adapter-static, is just a tree of
HTML/CSS/JS files. sppl bakes that tree into your Rust binary at compile
time and hands it to your web framework as a single Router (or a generic
asset lookup) that already knows how to:
- serve every file with the correct
Content-Type, - resolve SvelteKit
adapter-static<route>.htmlfiles for prerendered routes, - fall back to
index.htmlfor client-side SPA routes, - store one gzipped copy of each compressible asset and serve it as-is
with
Content-Encoding: gzip, regardless ofAccept-Encoding(modern clients all decompress transparently); flipRouterConfig::never_decompresstofalseto opt back into on-the-fly decompression for legacy clients, - ship as a single self-contained binary — no extra files to deploy.
https://github.com/user-attachments/assets/010351d4-e685-4aa2-9c9e-3d1294adb904
Compression
Run sppl::build::gzip_assets from your
build.rs once, after your Svelte build, and sppl takes care of the rest
at request time. Because only the gzipped bytes live in the binary, the
default request path is zero-CPU: every response is the stored gzipped
bytes, sent with Content-Encoding: gzip. Modern clients (browsers,
curl --compressed, every common HTTP library) decompress transparently;
the rare client that genuinely can't accept gzip can be served via
router_with(RouterConfig { never_decompress: false }), which restores
on-the-fly decompression with [flate2].
Layout
crates/sppl/ # the library
examples/app/ # SvelteKit + adapter-static demo (built with deno)
examples/server/ # axum server that embeds the demo
Usage
# Cargo.toml
[]
= "0.0.3"
= "0.7"
= { = "1", = ["macros", "rt-multi-thread"] }
use ;
;
async
If you'd rather wire things up yourself, sppl::resolve::<App>(path) returns
the matching (path, EmbeddedFile) using the same lookup rules and is
framework-agnostic.
Running the example
# from the repo root — the server's build.rs runs `deno task build` for you:
# …or build the svelte app yourself:
SPPL_SKIP_SVELTE_BUILD=1
Set SPPL_SKIP_SVELTE_BUILD=1 to skip the build-script step (useful in CI
when the build is produced upstream).
Then open http://127.0.0.1:3000.
Testing
Covers accepts_gzip header parsing and the resolve lookup rules
(exact path, .html extension, trailing-slash index.html, SPA fallback,
and .gz preference). Fixture files live under
crates/sppl/tests/fixtures/static/.
Requirements
- Rust (1.75+ recommended) —
cargo - Deno 2.x — drives the SvelteKit build via
deno task
License
MIT