Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/rcrdk/nextjs-fastify-saas-rbac

This project contains all the necessary boilerplate to setup a multi-tenant SaaS with Next.js and Fastify including authentication and RBAC authorization.
https://github.com/rcrdk/nextjs-fastify-saas-rbac

boilerplate casl docker fastify ky-http-client monorepo multi-tenant nextjs nodejs postgresql prisma-orm rbac react saas saas-boilerplate shadcn-ui turborepo typescript zod

Last synced: about 1 month ago
JSON representation

This project contains all the necessary boilerplate to setup a multi-tenant SaaS with Next.js and Fastify including authentication and RBAC authorization.

Awesome Lists containing this project

README

        

# 🔐 SaaS: Next.js and Fastify + RBAC
This project was developed for learning case at [Rocketseat](https://www.rocketseat.com.br/). It's a monorepo managed with TurboRepo that contains all the necessary boilerplate to setup a multi-tenant SaaS with Next.js and Fastify including authentication and RBAC authorization.

[![YouTube](https://github.com/rcrdk/nextjs-fastify-saas-rbac/blob/main/apps/web/public/acme-inc-2.png?raw=true)](https://www.youtube.com/watch?v=CorOVA9LM9A)

## 🚀 Techs and Tools


Tools

Turborepo 
PNPM 
Docker 
Warp Terminal 



API

Node.js 
Fastify 
Typescript 
Zod 
Prisma Client 
PostgreSQL 
Swagger 
Nodemailer + Gmail 
AWS SDK 
Cloudflare R2 
GitHub OAuth 
Google OAuth 



Front-end

React 19 RC 
Next.js 
React Query 
KY HTTP Requests 
Typescript 
Zod 
TailwindCSS 
Radix UI 
shadcn/ui 
Tabler Icons 
Day.js 
React Hot Toast 



Packages and Config

RBAC Authorizations with CASL 
Typescript 
ESLint 
Prettier 
T3 Env 



Deploy

Vercel 
Render 
Neon 

## 🖥️ Project
This project contains all the necessary boilerplate to setup a multi-tenant SaaS including authentication with RBAC, account settings, organizations management with projects, members, invitations and its settings. It started as a learning case and I end up creating more features and expanding all the project. Check it out:

**Roles:** the owner (administrator) of organizations who is able manage all data and actions; The regular member who is able to manage their projects; And the billing member who is able to manage, of course, the billing data. You can see the full detailed table below with the authorizations.

**Authentication:** consists into classic e-mail and password sign-in, also it includes the oAuth with third-party services from GitHub and Google. The traditional sign-up method requires an e-mail verification by a token valid for five minutes that is sent to the user inbox with instructions. The password recovery functionality works in a similar way of e-mail verification by a token sent to user e-mail.

**Account settings:** the user is able to manage their account: (1) basic information including the avatar, name and e-mail (to effectly change the e-mail, a revalidation is required); (2) set a password in case of social sign-in or change an existing one; (3) Connect or disconnect third-party authentication providers; (4) Manage all organizations that they are in and there's a option to leave organization from that they doesn't owns; (5) Delete account along with all owned organizations.

**Organization projects:** here the users can make the CRUD of projects, since this app is a boilerplate, it was developed a superficial projects section only with avatar, name, description and author.

**Organization members:** in this section the owner can manage the existing members of the organization being able to change their roles, remove them or transfer the ownership of the organization to one of them. There is also the option to invite new members for a specific role by sending an e-mail with the invitation link.

**Organization settings:** the owner has control of the entire organization: (1) change the avatar and its unique name; (2) It is possible to configure a unique domain, so new app users after signing up with the e-mail containing the domain could auto-join the organization. To be able to use a domain on organization, the owner must verify the domain ownership by setting a TXT entry on domain DNS records configuration of their domain; (3) The billing section, also shown to the billing member, is where the usage stats of organization are; (4) Finally, there it the option to shutdown the organization with all its data.

The API was developed using Fastify along with Prisma ORM and PostgreSQL as database; It was configured nodemailer to deal with transactional and validation e-mails; It was created a Cloudflare R2 bucket to store users, organizations and projects avatars using AWS SDK to establish the connection.

The front-end web app was developed using Next.js 15 with App Router with React 19 RC; It was used a not very known API client, KY, to deal with the requests that works very well with Next; It was used React Query to some client side requests; All design and components was written using shadcn/ui with Tailwind.

This project was prepared for deploy usign these three services: (1) Neon for hosting the PostgreSQL database; (2) Render to host the API; (3) Vercel to host the wep app. The API and Web apps were configured with my subdomain.

There are some pending stuff to do in here, so I'll be commiting in the near future.

## ⚙️ Get started

### 1️⃣ Setup enviroment:

Display contents

1. Generate your .env file: `cp .env.example .env`
2. Follow the next steps to fill the information.

### 2️⃣ Setup services:

Display contents

**Configure this services and paste all needed information to your .env file:**

1. Create a [GitHub OAuth](https://docs.github.com/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps) and a [Google OAuth](https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow) apps to be able to sign-in with these providers.
2. Make sure your Google Account have [2FA activeted](https://support.google.com/accounts/answer/185833) and then you must [generate an app password](https://myaccount.google.com/apppasswords) to be able to send transactional and validation e-mails.
3. Create a [Cloudflare R2](https://www.cloudflare.com/) bucket to upload the app avatars.

### 3️⃣ Generate JWT keys:

Display contents

```shell
# Generate RSA256 secret and public keys: (Requires OpenSSL installed)
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem

# Convert keys to Base64: (MacOS/Linux)
base64 -i private_key.pem -o private_key.txt
base64 -i public_key.pem -o public_key.txt
```

> [!TIP]
> **Use ChatGPT:**

> 1) Private and public keys: "How to generate RS256 private and public keys on [YOUR OS]"

> 2) Convert generated keys to base64: "How to convert file contents to base64 on [YOUR OS]"

### 4️⃣ Install dependencies and run services:

Display contents

```shell
# root:
pnpm i
docker compose up -d # make sure you are running docker

# apps/api
pnpm run db:migrate # seeds will run along

# root:
pnpm run dev
```

Other available commands:
```shell
# apps/api
pnpm run db:deploy
pnpm run db:reset
pnpm run db:studio
```

> [!NOTE]
> The commands starting with `pnpm run db:*` are used for loading environment variables into them.

## 🔗 Base routes
- API: http://localhost:3333
- API Docs: http://localhost:3333/docs
- WEB: http://localhost:3000/

## 🧑🏼‍💻 RBAC: Roles and Permissions

| Description | Owner | Member | Billing | Anonymous |
| ------------------------ | ----- | ------ | ------- | --------- |
| Update organization | ✅ | ❌ | ❌ | ❌ |
| Delete organization | ✅ | ❌ | ❌ | ❌ |
| Invite a member | ✅ | ❌ | ❌ | ❌ |
| Revoke an invite | ✅ | ❌ | ❌ | ❌ |
| List members | ✅ | ✅ | ✅ | ❌ |
| Transfer ownership | 🟡 | ❌ | ❌ | ❌ |
| Update member role | ✅ | ❌ | ❌ | ❌ |
| Delete member | ✅ | 🟡 | ❌ | ❌ |
| List projects | ✅ | ✅ | ✅ | ❌ |
| Create a new project | ✅ | ✅ | ❌ | ❌ |
| Update a project | ✅ | 🟡 | ❌ | ❌ |
| Delete a project | ✅ | 🟡 | ❌ | ❌ |
| Get billing details | ✅ | ❌ | ✅ | ❌ |
| Export billing details | ✅ | ❌ | ✅ | ❌ |

> ✅ allowed |
> ❌ not allowed |
> 🟡 allowed with conditions

**Conditions:**
- Only owners are able to transfer organization ownership;
- Only administrators and project authors are able update/delete a project;
- Only auth users can update their preferences;
- Members are able to leave a organization that they are in;
- Invites can be accepted or rejected by anyone with the link;