Your First App

  1. Scaffold a project
  2. Look around
  3. Create the database
  4. Serve it
  5. See every route
  6. Iterate with xr dev
  7. Generate something
  8. Next

Scaffold a project

From anywhere - every Larust crate is published to crates.io, so xr new needs no checkout nearby by default:

xr new blog-tutorial --auth

A few things about that command:

  • No workspace checkout required. The generated Cargo.toml depends on the published larust-* crates directly (version = "..."), not a local path - xr new works the same whether you’re inside a cloned Larust checkout or in a completely unrelated directory. Scaffolding inside your checkout under examples/ is still convenient if you’re actively developing Larust itself and want your test app to build against local, uncommitted framework changes instead of the published version - add --workspace <path-to-the-checkout> for that, and note the workspace root’s own Cargo.toml already lists examples/* as a member glob, so an app scaffolded there needs no extra configuration to be picked up by cargo build --workspace from the checkout root.
  • Omit the path (xr new with nothing else) to get an interactive wizard instead - it asks for the project directory, whether to include auth, and which optional larust-support features you want (see Optional Features for the full, current list), one at a time, rather than requiring you to already know every flag.
  • --auth scaffolds a User model plus register/login/logout, so you get a real authenticated flow to look at rather than an empty shell. Leave it off for a minimal app with no auth at all.

You’ll see:

Created new Larust application at blog-tutorial

Look around

cd blog-tutorial

A --auth scaffold ships a small working blog: Post/Comment/User models, a PostController with the full create/show/edit flow, real register/login/logout routes, and Blade-flavored templates for all of it. See Project Structure for what every file is.

Create the database

cargo run -- migrate
Migrated: 0001_create_posts_table.sql
Migrated: 0002_create_users_table.sql
Migrated: 0003_create_comments_table.sql

This runs every .sql file under database/migrations/ in order against a fresh SQLite database (the default DB_CONNECTION) at the path your .env names - no separate database server to install or configure for local dev. See Migrations & the Query Builder for MySQL/Postgres/SQL Server instead.

Serve it

cargo run

Or, if you have xr installed (see Iterate with xr dev), you can run it with:

xr dev

Visit http://127.0.0.1:34187 (Larust’s default APP_PORT - not 8000, deliberately; see the FAQ). Register an account, write a post, and you’re looking at a real, working Larust app.

See every route

From another terminal, in the same directory:

xr route:list
GET     /                        
GET     /posts                   posts.index
GET     /posts/{post}            posts.show
GET     /__larust_wire/runtime.js 
POST    /__larust_wire/{component_id} 
GET     /__larust_spa/runtime.js 
GET     /__larust_reverb/runtime.js 
GET     /__larust_reverb/{channel} 
GET     /posts/create            posts.create
POST    /posts                   posts.store
POST    /posts/{post}/comments   posts.comments.store
GET     /register                register
POST    /register                register.store
GET     /login                   login
POST    /login                   login.store
POST    /logout                  logout

The unnamed /__larust_* routes are framework-internal - the wire component runtime script and its action endpoint, the SPA-mode runtime script, and the live-broadcast WebSocket runtime/endpoint. They’re always registered; you’ll never call them directly.

Iterate with xr dev

Stop cargo run and use the dev server instead:

../../target/debug/xr.exe dev     # or just `xr dev` if it's on PATH

xr dev binds the port itself immediately (serving a “building…” page if the very first build hasn’t finished yet), then rebuilds and hot-swaps the running process on every save - with zero dropped requests, not just a fast restart - and pushes a live-reload signal to any open browser tab over SSE so it refreshes automatically once the new build is ready. A build that fails leaves the last known-good version running and shows you the real compiler error on the page, instead of taking the site down.

Each rebuild is a plain cargo build, not a from-scratch recompile - it gets Cargo’s own incremental compilation for free, the same as running cargo build by hand twice in a row. Editing your own app code (a controller, a route, a template) only recompiles your app’s one crate, typically a few seconds to under a minute depending on the app; the much longer first build (and any rebuild after editing a framework crate itself, if you’re working on Larust’s own source) recompiles the full dependency tree instead, since that’s genuinely what changed. There’s no separate “hot reload without recompiling” mode - Rust doesn’t support patching a running compiled binary, so the fastest possible loop for changed app code is exactly what happens today: recompile that one crate, then swap the process with zero dropped requests.

Generate something

xr make:controller CommentController --resource
xr make:model Category --migration
xr make:policy Category

See the CLI reference for every make:* generator and every other subcommand.

Next

Project Structure walks through what every generated file does, or jump straight into The Basics to start building.