# 100. Getting started

**For:** app developers. Twenty minutes to a page rendering from Rust.

## What you need

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

```
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:

```
fsr --help
```

## Scaffold an application

```
fsr new storefront
```

That writes a project directory: a `config/app.toml`, an `app/` holding `routes/`, `src/`, `styles/` and an `importmap.json`. There is no `package.json` and no `node_modules`. The project never gets either.

```
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
    types/@snapfire/
```

It does not add a framework. The import map names the client, its standard library and its store. The pages are written against `@snapfire/fsr-authoring/template`, which types the placements without React. A bare application is the default because most pages do not need one.

Ask for React with `--with`, which vendors it and adds the four import-map entries:

```
fsr new storefront --with react
```

`fsr use <app> react` does the same to a project that already exists. Both take `vue`, `elements`, `htmx` and `tera` as well. The scaffold prints the line for you:

```
next      fsr use storefront/app react      # only if the application wants React; also vue, elements, htmx or tera
```

## Run it

```
fsr dev storefront/app
```

The host boots, prints what needs attention and serves on the address in `config/app.toml`. `fsr dev storefront/app --verbose` prints the whole report, which is worth reading: 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 has usually already said so.

Edit `app/routes/page.tsx` and the browser reloads.

## Commands

| 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 use <app> <direction>` | Give the app react, vue, elements, htmx or tera. |
| `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, `paths` included. |
| `fsr doctor <app>` | Check a project or a deploy tree for what will bite in production. |

## Where things live

`config/app.toml` holds the 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. The report tells you what the host inferred.

It is the first of several files the host reads, in this order:

| File | When |
|---|---|
| `app.toml` | always |
| `<release_env>` | `RELEASE_ENV` |
| `<app_env>` | `APP_ENV` |
| `<region>` | `APP_REGION` |
| `<app_env>-<region>` | both |
| `bundle.toml` | in a deploy tree, written by `fsr bundle` |

Each is looked for as `.toml`, then `.yaml`. A missing file is normal: a checkout with only `app.toml` runs. A deployment adds its own overlay without touching the base. The boot report lists the files it actually read, in order.

`app/importmap.json` is the allowlist of bare specifiers. The compiler is given it as `--import-map`. 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.

## Try it

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 that line before the browser ever sees the page. This is the contract described in [What SnapFire FSR is](https://snapfirers.com/fsr/docs/001-what-snapfire-fsr-is.md).
