Skip to main content

Frontend

SST makes it easy to connect your web or mobile frontends to your backend resources. For web apps, SST also allows you to deploy them to AWS.

Let's start by looking at web apps.

Web apps

SST provides a couple of constructs that allow you to build and deploy your web app to AWS. Internally these static sites are stored in S3, served through a CloudFront CDN for fast content delivery, and use Amazon Route 53 for custom domains.

Frameworks

SST provides out of the box support for Create React App, Vite, Next.js, and any static site framework through the ReactStaticSite, ViteStaticSite, NextjsSite, and StaticSite construct.

new ReactStaticSite(stack, "React", {
path: "path/to/site",
});

Here the path points to the location of the frontend app. Note that the frontend app is built alongside the backend resources in the SST app. We'll look at why this is helpful below.

Example

Here are a couple of examples using your favorite frontend frameworks to build a simple full-stack click counter app with SST:

CDN

SST deploys the static content of your web app to an S3 bucket, and then points a CloudFront distribution to the bucket. All static contents are served out from the CDN. The CDN cache is invalidated on every deploy.

Domains

You can configure a custom domain (ie. domain.com) for your web app. And SST will also setup the http to https redirect. Visitors to the http://domain.com URL will be redirected to the https://domain.com.

new ReactStaticSite(stack, "React", {
path: "path/to/site",
customDomain: "domain.com",
});

Domain Alias

If a domain alias is configured, visitors to the alias domain will be redirected to the main one. So if www.domain.com is the domain alias for domain.com, visitors to www.domain.com will be redirected to domain.com.

new ReactStaticSite(stack, "React", {
path: "path/to/site",
customDomain: {
domainName: "domain.com",
domainAlias: "www.domain.com",
},
});

Environment variables

A benefit of deploying the frontend web app alongside the backend is to be able to pass backend resource references directly into the frontend code. This is done through the environment prop.

const api = new Api(stack, "Api", {
routes: {
"GET /": "src/lambda.main",
},
});

new ReactStaticSite(stack, "React", {
path: "path/to/site",
environment: {
REACT_APP_API_URL: api.url,
},
});

You can now reference the environment variable in your web app.

fetch(process.env.REACT_APP_API_URL);

How passing environment variables works

If an environment contains a dynamic value that'll only be known after deploy, SST first builds the web app with a placeholder value, and then replaces the placeholder with the real value after deploying. In the example above, api.url is a dynamic value. The url is not known at build time if the Api construct has not been previously deployed. And the value can change if Api is to be replaced during deployment.

Given the following environment setting.

environment: {
REACT_APP_HELLO: "world",
REACT_APP_API_URL: api.url,
}

SST builds the app with placeholders.

$ REACT_APP_API_URL="{{ REACT_APP_API_URL }}" REACT_APP_HELLO="world" npm run build

After the Api construct is deployed, SST will replace all occurrences of {{ REACT_APP_API_URL }} with the real value.

Editor autocomplete

The ViteStaticSite construct also creates a type definition file for the environment variables in src/sst-env.d.ts. This tells your editor the environment variables that are available and autocompletes them for you.

Vite environment variables autocomplete

Next.js limitation

Since dynamic environment values are not known at build time, they cannot be used to fetch data in getStaticProps.

Local development

To use the above environment variables while developing, first run sst start to start the local environment.

npm start

Then in your frontend app add the sst-env npm package to reference these variables.

npm install --save-dev @serverless-stack/static-site-env
# or
yarn add --dev @serverless-stack/static-site-env

And tweak the start script in your package.json to.

package.json
"scripts": {
"start": "sst-env -- react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},

Now you can start your app as usual and it'll have the environment variables from your SST app.

Note that, the sst-env CLI will traverse up the directories to look for the root of your SST app. If the static site or Next.js app is located outside the SST app folder, pass in --path to specify the relative path of the SST app.

package.json
"scripts": {
"start": "sst-env --path ../backend -- react-scripts start",
},

There are a couple of things happening behind the scenes here:

  1. The sst start command generates a file with the values specified by StaticSite, ReactStaticSite, ViteStaticSite, or NextjsSite construct's environment prop.
  2. The sst-env CLI will traverse up the directories to look for the root of your SST app. If the static site or Next.js app is located outside the SST app folder, pass in --path to specify the relative path of the SST app.
  3. It'll then find the file that's generated in step 1.
  4. It'll load these as environment variables before running the start command.

Mobile apps

For mobile apps, you want to make sure to set the references to the backend resources as environment variables.

We have a couple of examples of creating mobile apps with Expo and Flutter.

Example

Learn how to build a click counter native mobile app with Expo, Flutter, and SST.