Basics · for app developers

Getting started

What you need

Rust, and nothing else. The build installs the two binaries it uses.

text
cargo install snapfire_compiler
cargo install snapfire_fsr_cli

snapfirec is the compiler that bundles TypeScript. fsr is the command you drive everything else with. Check them:

text
fsr --help

Scaffold an application

text
fsr new storefront

That 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.

text
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

text
fsr dev storefront/app

The 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

CommandWhat 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.

Built with SnapFire FSR. Pure Rust runtime, zero Node.js on the server.