Demo site here
Pottery Helper here
Discord here
This https://blog.checklyhq.com/building-a-multi-tenant-saas-data-model/ Article by https://twitter.com/tim_nolet was my inspiration for the user/account/subscription schema. Tim was also generous with his time and answered some of my stoopid questions on the https://www.reddit.com/r/SaaS/ Subreddit.
The focus is on separation of concerns and avoiding vendor lock in.
Composition over options API - I have decided to use composition api and setup functions accross the board including components, pages and Pinia stores. I was resistant at first, especially with the stores as I was used to Vuex but have come to the conclusion that it is easier to go one approach all over. It's also the latest and greatest and folks don't like to use a starter that starts behind the cutting edge.
Prisma over Supabase API - I went with Prisma for direct DB access rather than use the Supabase client. This is Primarily to avoid lock-in with Supabase too much. Supabase is great but I thought burdening my users with a future situation where it's difficult to move off it wouldn't be very cool. Also, I really like how Prisma handles schema changes and updates to the client layer and types with just two bash commands, after using other approaches, I find this super smooth.
Trpc over REST - Primarily for full thickness types without duplication on the client. Also I think the remote procedure call paradigm works well. Note however that I still include a REST endpoint example for flexibility. My preference for mobile is Flutter and there is not a Trpc client for Flutter that i'm aware off so it was important for me to make sure REST works also.
Things you gotta do that aren't code (and are therefore not very interesting)
Copy the .env_example file to create .env Note) This file is for development convenience, is .gitignored by default and should not be added to source control
This solution uses Supabase for Auth and to provide a DB. In addition to Magic Link and email/password login via Supabase, it also supports Google OAuth via Supabase.
[YOUR-PASSWORD]
with the password you provided when you setup the project.This solution uses Stripe for Subscription payments.
create: {
name: 'Team Plan',
.....
stripe_product_id: '[Your Product ID from Stripe]'
},
price_id
form fields...<input type="hidden" name="price_id" value="[Your Price ID from Stripe]" />
go to the API Keys page find 'Secret Key' -> reveal test key. click to copy and then replace the STRIPE_SECRET_KEY value in your .env
install the stripe cli used to forward webhooks (macos)
brew install stripe/stripe-cli/stripe
stripe login -i
provide the api key found in step 5) above
This solution uses Prisma to both manage changes and connect to the Postgresql database provided by Supabase. Your Supabase DB will be empty by default so you need to hydrate the schema and re-generate the local prisma client.
npx prisma db push
npx prisma generate
npm install @prisma/client --save-dev
npx prisma db seed
...you should now have a a Plan table with 3 rows and a bunch of empty tables in your Supabase DB
# yarn
yarn install
# npm
npm install
# pnpm
pnpm install --shamefully-hoist
This makes sure that you can debug subscription workflows locally
stripe listen --forward-to localhost:3000/webhook
If you haven't already done so look at the stripe cli output for this text
Your webhook signing secret is whsec_xxxxxxxxxxxxx (^C to quit)
take ths signing secret and update the STRIPE_ENDPOINT_SECRET value in .env
Start the development server on http://localhost:3000
npm run dev
There are a few unit tests, just for the stores because I needed to refactor. Feel free to extend the tests for your use cases, or not, it's your SaaS, not mine.
npm run test
Build the application for production:
npm run build
Locally preview production build:
npm run preview
Check out the deployment documentation for more information.
Where you host your SAAS is 100% your problem however :-
Steps (Assumes your repo is in github)
Go to Netlify
Log in with your github account (it's easier) and create an account (Free Tier is fine for now)
Add a New Site -> Import from Existing Proect
Choose your repo (You might need to Configure the Netlify app on GitHub) - Netlify auto-detects a nuxt app pretty good and the defaults it chooses seem to be fine.
Setup environment variables per the .env_example file (SUPABASE_URL, SUPABASE_KEY....etc)
Optionally change site name (e.g. mycoolsaas) or apply a domain name
Go to Supabase
Choose your project
Go to URL Authentication -> URL Configuration -> Site URL
enter your new netlify URL e.g. https://mycoolsaas.netlify.app/ and click 'save'
Add the following additional redirect URLs for local development and deployment previews:
Netlify is a bit rubbish at updating environment variables so you may need to manually re-deploy your site in certain situations e.g.
To manually redeploy to to your Netlify dashboard and navigate to Deploys -> Trigger Deploy -> Deploy site