/saas-template

SaaS template for AWS, Amplify, React, NextJS and Chakra

Primary LanguageTypeScriptMIT LicenseMIT

AWS + React SaaS Template

End-to-end SaaS Template using AWS Amplify, Apollo Client, Chakra, and NextJS.

YouTube Channel YouTube Channel YouTube Channel

Table of content

Tech Stack

🔹 DynamoDB
🔹 AppSync (GraphQL)
🔹 Cognito
🔸 React / NextJS
🔸 Amplify
🔸 Apollo Client
🔸 Chakra ▪️ Pulumi ▪️ GitHub Actions

Prerequisites

Create an account on AWS (https://aws.amazon.com/).

You will need to setup the AWS CLI on your local system, if you haven't already.

Create an account on Pulumi (https://pulumi.com/).

You will need to setup the Pulumi CLI and configure it with AWS.

Install Amplify CLI.

We need Amplify to set up the Front End, so you need to setup the Amplify CLI on your local system.

ℹ️ Additional info

This repository is a monorepo, but you can split out the front-end and back-end folders into separate repositories.

Setup

Setup the stack in the cloud

Go to the back-end folder:
cd back-end

Install the dependencies:
npm install

Use Pulumi to setup the stack in the cloud:
pulumi up

This command will set up a stack consisting of 18 resources in AWS.
They boil down to:

  • A DynamoDB table for users
  • A Cognito user pool
  • An Identity Pool
  • AppSync GraphQL API
  • A PostConfirmation Lambda which is triggered when a user signs up
  • A Resolver Lambda which is used to fetch a user through GraphQL

When the pulumi up command has finished running, you will get an output that looks similar to this.
Note down this output:

Outputs:
    appSyncID       : "<APPSYNC-ID>"
    dynamoID        : "<TABLE-NAME>"
    graphQLEndpoint : {
        GRAPHQL : "https://<GRAPHQL-ENDPOINT>/graphql"
        REALTIME: "wss://<REALTIME-ENDPOINT>/graphql"
    }
    identityPoolID  : "<IDENTITY-POOL-ID>"
    userpoolClientID: "<USERPOOL-CLIENT-ID>"
    userpoolID      : "<USERPOOL-ID>"

ℹ️ Additional info

If Pulumi complains about missing region, use the command: pulumi config set aws:region eu-west-1

If you want to use another region than eu-west-1, go to the file back-end/resources/variables/ and change the region here as well.

export const variables = {
  region: 'eu-west-1' as const, // <-- change this to your region
  dynamoDBTables: {} as Record<string, Output<string>>,
};

Setup the front-end

Go to the front-end folder:
cd front-end

Install the dependencies:
npm install

Use Amplify to link the front-end to the back-end: amplify init

  • ? Enter a name for the project: my-app-name
  • ? Choose the environment you would like to use: dev
  • ? Choose your default editor: Visual Studio Code
  • ? Choose the type of app that you're building: javascript
  • ? What javascript framework are you using: react
  • ? Source Directory Path: src
  • ? Distribution Directory Path: build
  • ? Build Command: npm run build
  • ? Start Command: npm run start
  • ? Select the authentication method you want to use: AWS profile
  • ? Please choose the profile you want to use: <default - or pick the one you use>

This will setup an Amplify project in the cloud for the front-end.

A file called src/aws-exports.js will be created. You can safely deleted this file.
(In fact, you can delete the src folder entirely).

Configure the environment

Go to the file front-end/deployment/config/config-development.ts.
Now, use the Pulumi output from before, to setup the environment:

const configDevelopment = {
  ...

  /**
   * Add the details from the Pulumi output here, after running 'pulumi up'
   */
  USER_POOL_CLIENT_ID: '<USERPOOL-CLIENT-ID>',
  USER_POOL_ID: '<USERPOOL-ID>',
  IDENTITY_POOL_ID: '<IDENTITY-POOL-ID>',
  GRAPHQL_ENDPOINT: 'https://<GRAPHQL-ENDPOINT>/graphql',
};

Next, run the command: amplify codegen add -apiId <APPSYNC-ID>

  • ? Choose the code generation language target: typescript
  • ? Enter the file name pattern of graphql queries, mutations and subscriptions: /graphql/**/*.ts
  • ? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions? Y
  • ? Enter maximum statement depth [increase from default if your schema is deeply nested]: 4
  • ? Enter the file name for the generated code: /graphql/API.ts
  • ? Do you want to generate code for your newly created GraphQL API? Y

Add hosting

Finally, setup hosting for the front-end:
amplify hosting add

  • ? Select the plugin module to execute: Hosting with Amplify Console
  • ? Choose a type: Continuous deployment

Sign into AWS and link your GitHub repository to Amplify Console.
When the environment has been set up, go to the Environment variables page from the left menu, and click Manage variables.

Add a new variable called NEXT_PUBLIC_CLOUD_ENV with the value dev.

Amplify will create a hosted URL for you.
Go to the file front-end/deployment/config/config-development.ts again, and add the URL here:

/**
 * Add your hosted dev URL here
 */
const HOSTED_URL = '<ADD-YOUR-HOSTED-URL-HERE>';

Finally, run:
amplify push
amplify publish

Let Amplify do it's thing 😎

Start the app locally

Start the app by running npm run dev.
The app will start locally on http://localhost:3000.

Create a new user by going to the /signup page.
Sign into the app by going to the /signin page.

Authentication should work smoothly at this point - now, start building your SaaS 🚀

ℹ️ Additional info

If you want to use different environments (dev and prod), simply set up Pulumi in a different environment, and paste the output into the front-end/deployment/config/config-production.ts.

Similarly, create an environment variable in the Amplify Console for the production environment called NEXT_PUBLIC_CLOUD_ENV with the value prod.

Get Help

Contribute

PRs are welcome!