← All posts

· ShipRust · Updated

Introducing ShipRust: a SaaS starter in Rust

Start with accounts, sessions, Postgres, and server-rendered pages. ShipRust gives your next Rust SaaS project a working foundation you can read and change.

Starting a SaaS app usually means doing the same work again: creating a users table, hashing passwords, setting session cookies, wiring up forms, and figuring out deployment. None of that is the feature you wanted to build.

ShipRust is a starting point for that work. It gives you a runnable Rust web app with accounts, a dashboard, a Postgres database, and a Dockerfile. You name your project, download the source, and start changing it.

A small stack you can follow

The application uses Axum for HTTP, Maud for HTML, and sqlx to talk to Postgres. Pages render on the server. Styling is plain CSS, with light and dark themes and no JavaScript build step.

A request follows a short path: a route handler reads a form or queries the database, then passes the result to a Maud view. You can follow it without switching between a separate frontend application and a backend API.

This is a deliberate choice for products where forms, account pages, and database records make up much of the interface. If your product needs a rich client-side editor or offline interaction, you'll have frontend work to add. ShipRust starts with the simpler pages most apps need either way.

The repetitive parts are already connected

The starter includes:

  • Email and password accounts. Passwords use Argon2id, with hashing moved off the async request workers.
  • Server-side sessions. Cookies carry a session token; session records live in Postgres. Signed-in routes use a CurrentUser extractor.
  • Database migrations and checked queries. Migrations ship with the application, and sqlx checks queries against the schema during development. Offline query metadata supports builds without a live database.
  • Pages you can edit. A landing page, sign-up and sign-in forms, and a dashboard use the same layout and styles.
  • Tests against Postgres. Integration tests exercise the router with a fresh database for each test.
  • A deployment starting point. A Dockerfile is included. Choosing CapRover during project creation also adds a GitHub Actions deployment workflow.

Those pieces give you a foundation. Optional Stripe billing supplies Checkout, webhooks, and a customer portal. You still define your product's data model, permissions, pricing, paid-feature gates, and workflows. A starter can't decide those for you.

For a code-level walkthrough, read how we implemented email/password authentication in Rust, including pending signup, Argon2id, and Postgres-backed sessions.

Your app code has a place to live

The generated project separates the application from two supporting crates. shiprust-core handles configuration, database connections, errors, and shared HTTP behavior. shiprust-auth handles users, passwords, and sessions.

Your routes and views live in the app. Adding a feature should usually mean working there, rather than learning a plugin system or overriding hidden framework behavior.

The repository also includes an AGENTS.md operating manual. It describes where code belongs, how to run checks, and which rules matter. That gives both a human contributor and a coding agent a concrete place to start. It doesn't replace reviewing changes or running tests.

We use the same foundation

The ShipRust website runs on the same core and authentication crates that ship in generated projects. Its project generator packages the template with your chosen name and hosting option.

Each download records its template revision in .shiprust.toml. That makes the starting version explicit. Automatic upgrades are planned; recording a revision doesn't mean an upgrade system is already available.

Get a project running

Create an account and verify your email, then unlock lifetime access: $999 once for unlimited projects. Active site administrators have access without a purchase. Name your project and download its ZIP. With Rust and Docker installed, a project named my-app starts like this:

unzip my-app.zip
cd my-app
docker compose up -d
cp .env.example .env
SQLX_OFFLINE=true cargo run

Open http://localhost:3000 to check that the server is running. The first build uses SQLX_OFFLINE=true because the new database has no tables until the app starts and migrates it. Sign up straight away: with no mail provider configured, the verification code is printed to the terminal running the server, and a new account always requires that code. Before deploying, configure your own Mailgun credentials and email-verification key using the download and setup guide. Read the generated README and AGENTS.md before adding your first feature.

ShipRust is in early access. The next useful step is to generate a project and see whether this way of building fits your app.

For work that must survive a restart, see how we built Rust background jobs with a Postgres queue: transactional enqueueing, worker leases, retries, and the limits of at-least-once delivery.