I have been a software developer working on SaaS platforms for over 15 years. This example project compresses my years of knowledge into a fully functional Software as a Service (SaaS) platform that can be deployed to AWS using IaC and GitHub Actions. It's certainly not perfect, but I hope that this will help some up and coming SaaS entrepreneurs see a scalable, production-level build from end to end.
- Web App (NextJS + AuthJS + React) - Deployed to AWS Lambda
- REST API (NextJS + AuthJS) - Deployed to AWS Lambda
- OAuth2 Authentication Server (NextJS + @node-oauth/oauth2-server) - Deployed to AWS Lambda
- MCP Server Cluster (Express + MCP Typescript-SDK) - Deployed to AWS ECS
- Web Analytics (PostHog)
It uses Infrastructure as Code (IaC) using SST. It deploys to AWS using GitHub Actions. This is the current architecture of the live demo:
The production cloud deployment without much activity is $1-$2 per day to run on AWS. Any product getting real use and customers will have to scale up the MCP cluster, but that's usually a good problem to have.
- AWS account with SSO set up in
~/.aws/config
Setup Guide - AWS CLI Install
- Docker for local postgres database Install Docker
- You must also bring your own production postgres database or you need to add RDS to the SST stack. I use Digital Ocean managed databases.
- Your domain should be set up in Route 53 and you will need the Hosted Zone ID for cloud deployments (not needed for local deployments).
- IAM user access key/secret Setup Guide and Permissions Guide
- Mailgun Account Get API Key
- Stripe Account [Get API Key] (https://docs.stripe.com/keys)
You can do a global find for chipgpt
(case insensitive) and locate most things that need to be updated with your own project name and description.
Log in to AWS SSO:
npm run sso
Copy the .env.example
file and populate them. You don't need a development cloud deployment but it supports it if you want a staging server eventually:
cp .env .env.{{username}}
cp .env .env.development
cp .env .env.production
Install dependencies:
npm install
Start local postgresql database:
npm run docker:up
Start a local deployment:
npx sst dev
NOTE: If you run into this error when trying to
npx sst dev
, it usually means you need tonpm run sso
to reauthorize with AWS.✕ Unexpected error occurred. Please run with --print-logs or check .sst/log/sst.log if available.
After starting up new environments for the first time, you will need to update the new Amazon Cognito Pool's domain in AWS console.
Log in to AWS Console > Amazon Cognito > User Pools > select user pool > Domain > set a domain for your cognito pool and make sure to set "Hosted UI (classic)"
NOTE: You may be able to use the new UI if you set it all up, but I have not done that. So if you just wanna get this up and running, then you should go with Hosted for now and plan to try to update later.
At this point you should have the stack running locally. Some of the resources are in AWS but your code is all executed locally and is not deployed to AWS. SST has a cool multiplexer that you can use to monitor the apps locally as well. Everything updates live when you save files.
- Default Web URL is: http://localhost:3000
- Default Web Dashboard is: http://localhost:3000/dashboard
- Default API URL is: http://localhost:3000/api
- Default OAuth URL is: http://localhost:3000/api/oauth
- Default MCP server URL is: http://localhost:3333/mcp
Make sure docker database is running:
npm run docker:up
Make sure you are logged in:
npm run sso
Start up the local deployment:
npx sst dev
npx @modelcontextprotocol/inspector
npm run deploy:production
If this is the first deployment, you will need to update your Amazon Cognito Pool's domain in AWS console after it gets deployed.
Log in to AWS Console > Amazon Cognito > User Pools > select user pool > Domain > set a domain for your cognito pool and make sure to set "Hosted UI (classic)"
NOTE: You may be able to use the new UI if you set it all up, but I have not done that. So if you just wanna get this up and running, then you should go with Hosted for now and plan to try to update later.
To get the GitHub action deployment working you will need an IAM user with access/secret key and add secrets to your repo (see Requirements).
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AUTH_SECRET
- DATABASE_URL
- AWS_HOSTED_ZONE_ID
- MAILGUN_API_KEY
- STRIPE_API_KEY
- NEXT_PUBLIC_POSTHOG_KEY (not really a "secret", it could be a variable instead)
-
Add SES email management for production SES accessAdd Mailgun email for sending emails - Add a paid account tier (most likely using Stripe as the payment gateway)
- Add a propper logging utility that works better with AWS CloudWatch.
- Add Alarms/Alerts for cloud deployments to be proactive about issues.
- Auto-Generate REST API Documentation.
- Support for Amazon RDS + Proxy (had trouble getting it working with Sequelize, didn't feel like finding a new ORM)
- Add proper Sequelize migrations.
- Update to use the new Cognito UI mode.
- Switch to the official
@auth/sequelize-adapter
package after PR #13120 is merged.
I'm happy to take feedback or answer questions as I am able to. Submit an issue to the repository and I'll do my best to respond in a timely manner.
If you found this helpful, please star this repo and follow me on TikTok: @Chip.GPT