Getting started
What you need
Rust, and nothing else. The build installs the two binaries it uses.
cargo install snapfire_compiler
cargo install snapfire_fsr_clisnapfirec is the compiler that bundles TypeScript. fsr is the command you drive everything else with. Check them:
fsr --helpScaffold an application
fsr new storefrontThat writes a project directory: a config/app.toml, an app/ holding routes/, src/, styles/ and an importmap.json, and a vendored copy of React under app/vendor/. There is no package.json and no node_modules, and there will not be one.
storefront/
config/app.toml
app/
importmap.json
routes/
layout.tsx
page.tsx
page.loader.ts
not-found.tsx
error.tsx
src/main.ts
styles/app.css
vendor/
types/Run it
fsr dev storefront/appThe host boots, prints a report of everything it found and serves on the address in config/app.toml. The report is worth reading every time: it lists each route with its pattern, each loader with whether it lowered, each component with whether the server can render it and every static root. When something does not work, the report usually already said so.
Edit app/routes/page.tsx and the browser reloads.
The commands you will actually use
| Command | What it does |
|---|---|
fsr dev <app> | Build, serve and watch. The development loop. |
fsr build <app> | Build once, write generated/ and dist/. |
fsr check <app> | Typecheck without emitting. |
fsr serve <app> | Serve what is already built, no watcher. |
fsr test <app> | Run the application's tests, without a browser. |
fsr add <app> <pkg@version> | Vendor a dependency and add its import-map entry. |
fsr types <app> | Fetch the type declarations the import map implies. |
fsr bundle <app> --out <dir> | Write the deploy tree. |
fsr prerender <app> | Render every eligible route to a file. |
Where things live
config/app.toml is the whole configuration: what to listen on, what the document's title is, how sessions are keyed, which service clients exist and where the static roots are. Most of it has a default, and the report tells you what the host inferred.
app/importmap.json is the allowlist of bare specifiers. The compiler is given it as --import-map, and an import with no entry fails the build rather than shipping a broken module. fsr add is what writes entries.
app/generated/ is written by every build and read by nothing you edit. It holds the plan the host serves, the route types your loaders constrain themselves against and the props types your pages import.
The lab
Change page.loader.ts to return a second field, then read it in page.tsx. Now delete the field from the loader but leave the page reading it: the build fails, on the line, before the browser ever sees the page. That is the contract in What SnapFire FSR is doing its job.