We will assume that you have already initialized a project. If you haven’t, you should check out our quick start section.

While deploying to production is easy with Shuttle, running your project locally is useful for development. To start your project on your local system, while in your project directory, run:

cargo shuttle run

Local runs with databases

If your project relies on a database resource, it will default to starting a Docker container for that database. If you’d like to opt out of this behavior and rather supply your own database URI, simply pass it in as an argument to your resource. This argument also supports insertion of secrets from Secrets.toml with string interpolation:

async fn tide(
        local_uri = "postgres://postgres:{secrets.PASSWORD}@localhost:16695/postgres"
    )] pool: PgPool,
) -> ShuttleTide<MyState> { ... }

Expose your application to your local network

If you’d like to expose your application to you local network, for example if you’re serving a static website and you’d like to open it on your phone, simply pass in the --external flag:

cargo shuttle run --external

This will bind your local application to, and you will now be able to connect to it using your computer’s local IP. If you’d also like to change the port, you can do so with the --port argument:

cargo shuttle run --external --port 8123
You may need to open the port your app is started on in your firewall.

Development Tips

Here are some small tips and tricks to boost your productivity when developing locally.

Live reload backend with cargo watch

To live reload your Shuttle app when you save a file, you can use cargo-watch:

# This will e(x)ecute `cargo shuttle run` when you save a file.
cargo watch -x 'shuttle run'
# This will also (q)uietly (c)lear the console between runs.
cargo watch -qcx 'shuttle run'

# There are many other helpful options, see `cargo watch --help`

Small caveat: Be aware that ignoring files with .ignore will also affect the behaviour of cargo shuttle deploy.

Live reload frontend with tower-livereload

Using cargo watch will only reload the “backend” Shuttle process. If you are developing a frontend in the browser that is hosted by your Shuttle app, you might also want the web page to reload when files change. If you are using Axum or other Tower-compatible frameworks, the Tower layer tower-livereload can help you.

First, add it to your project:

cargo add tower-livereload

Then, when constructing your Axum router, add the layer like this:

let router = Router::new()
    .route(/* ... */)

This will inject HTML responses with code for live reloading your web page when the server restarts. This also works in combination with cargo watch!

If you want to exclude this functionality from the release build, add this:

let mut router = /* ... */;

if cfg!(debug_assertions) {
    router = router.layer(tower_livereload::LiveReloadLayer::new());