Every SaaS product needs the same foundation: user authentication, payment processing, an admin panel, database models, and a deployment pipeline. Building those from scratch takes weeks of work before you write a single line of product-specific logic. ShipKit is a production-tested FastAPI boilerplate that gives you all of that infrastructure out of the box, extracted from the architecture running six live Wigley Studios products. This guide walks you through getting from a fresh download to a running SaaS backend.
What You Get
ShipKit is not a framework or a library you install as a dependency. It is a complete project you download and build on top of. When you open the project for the first time, you have a working FastAPI application with:
- JWT authentication with dual-key rotation, token refresh, and protected route guards
- Stripe Checkout integration with webhook signature validation and idempotent event processing
- Admin panel foundation with session-based auth and customer management views
- MySQL + SQLAlchemy models with typed ORM patterns and migration-ready schema design
- Structured project layout with modular routing, dependency injection, and clear module boundaries
The Professional tier adds deploy scripts, CI/CD templates, multi-tenant scaffolding, Redis caching, background worker queues, rate limiting, and transactional email.
Production-Tested Architecture
Every pattern in ShipKit was extracted from backends that handle real Stripe transactions, serve real API traffic, and run on real infrastructure. The gap between boilerplate and production code is already closed.
Step 1: Set Up Your Environment
1 Prerequisites
You need Python 3.12+, MySQL 8.0+ (or MariaDB), and pip. If you are using the Professional tier, you will also need Redis 5.0+ installed locally for caching, rate limiting and instant sign-out. A Stripe account (test mode is fine for development) is needed to configure payment processing.
After downloading ShipKit from your purchase confirmation, unzip the project and create a virtual environment:
- Create and activate a Python virtual environment in the project root
- Install dependencies from the included
requirements.txtwith pinned versions - Copy the
.env.examplefile to.envand fill in your database credentials, JWT secret, and Stripe keys
The .env.example file documents every variable with comments explaining what each one controls. The only values you must change before the app will start are the database connection string and the JWT secret key.
Step 2: Configure Your Database
2 Database Setup
Create a MySQL database and user for your project. ShipKit's config reads the connection string from the DATABASE_URL environment variable. Then run alembic upgrade head: the kit's migrations create every table (the app never creates tables itself, so the schema you run is always the one the migrations describe), and you keep using migrations for every schema change after.
The database layer uses SQLAlchemy with typed models. Each model follows patterns tested across six production applications: explicit column types, proper indexing, and foreign key relationships that work with MySQL's InnoDB engine. Connection pool sizing is pre-configured for typical VPS workloads but adjustable through environment variables.
Step 3: Wire Up Authentication
3 JWT Auth
ShipKit's auth system is ready to use immediately. Set SECRET_KEY (32 or more random characters) in .env, and the route guards, token generation, and refresh logic all work. To rotate it later, move the old value to SECRET_KEY_PREVIOUS: tokens signed with it stay valid until they expire, so nobody is logged out.
The auth module includes registration, login, token refresh, and logout endpoints. Protected routes use a dependency that validates the access token (a refresh token is never accepted in its place), checks the account is still active, and returns the current user. Adding a new protected endpoint is one decorator:
- Import the
get_current_userdependency - Add it as a parameter to your route function
- The user object is available in the function body with typed fields
Logging out revokes the refresh token, so the session cannot be renewed, and “sign out everywhere” ends every session at once (a password change or reset does too). On Professional the access token in hand also stops working the moment you log out, through a Redis revocation list; on Starter it simply expires at the end of its short lifetime.
Step 4: Connect Stripe
4 Stripe Integration
Add your STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET to .env. The checkout endpoint creates payment sessions, and the webhook handler validates signatures, deduplicates events, and processes them with retry logic. Dead-letter handling prevents silent payment failures.
ShipKit ships with payment-mode Checkout Sessions. To add subscription billing, you extend the existing checkout handler with Stripe's subscription-mode parameters. The webhook handler already processes checkout.session.completed events and can be extended to handle customer.subscription.updated, invoice.payment_failed, and other subscription lifecycle events.
Every webhook is checked against its Stripe signature and recorded by event id first, so a repeated delivery does nothing twice. On Professional it is then queued to the database job queue and answered at once, and a worker processes it with retries and backoff. On Starter it is applied in the same transaction as the record, so a failure rolls both back and Stripe retries it.
Step 5: Build Your Product Logic
5 Add Your Modules
With auth, payments, and admin already handled, you can focus entirely on what makes your product unique. Create a new module directory, define your models and routes, and register the router in the main application. ShipKit's modular structure keeps your code separate from the infrastructure code.
The project layout uses FastAPI's router system with clear boundaries between modules. Each module gets its own directory with routes, models, and schemas. Adding a new module follows a consistent pattern:
- Create a directory under
app/for your module - Define SQLAlchemy models for your domain objects
- Create Pydantic schemas for request and response validation
- Write route handlers using the existing auth dependencies
- Register the router in the main app with a URL prefix
Because every module follows the same structure, navigating the codebase stays intuitive as your application grows. New developers can look at any existing module to understand the pattern.
Step 6: Deploy (Professional Tier)
6 VPS Deployment
The Professional tier includes systemd service definitions and nginx reverse-proxy configurations. These are the actual configs used in production, not generic templates. Connection pool sizing, SSL termination, and health check endpoints are already configured.
Deployment to a VPS follows a straightforward process:
- Provision a VPS with Python 3.12+, MySQL or MariaDB, nginx, and (Professional) Redis
- Upload the project and create a virtual environment on the server
- Configure the production
.envwith live credentials - Install the systemd service file to run the FastAPI app as a background process
- Configure nginx as a reverse proxy with SSL termination via Let's Encrypt
- Start the service and verify the health check endpoint responds
On Professional, the included CI/CD templates automate later deploys. Tag a release (v1.2.0) and the deploy workflow runs the tests, uploads the release, migrates the database, switches to it and checks its health, rolling back if it fails; a reviewer's approval can gate it. Pushes to your main branch only run the tests.
Starter vs Professional: Which Tier Fits
| Capability | Starter ($29) | Professional ($79) |
|---|---|---|
| FastAPI structure & routing | ✓ | ✓ |
| JWT auth & protected routes | ✓ | ✓ |
| Stripe Checkout | ✓ | ✓ |
| Admin panel foundation | ✓ | ✓ |
| MySQL + SQLAlchemy models | ✓ | ✓ |
| VPS deploy scripts | — | ✓ |
| CI/CD pipeline templates | — | ✓ |
| Multi-tenant scaffolding | — | ✓ |
| Redis caching & rate limiting | — | ✓ |
| Background worker queues | — | ✓ |
| Transactional email | — | ✓ |
If you are building a side project or validating an idea, Starter gives you everything needed to build and test locally. If you plan to deploy to production and need operational infrastructure from the start, Professional saves you from rebuilding the deploy pipeline, caching layer, and background processing that every scaling SaaS eventually needs.
Upgrade Path
Start with Starter and upgrade to Professional later if you need the additional infrastructure. Contact support for a difference-priced upgrade checkout so you only pay the gap.
Skip the Setup
Auth, billing, admin, and deploy — already built, already tested, already shipping. Start building what makes your product different.
Explore ShipKit