Getting Started
This guide uses Prisma for database access and GitHub as the authentication provider.
Install packages
For Auth & Payment:
pnpm install -D @airbadge/sveltekit @auth/sveltekit
For Prisma:
pnpm install -D prisma @prisma/client @auth/prisma-adapter
Configure environment
Add environment variables to .env
:
# Stripe private key
# Find it here: https://dashboard.stripe.com/test/apikeys
SECRET_STRIPE_KEY=sk_...
# Domain to use for URLs:
DOMAIN=http://localhost:5173
# Database URL for the Auth.js database adapter
# For examples, see: https://www.prisma.io/docs/orm/reference/connection-urls
# If you don't have postgres locally, create one for free here: https://console.neon.tech/signup
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/airbadge_dev?schema=public"
# Generate a secret key via Auth.js's CLI:
# > npx auth secret
AUTH_SECRET=
# OAuth setup for GitHub:
# - Create an OAuth app: Settings -> Developer Settings -> OAuth Apps
# - Copy & paste Client Id and Client Secret here:
AUTH_GITHUB_ID=
AUTH_GITHUB_SECRET=
Setup database
First, initialize Prisma:
pnpm prisma init
Then, update your prisma/schema.prisma
:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
// customizations for AirBadge
customerId String?
subscriptionId String?
subscriptionStatus SubscriptionStatus?
plan String?
priceId String?
purchases Json @default("[]")
}
// customization for AirBadge
enum SubscriptionStatus {
INCOMPLETE
INCOMPLETE_EXPIRED
TRIALING
ACTIVE
PAST_DUE
CANCELED
UNPAID
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
Finally, push the schema:
pnpm prisma db push
Create pricing
Create some plans and pricing. This can be done via the Stripe Dashboard or from the Stripe CLI.
To create them with the CLI:
# login to Stripe
stripe login
# create products & pricing
stripe prices create \
--product-data.name="Basic Plan" \
--lookup-key=basic_monthly \
--currency=usd \
--unit-amount=1000 \
--recurring.interval=month
stripe prices create \
--product-data.name="Pro Plan" \
--lookup-key=pro_monthly \
--currency=usd \
--unit-amount=2500 \
--recurring.interval=month
stripe prices create \
--product-data.name="Enterprise Plan" \
--lookup-key=enterprise_monthly \
--currency=usd \
--unit-amount=10000 \
--recurring.interval=month
Configure SvelteKit
Configure authentication and billing options in src/hooks.server.js
:
import { SvelteKitAuth } from '@airbadge/sveltekit'
// use GitHub OAuth provider
import GitHub from '@auth/sveltekit/providers/github'
// use Prisma database adapter
import { PrismaAdapter } from '@auth/prisma-adapter'
// import Prisma client for database adapter
import { PrismaClient } from '@prisma/client'
// init database client
const db = new PrismaClient()
// add Auth.js + Stripe handler
// API is similar to Auth.js
export const { handle } = SvelteKitAuth({
adapter: PrismaAdapter(db),
providers: [ GitHub ]
})
Forward webhooks
Webhook handling is built-in. Just forward webhooks via Stripe’s CLI.
stripe listen --forward-to localhost:5173/billing/webhooks
Celebrate! 🎉
You now have a working SaaS app!
Visit http://localhost:5173/billing/checkout?id=pro_monthly to sign up and pay.