Manual contentsGetting StartedBrowse 103 chapters
Manual 5 min read

Development

The day-to-day Suprnova loop is one command: suprnova serve. It runs the Rust backend, the Vite frontend, and a TypeScript-types regenerator in a single process, each watching the right files. This chapter covers the dev server, how the hot-reload pieces fit together, and the commands you'll reach for daily. For first-time setup see Installation; for the directory tour see Directory Structure.

The dev server

From a scaffolded project's root:

suprnova serve

The CLI prints two URLs and then a continuous stream of prefixed output from each child process:

Backend  http://127.0.0.1:8765
Frontend http://127.0.0.1:5765

[backend]  Compiling links v0.1.0
[backend]  Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.21s
[backend]  Running `target/debug/links`
[frontend] VITE v6.0.1  ready in 312 ms
[frontend]   ➜  Local:   http://localhost:5765/
[types]    Watching for Rust file changes to regenerate types

You hit the backend URL (127.0.0.1:8765). Vite serves your JS/CSS through Inertia's dev integration - you don't visit :5765 directly. Press Ctrl+C once and the CLI shuts both children down cleanly.

Flags

Flag Default What it does
-p, --port <N> 8765 Backend port
--frontend-port <N> 5765 Vite port
--backend-only off Skip the Vite child (API-only work)
--frontend-only off Skip the backend child (component work against a running backend elsewhere)
--skip-types off Skip the TypeScript-type generator + its watcher

The same ports can be set in .env via SERVER_PORT and VITE_PORT. A flag on the command line wins over .env.

What it pre-flights

Before spawning anything, suprnova serve:

  1. Checks you're in a project. Aborts with a clear error if there's no Cargo.toml (or no frontend/ when running the frontend).
  2. Generates TypeScript types once. Scans src/ for #[derive(InertiaProps)] and writes frontend/src/types/inertia-props.ts. Skipped by --skip-types or --frontend-only.
  3. Installs cargo-watch if missing. First run on a new machine runs cargo install cargo-watch for you, then continues.
  4. Runs npm install if frontend/node_modules is missing. No manual install step on a fresh clone.

Hot reload

Three watchers run concurrently inside suprnova serve:

  • cargo watch -x 'run --bin <pkg>' drives the backend. Any .rs change under the project triggers a recompile and an in-process restart. Compile errors print to the [backend] stream and the previous binary stays up until the next successful build.
  • Vite drives the frontend. Component, style, and asset edits hot-module-replace into the open browser tab without a full reload.
  • notify-based type watcher reruns the InertiaProps scanner whenever a .rs file changes. It debounces at 500ms so a burst of saves regenerates inertia-props.ts once. Output appears under the [types] prefix.

That third one is the bit you don't have to think about: rename a field on a #[derive(InertiaProps)] struct and the matching TypeScript interface follows on the next save. The Svelte/React/Vue page picks the new type up immediately. No suprnova generate-types invocation needed during normal dev.

Why Suprnova diverges

Most Rust web stacks make hot reload your problem - pick your own file watcher, write your own restart wrapper, run Vite in a separate terminal. Most Laravel stacks make TypeScript types your problem - declare them in two places (PHP and TS) and keep them in sync. suprnova serve runs both watchers, plus the type generator that keeps your frontend types honest, as one supervised process. The Tokio runtime makes "many things at once" cheap enough that a dev loop can spend it freely.

Day-to-day commands

The handful you'll run hourly:

suprnova serve                    # start dev (backend + Vite + type watcher)
suprnova make:controller orders   # scaffold a controller
suprnova make:migration add_idx   # scaffold a migration
suprnova db:sync                  # run migrations, regenerate SeaORM entities
suprnova migrate:status           # see what's applied
suprnova migrate:fresh            # drop tables + re-run from scratch
suprnova key:generate --show      # rotate APP_KEY
cargo run --bin console <cmd>     # any `#[command]`-annotated console handler
cargo test                        # run the test suite

db:sync is the dev shortcut for "migration + entity regen in one step." In production you use plain suprnova migrate because you don't want regeneration to happen on a release box. The full generator surface is in Code Generators and the migration verbs are in Migrations.

Debugging

Logging

Suprnova uses tracing end-to-end. Filter what gets printed with LOG_LEVEL (the same syntax as tracing-subscriber's EnvFilter):

# Verbose framework output
LOG_LEVEL=debug suprnova serve

# Quiet hyper but verbose your crate
LOG_LEVEL=info,my_app=debug,hyper=warn suprnova serve

Output format is controlled by LOG_FORMAT (pretty for human-readable, json for machine-parseable). The dev default is pretty. See Observability for the full logging surface.

SQL queries

Turn on per-query logging with one env var:

DB_LOGGING=true

This routes every SeaORM query through tracing at info so you can see exactly what's executing. Leave it off in production unless you're chasing a specific slow query - the volume gets noisy fast.

Backtraces

Standard Rust:

RUST_BACKTRACE=1 suprnova serve

A panic in a handler is caught and turned into a structured 500 response; the backtrace lands in your logs without taking the server down. See Error Model for how that contract works.

Tests in the loop

cargo test                        # whole workspace
cargo test -p my_app              # just your app crate
cargo test some_test_name         # filter by name
cargo test -- --nocapture         # show println!/tracing output

Test execution is plain Cargo. The framework-side helpers (#[suprnova_test], TestDatabase, expect!, fakes for Mail/Queue/ Storage/etc.) are documented in Testing and Database Testing. They run under the same cargo test you already know.

Working with the SSR worker

If your app uses Inertia server-side rendering, you'll want the SSR worker alongside suprnova serve during dev:

# Terminal 1
suprnova serve

# Terminal 2
suprnova ssr:start

ssr:start runs the bundled SSR worker under Node, Bun, or Deno (--runtime). ssr:check verifies a running worker is reachable. Both are documented under the frontend chapter - see Frontend.

When something looks wrong

A short triage list for the most common dev-loop hiccups:

  • Port already in use. Another suprnova serve is still up, or a prior backend wedged. lsof -i :8765 to find it, or just pass --port 8001.
  • cargo-watch keeps recompiling. Some editor is rewriting files on save (formatters, linters with autofix). Disable on-save format for the project, or scope your watcher with CARGO_WATCH_IGNORE patterns.
  • TypeScript types not updating. Either --skip-types was passed, or the watcher tripped over a .rs parse error. Look at the [types] lines - it prints a warning and continues rather than failing the whole serve.
  • Vite errors but the backend is fine. Run npm install in frontend/ once (the CLI does this on first serve, but if you blow away node_modules it won't redo it until that directory is missing again on a fresh start).

Anything else, the Errors chapter covers deeper triage patterns.

Next