A customized version of Fulco's JustShip SvelteKit marketing + app boilerplate.
This boilerplate provides a full stack shell for a SaaS application driven by SvelteKit with Typescript/Node and SQLite, with separate marketing and application front-ends, user accounts, auth access and control, and paid plans billed with Stripe.
- added Svelte Preprocess + Pug
- converted markup to Pug syntax
- added custom fonts (Inter, Lexend)
- added Tailwind Forms
- removed DaisyUI
- removed Embla Carousel
- created separate routes for 'marketing' and 'app' content, with auth control
- made Google Oauth sign-up & sign-in optional
- removed original marketing components
- added new Tailwind marketing components
- added default privacy & terms content
- updated sign-up & sign-in to use email & password
- added password reset flow
- connected creation of Stripe customer on sign-up
- update pricing UX to default new accounts to free plan
You'll Need To Build
- your application 😉
- application settings page (allowing user to manage auth settings and update plan, via Stripe Checkout)
- responses to billing events (see
src/routes/stripe/webhook/server.ts
for starter)
========================
A batteries included Svelte 5 SaaS Boilerplate - https://github.com/ocluf/justship
The current UX and code presume you have a free plan, plus optional paid plans. When a user signs up, the app will create a new user record + an associated Stripe customer record + that is subscribed automatically to your free plan. The user can then change plans within their app settings when prompted/desired.
- Use this repo as template (or fork) to create new GitHub repo
- Within local copy of repo run
pnpm install
- Rename the
.env.example
file to.env
- Run
pnpm run generate && pnpm run migrate
to create a local database - Install mailpit to receive emails locally
- start mailpit running in background in separate terminal (e.g.
brew services start mailpit
) - note: can stop background mailpit process after dev (e.g.
brew services stop mailpit
)
- start mailpit running in background in separate terminal (e.g.
- run
pnpm run dev
- create a new account at sign in page using any email address
- check for sign-up email at Mailpit localhost:8025
- click email activation link to create account and sign in
- Update missing / placeholder content
- update static resources (or alternatively, the links to them across templates):
static/logo.svg
static/favicons/…
(e.g. https://favicon.io/)static/socialcard.jpg
static/product-image-hero.png
/static/product-screenshot-hero.svg
static/signin-image.jpg
- update marketing content:
- can update marketing content in
src/lib/data/marketingContent.ts
- sections without content will not be shown
- can reorder marketing sections by editing
src/routes/(marketing)/+page.svelte
- can update privacy policy and terms in
src/routes/(marketing)/privacy/+page.svelte
andsrc/routes/(marketing)/terms/+page.svelte
- e.g. Privacy/Terms References of Generators
- can update marketing content in
- update static resources (or alternatively, the links to them across templates):
- Setup plans and billing with Stripe
- create new account OR access existing account
- configure public details at 'Settings : Business : Public details' (e.g. business name, help link, privacy/terms links, etc.)
- setup test environment
- search for 'Product Catalog'
- create a product for each plan level (e.g. 'Starter Plan', 'Pro Plan', 'Elite Plan')
- add pricing for each product
- create at least one free plan (e.g. 'Starter Plan' / $0)
- can optionally add multiple prices per product for monthly/yearly
- will most likely use 'flat-rate' billing (for app recurring subscriptions)
- within your free product (aka plan), select '...' menu link next to your $0 price and 'Copy price ID'
- copy price id value to
STRIPE_FREE_PLAN_PRICE_ID_TEST
in.env
(locally and in Vercel project)
- copy price id value to
- configure Customer Portal settings at 'Settings : Billing : Customer portal'
- e.g. business info, ability to switch subscription plans, etc.
- optional: configure branding settings at 'Settings : Business : Branding'
- search for 'Developers : Webhooks' (may be called 'Event Destinations' later)
- create new endpoint with url
https://{www.yourdomain.com}/stripe/webhook
- add events to listen for:
checkout.session.completed
customer.subscription.deleted
customer.subscription.updated
invoice.paid
invoice.payment_failed
- save endpoint and copy 'Signing secret' value to
STRIPE_WEBHOOK_SIGNING_SECRET_TEST
in.env
(locally and in Vercel project)
- create new endpoint with url
- search for 'Developers : API Keys'
- copy key to
STRIPE_SECRET_KEY_TEST
in.env
(locally and in Vercel project)
- copy key to
- search for 'Product Catalog'
- test plan subscriptions
- you should now be able to in dev 1) create a new account, 2) verify email (using Mailpit), 3) see new Stripe user created with subscription to free product in Stripe's test environment
- create new account OR access existing account
- (Optional: if want to use Google sign-up/in) Setup Google OAuth with Google Cloud
- set
PUBLIC_GOOGLE_OAUTH_ENABLED=true
in.env
(both locally and in Vercel project) - create new account, or access existing account
- create new project, or use existing project
- navigate to 'APIs & Services' : 'Credentials'
- select '+ Create Credentials' : 'OAuth client ID'
- (full details pending…)
- set
- Have or get a domain name
- (Optional) Setup email account(s) with new domain to create new infrastructure accounts below (e.g. using service like Migadu)
- Setup hosting with Vercel
- create new account, or access existing account
- add new project by importing repo from GitHub
- add environment variables to Vercel project
- can copy-paste full text from
.env
into 'Environment Variables' section of Vercel 'Configure Project' step
- can copy-paste full text from
- check for successful build
- if encounter issues, can run
npm run build
locally to help problem-solve
- if encounter issues, can run
- add domain to project on Vercel
- enable Vercel DNS and update A & CNAME records as indicated by Vercel
- Setup email service with Postmark
- create new account, or access existing account
- confirm email if new account
- navigate to 'Sender Signatures'
- check valid email address present / add new one as needed
- update DNS records to validate domain for email delivery
- add Postmark's TEXT & CNAME records to Vercel 'DNS Records' for custom domain
- check for successful verification at Postmark
- go to 'API Tokens': copy 'Server API token'
- update
.env
values, both locally and in Vercel project- update
FROM_EMAIL
value to email address from Postmark 'Sender Signatures' - add token as
POSTMARK_SERVER_TOKEN
value
- update
- Setup database with Turso
- create new account, or access existing account
- create new database (if necessary, create new group first)
- update
.env
values, both locally and in Vercel project; select database then- copy database url & add as
TURSO_DB_URL
value - generate database token (read & write) & add as
TURSO_DB_AUTH_TOKEN
value
- copy database url & add as
- in local repo, run
npm run migrate:prod
to create tables on production database tables- should see rows read/written in Turso database dashboard update from 0
- Setup analytics with PostHog
- create new account OR access existing account
- complete Product Analytics : 'Get Started' setup flow
- go to 'Settings' and copy 'Project API key'
- update
.env
values, both locally and in Vercel project- add API key as
PUBLIC_POSTHOG_KEY
value
- add API key as
- Test email service, database, and analytics
- redeploy Vercel site if needed to use latest environment variables
- on deployed site, create a new account
- initially must use a valid email address that matches domain connected to Postmark account (during its 'review period')
- should receive verification email (and also see 'Transactional Stream' messages number update in Postmark account)
- should be able to sign in (and also see a new user in Turso
users
table withemail_verified=1
) - should see events in PostHog 'Web Analytics' dashboard
- Activate plans and billing on Stripe
- make account live & setup production environment
- complete company details at 'Settings : Business : Business details' to activate production environment
- in production environment, repeat steps in 'Development : Stripe' above to create Products, configure Customer Portal, create webhook
- yep, for some reason, most of this has to be redone manually 🤦♂️
- when viewing products, can select '...' menu and 'Copy to live mode' link
- within your free product (aka plan), select '...' menu link next to your $0 price and 'Copy price ID'
- copy price id value to
STRIPE_FREE_PLAN_PRICE_ID
in.env
(locally and in Vercel project)
- copy price id value to
- copy production webhook signing secret to
STRIPE_WEBHOOK_SIGNING_SECRET
in.env
(locally and in Vercel project) - copy production secret key to
STRIPE_SECRET_KEY
in.env
(locally and in Vercel project)
- test plan subscriptions
- you should now be able to in prod 1) create a new account (use address currently allowed by Postmark account), 2) verify email, 3) see new Stripe user created with subscription to free product in Stripe's production environment
- make account live & setup production environment
========================
† Added, Removed
- Frontend
- Svelte 5
- TailwindCSS
- Tailwind Typography
DaisyUIEmbla Carousel- Lucide (icons)
- Svelte Preprocess †
- Pug †
- Inter, Lexend fonts †
- App Framework & APIs
- SvelteKit 2
- TypeScript
- Forms
- SvelteKit Superforms
- Tailwind Forms †
- Zod
- Auth
- Lucia
- Arctic
- Olso
- Database (SQLite/ORM)
- Drizzle
- Turso
- Email
- EmailJS
- Postmark
- Mailpit (local)
- Payments
- Stripe
- Linting
- Prettier
- Testing
- Vitest
- Playwright
- Analytics
- PostHog
- Hosting
- Vercel (frontend / serverless)
- Turso (database)
-
Why Turso?
- The simplicity of SQLite, and Turso extends that simplicity by allowing it not to run on the same server as your application. This offers the best of both worlds: an excellent local development story and worry-free scalability and backups in production.
-
Why Vercel?
- Offers remarkable developer experience with features like branch previews and automatic deployments based on GitHub pushes. While it can be costlier with high traffic volumes, this boilerplate is meant for quick product experiments. If a product gains traction, migrating to another service is straightforward.
-
Why Stripe?
- Stripe provides an excellent developer experience. While I'm not particularly concerned that they aren't the merchant of record—a key selling point for Paddle or LemonSqueezy — I am open to other payment providers. Feel free to submit a pull request to add alternative payment options.
-
Why PostHog?
- PostHog offers a generous free tier, an extensive feature set, and comprehensive documentation. Although I haven’t tested many other analytics providers, my positive experience with PostHog has persuaded me to stick with it.