- Print
- DarkLight
Use the AI SaaS Starter Kit with Backblaze B2
- Print
- DarkLight
The AI SaaS Starter Kit is an open-source template for building AI-powered software-as-a-service applications. It provides a Next.js frontend, a FastAPI backend, user authentication, subscription billing, AI image generation, an administrative console, and file management backed by Backblaze B2 Cloud Storage.
Use the starter kit to begin with a working application foundation and adapt its interface, dashboard, plans, and AI workflow for your own product. The repository is also structured so that AI coding agents can understand its architecture, follow its development rules, and help extend the application.
The starter kit is available from the AI SaaS Starter Kit GitHub repository.
This guide describes AI SaaS Starter Kit version 0.1.0.
Starter Kit Components
The starter kit includes the following components:
Application interface
Next.js 16, React 19, TypeScript, Tailwind CSS, and shadcn/ui.Application API
FastAPI, Python, boto3, and Pydantic.Authentication and database
Supabase authentication and PostgreSQL.Subscription billing
Stripe Checkout, the Stripe Billing Portal, subscription synchronization, and Free, Pro, and Team plan gating.AI image generation
NVIDIA NIM with the flux.1-dev model, orchestrated through the Genblaze SDK.Object storage
Backblaze B2 storage for uploaded files, generated images, and generation provenance manifests.Administration
An admin console for reviewing users, subscriptions, generation jobs, files, provider runs, and audit events.Development guidance
Repository instructions, architecture documentation, structural tests, and feature documentation for developers and AI coding agents.
Stripe billing and AI image generation are optional. You can run the authentication, upload, and file-management features with Backblaze B2 and a local Supabase environment before configuring the optional services.
How the Starter Kit Uses Backblaze B2
The starter kit connects to Backblaze B2 through the S3-Compatible API by using boto3. It uses your bucket for the following data:
Files uploaded through the application
Images created through the AI generation workflow
SHA-256 provenance manifests associated with generated images
File metadata displayed by the dashboard and file manager
For uploads, the FastAPI backend creates a presigned URL and the browser uploads the file directly to Backblaze B2. The file does not pass through the application server. This design supports larger uploads and avoids serverless request-body limits.
By default, the application creates short-lived presigned URLs for private file previews and downloads. You can optionally configure a stable public URL base if you use a public bucket and want durable public links.
Prerequisites
Before you begin, ensure that you have the following items:
A Backblaze account with Backblaze B2 Cloud Storage enabled.
A Backblaze B2 bucket
Record the bucket name and region. Use a dedicated bucket for the starter kit.A Backblaze B2 application key restricted to the bucket
Select Read and Write and Allow List All Bucket Names. Save thekeyIDandapplicationKeywhen you create the key. Backblaze displays theapplicationKeyonly once.Node.js 20 or later
pnpm 9 or later
Python 3.11 or later
Docker or another Docker-compatible runtime
A Bash-compatible terminal. On Windows, use Windows Subsystem for Linux 2 (WSL2)
To enable optional features, you also need the following items:
A Stripe account and the Stripe CLI
Create a Project from the Template
You can create a new GitHub repository from the template or clone the starter kit directly. Creating a repository from the template is recommended because it gives your project its own Git history.
Open the AI SaaS Starter Kit repository.
Click Use this template, and select Create a new repository.
Enter a repository name, configure its visibility, and create the repository.
Clone your new repository and enter its directory.
git clone https://github.com/<your-organization>/<your-repository>.git cd <your-repository>Replace
<your-organization>and<your-repository>with the values for your GitHub repository.
Install the Dependencies
From the project root, install the frontend dependencies.
pnpm installCreate a Python virtual environment and install the backend dependencies.
cd services/api python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt cd ../..
Add the Backblaze B2 Environment Variables
From the project root, create a local environment file.
cp .env.example .envOpen
.env, and replace the Backblaze B2 placeholders with your values.B2_APPLICATION_KEY_ID=<your-application-key-id> B2_APPLICATION_KEY=<your-application-key> B2_BUCKET_NAME=<your-bucket-name> B2_REGION=<your-bucket-region> B2_PUBLIC_URL_BASE=For example, a bucket in the US West region might use
us-west-004forB2_REGION. The application derives the S3-Compatible API endpoint from the region, so you do not need to enter a separate endpoint.B2_PUBLIC_URL_BASEis optional. Leave its value empty to use short-lived presigned URLs with a private bucket. For a public bucket, you can set it to a value with the following format:B2_PUBLIC_URL_BASE=https://<bucket-name>.s3.<region>.backblazeb2.com.
Configure Backblaze B2 CORS for Local Development
The browser uploads files directly to Backblaze B2. Your bucket must allow cross-origin requests from the local application before you can test uploads.
From the project root, load the Backblaze B2 environment variables and run the included configuration script. The second origin allows uploads if Next.js uses port 3001 because port 3000 is unavailable.
set -a
. ./.env
set +a
services/api/.venv/bin/python scripts/configure_b2_cors.py \
--origin http://localhost:3000 \
--origin http://localhost:3001Applying this configuration replaces the bucket's entire CORS configuration. If another application uses the same bucket, include every origin that it requires.
Configure Supabase Locally
Supabase provides authentication and the PostgreSQL database used for profiles, roles, plans, subscriptions, generation jobs, and administrative data. For local development, the included configuration uses a local Supabase stack.
Start Docker or your Docker-compatible runtime.
From the project root, start Supabase.
supabase startCopy the local Supabase configuration into
.env.node scripts/sync-supabase-env.mjs
The script sets the following variables:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEY
The service-role key is a server-side secret. Do not expose it in browser code or commit the .env file to source control.
The local Supabase environment includes the following services:
Supabase Studio: http://127.0.0.1:54323
Mailpit: http://127.0.0.1:54324
Mailpit captures local account-confirmation and email-code messages. The local environment does not send these messages to an external email address.
Run the Starter Kit
From the project root, start the frontend and backend.
pnpm devThis command first runs pnpm doctor, which checks the Node.js, pnpm, and Python versions; the Python virtual environment; required environment variables; and local ports. If the check finds a problem, follow the displayed instructions and run the command again.
The application uses the following default addresses:
Component | Address |
|---|---|
Application |
|
API |
|
Backblaze B2 connectivity check |
|
If port 8000 is unavailable, the development script selects another API port and displays it in the terminal.
Verify the Starter Kit
Open
http://localhost:3000.Create an account.
Open Mailpit at
http://127.0.0.1:54324.Open the confirmation message, and confirm the account.
Sign in to the application.
Open the upload page, and upload a supported file.
Open the file manager, and verify that the file appears.
Open your Backblaze B2 bucket, and verify that the object was uploaded.
Open
http://localhost:8000/health, and verify that the API reports a successful Backblaze B2 connection.
Grant Administrative Access
New accounts receive the user role by default. To test the administrative console, grant your account the admin role.
Open Supabase Studio at
http://127.0.0.1:54323.Open the SQL editor.
Run the following statement, replacing the email address with your account email address.
update public.profiles set role = 'admin' where email = 'you@example.com';Open
/adminin the application, and verify that the administrative console appears.
Enable Stripe Billing
Stripe billing is optional. Without a Stripe configuration, the application continues to run, but billing endpoints return an HTTP 503 response.
The following steps use Stripe test mode and do not create real charges.
Sign in to the Stripe CLI.
stripe loginIn the Stripe Dashboard, enable test mode and copy your test secret key.
Add the secret key to
.env.STRIPE_SECRET_KEY=<your-stripe-test-secret-key>Create the Pro and Team recurring prices and add their identifiers to
.env.
The command is idempotent. If the products and prices already exist, it reuses them instead of creating duplicates.pnpm stripe:seedStart the Stripe webhook listener in a separate terminal.
pnpm stripe:listenCopy the displayed
whsec_signing secret into.envasSTRIPE_WEBHOOK_SECRET.Restart
pnpm devbecause the API reads.envduring startup.Open
/billing, and select the Pro plan.Complete the test checkout by using Stripe test card number
4242 4242 4242 4242, any future expiration date, and any valid CVC and postal code.If the API uses a port other than
8000, forward Stripe events to the displayed port instead.stripe listen --forward-to localhost:<api-port>/billing/webhook
For complete instructions, see Set Up Stripe Billing.
Enable AI Image Generation
AI image generation is optional. Without an NVIDIA API key, the generation endpoint returns an HTTP 503 response and the other application features remain available.
The generation feature requires a Pro or Team plan. Configure Stripe test mode and upgrade your test account before you test generation.
Get an API key from NVIDIA NIM.
Add the key to
.env.NVIDIA_API_KEY=<your-nvidia-api-key>Restart
pnpm dev.Open
/generate.Enter a prompt, and generate an image.
Verify that the image appears on the generation page and in the file manager.
Open the Backblaze B2 bucket, and verify that the generated image and its provenance manifest appear under the
generated/prefix.
The default model is black-forest-labs/flux.1-dev. You can configure the model, image dimensions, generation steps, timeouts, concurrency, and daily limit in services/api/app/config/settings.py.
For details about the workflow, see AI Media Generation.
Configure CORS for a Deployed Application
The browser uploads files directly to Backblaze B2 through presigned PUT requests. Before you deploy the application, the bucket must have a CORS rule that permits requests from the deployed frontend origin.
From the project root, load the Backblaze B2 environment variables and run the included configuration script.
set -a . ./.env set +a services/api/.venv/bin/python scripts/configure_b2_cors.py \ --origin https://<your-web-domain>Repeat the
--originoption to permit more than one frontend origin.services/api/.venv/bin/python scripts/configure_b2_cors.py \ --origin https://<your-production-domain> \ --origin https://<your-preview-domain>
The script configures GET, PUT, and HEAD requests and permits the Content-Type header. Applying the configuration replaces the bucket's entire CORS configuration. If other applications use the bucket, include every origin that they require. A dedicated bucket for each deployment environment prevents different applications or environments from overwriting one another's CORS configuration. If you use the same bucket for local development, include your local origins (for example, http://localhost:3000) in this command too: it replaces the local CORS rules that you configured earlier in Configure Backblaze B2 CORS for Local Development rather than adding to them.
The API also has its own CORS setting. In production, set API_CORS_ORIGINS on the backend to the exact frontend origin.
API_CORS_ORIGINS=https://<your-web-domain>For full production instructions, see Deploy the AI SaaS Starter Kit.
Deploy the Starter Kit
The recommended production topology separates the application into the following services:
A Next.js frontend deployed to Vercel
A FastAPI backend deployed to Railway, Render, or Fly.io
A hosted Supabase project for authentication and PostgreSQL
Stripe for billing, if enabled
Backblaze B2 for uploaded and generated files
Deploy the backend first so that you can add its address to the frontend as NEXT_PUBLIC_API_URL. When you import the frontend into Vercel, set its root directory to apps/web.
You can also deploy the frontend and backend as separate Vercel projects. Review the serverless limitations in the repository deployment guide before selecting this topology.
See the deployment guide for required environment variables, hosted Supabase configuration, production Stripe webhooks, Backblaze B2 CORS configuration, and post-deployment verification.
Customize the Starter Kit
The repository separates reusable SaaS infrastructure from the example application behavior. When you build your application:
Retain the authentication, billing, file manager, upload workflow, UI components, and navigation structure.
Adapt the dashboard cards, charts, and tables to represent your application's activity.
Change the application name and description in
apps/web/src/lib/app-config.ts.Use the existing FastAPI layer structure and TanStack Query data-access patterns when you add features.
Update the repository documentation in the same pull request as the related code.
Start with AGENTS.md before you give the repository to an AI coding agent. It defines the repository layout, development commands, architectural constraints, and links to the detailed documentation.
Troubleshoot the Starter Kit
Use the following solutions to resolve common setup and configuration issues.
Resolve Environment Check Failures
Run the environment check separately to see each detected problem and its corrective action.
pnpm doctorInstall any missing dependency, replace placeholder values in .env, or recreate the Python virtual environment as directed. Then run pnpm doctor again.
Resolve a Missing Python Virtual Environment
Recreate the environment from the project root.
cd services/api
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cd ../..Resolve Supabase Startup Failures
Confirm that Docker is running before you run supabase start. If the Supabase variables are missing from .env, run the synchronization script again.
node scripts/sync-supabase-env.mjsResolve a Failed Backblaze B2 Health Check
Confirm that the values for B2_APPLICATION_KEY_ID, B2_APPLICATION_KEY, B2_BUCKET_NAME, and B2_REGION in .env match the bucket and application key. Also confirm that the key has Read and Write access to the selected bucket.
Resolve Upload Failures After Deployment
If the application loads but file uploads fail, confirm that the Backblaze B2 bucket CORS configuration permits the deployed frontend origin. Also confirm that the backend's API_CORS_ORIGINS value includes the same frontend origin.
Resolve Billing Service Unavailable Errors
An HTTP 503 response from a billing endpoint means that Stripe is not fully configured. Confirm that .env contains STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_PRO, and STRIPE_PRICE_TEAM. Restart the application after you change .env.
Resolve Stripe Webhook Signature Errors
If a webhook returns 400 Invalid signature, confirm that STRIPE_WEBHOOK_SECRET matches the signing secret displayed by the active Stripe listener. Restart the API after you update the value.
Resolve AI Generation Service Unavailable Errors
An HTTP 503 response from the generation endpoint means that NVIDIA_API_KEY is not configured. Add the key to .env and restart the application.
If the generation page remains locked, confirm that the signed-in account has an active Pro or Team plan.
Resolve Administrative Access Errors
New users are not administrators. If /admin returns an HTTP 403 response, grant the account the admin role in Supabase and sign in again.
Next Steps
After you verify the starter kit, use these resources to customize and deploy your application:
Review the architecture
To understand the frontend, backend layers, data flows, and integration boundaries, see Architecture.Work with an AI coding agent
To learn the repository structure, rules, commands, and required documentation updates, see Agent Instructions.Explore the application workflows
To review the sign-in, upload, billing, generation, and administrative workflows, see Application Workflows.Review the feature documentation
To understand authentication, billing, image generation, file uploads, file management, the dashboard, and administration, browse the feature documentation.Deploy the application
To configure Vercel, a backend host, hosted Supabase, Stripe, and Backblaze B2, see Deployment.Review the security guidance
To understand authentication boundaries, credential handling, upload validation, rate limiting, and production hardening, see Security.Learn about the S3-Compatible API
To understand how the application uses boto3 and presigned URLs with Backblaze B2, see the S3-Compatible API documentation.Configure CORS rules
To learn more about permitting direct browser uploads to Backblaze B2, see Cross-Origin Resource Sharing Rules.Explore more integrations
To learn about other Backblaze integrations and developer examples, visit Backblaze Labs.
Help us improve this guide. If you find an error, notice outdated information, or have suggestions for improvement, email techpubs@backblaze.com.