Skip to content

StaticSite

Reference doc for the `sst.aws.StaticSite` component.

The StaticSite component lets you deploy a static website to AWS. It uses Amazon S3 to store your files and Amazon CloudFront to serve them.

It can also build your site by running your static site generator, like Vite and uploading the build output to S3.

Minimal example

Simply uploads the current directory as a static site.

new sst.aws.StaticSite("MyWeb");

Change the path

Change the path that should be uploaded.

new sst.aws.StaticSite("MyWeb", {
path: "path/to/site"
});

Running locally

In sst dev, we don’t deploy your site to AWS because we assume you are running it locally.

For example, for a Vite site, you can run it locally with.

Terminal window
sst dev vite dev

This will start the Vite dev server and pass in any environment variables that you’ve set in your config. But it will not deploy your site to AWS.

Deploy a Vite SPA

Use Vite to deploy a React/Vue/Svelte/etc. SPA by specifying the build config.

new sst.aws.StaticSite("MyWeb", {
build: {
command: "npm run build",
output: "dist"
}
});

Deploy a Jekyll site

Use Jekyll to deploy a static site.

new sst.aws.StaticSite("MyWeb", {
errorPage: "404.html",
build: {
command: "bundle exec jekyll build",
output: "_site"
}
});

Deploy a Gatsby site

Use Gatsby to deploy a static site.

new sst.aws.StaticSite("MyWeb", {
errorPage: "404.html",
build: {
command: "npm run build",
output: "public"
}
});

Deploy an Angular SPA

Use Angular to deploy a SPA.

new sst.aws.StaticSite("MyWeb", {
build: {
command: "ng build --output-path dist",
output: "dist"
}
});

Add a custom domain

Set a custom domain for your site.

new sst.aws.StaticSite("MyWeb", {
domain: "my-app.com"
});

Redirect www to apex domain

Redirect www.my-app.com to my-app.com.

new sst.aws.StaticSite("MyWeb", {
domain: {
name: "my-app.com",
redirects: ["www.my-app.com"]
}
});

Set environment variables

Set environment variables for the build process of your static site. These will be used locally and on deploy.

For some static site generators like Vite, environment variables prefixed with VITE_ can be accessed in the browser.

const bucket = new sst.aws.Bucket("MyBucket");
new sst.aws.StaticSite("MyWeb", {
environment: {
BUCKET_NAME: bucket.name,
// Accessible in the browser
VITE_STRIPE_PUBLISHABLE_KEY: "pk_test_123"
},
build: {
command: "npm run build",
output: "dist"
}
});

Constructor

new StaticSite(name, args?, opts?)

Parameters

StaticSiteArgs

assets?

Type Input<Object>

Default Object

Configure how the static site’s assets are uploaded to S3.

By default, this is set to the following. Read more about these options below.

{
assets: {
textEncoding: "utf-8",
fileOptions: [
{
files: ["**/*.css", "**/*.js"],
cacheControl: "max-age=31536000,public,immutable"
},
{
files: "**/*.html",
cacheControl: "max-age=0,no-cache,no-store,must-revalidate"
}
]
}
}

assets.fileOptions?

Type Input<Object[]>

Default Object[]

Specify the Content-Type and Cache-Control headers for specific files. This allows you to override the default behavior for specific files using glob patterns.

By default, this is set to cache CSS/JS files for 1 year and not cache HTML files.

{
assets: {
fileOptions: [
{
files: ["**/*.css", "**/*.js"],
cacheControl: "max-age=31536000,public,immutable"
},
{
files: "**/*.html",
cacheControl: "max-age=0,no-cache,no-store,must-revalidate"
}
]
}
}

You can change the default options. For example, apply Cache-Control and Content-Type to all zip files.

{
assets: {
fileOptions: [
{
files: "**/*.zip",
contentType: "application/zip",
cacheControl: "private,no-cache,no-store,must-revalidate"
},
],
}
}

Apply Cache-Control to all CSS and JS files except for CSS files with index- prefix in the main/ directory.

{
assets: {
fileOptions: [
{
files: ["**/*.css", "**/*.js"],
ignore: "main/index-*.css",
cacheControl: "private,no-cache,no-store,must-revalidate"
},
],
}
}
assets.fileOptions[].cacheControl?

Type string

The Cache-Control header to apply to the matched files.

assets.fileOptions[].contentType?

Type string

The Content-Type header to apply to the matched files.

assets.fileOptions[].files

Type string | string[]

A glob pattern or array of glob patterns of files to apply these options to.

assets.fileOptions[].ignore?

Type string | string[]

A glob pattern or array of glob patterns of files to exclude from the ones matched by the files glob pattern.

assets.textEncoding?

Type Input<none | ascii | utf-8 | iso-8859-1 | windows-1252>

Default “utf-8”

Character encoding for text based assets uploaded, like HTML, CSS, JS. This is used to set the Content-Type header when these files are served out.

If set to "none", then no charset will be returned in header.

{
assets: {
textEncoding: "iso-8859-1"
}
}

build?

Type Input<Object>

Configure if your static site needs to be built. This is useful if you are using a static site generator.

The build.output directory will be uploaded to S3 instead.

For a Vite project using npm this might look like this.

{
build: {
command: "npm run build",
output: "dist"
}
}

build.command

Type Input<string>

The command that builds the static site. It’s run before your site is deployed. This is run at the root of your site, path.

{
build: {
command: "yarn build"
}
}

build.output

Type Input<string>

The directory where the build output of your static site is generated. This will be uploaded.

The path is relative to the root of your site, path.

{
build: {
output: "build"
}
}

domain?

Type Input<string | Object>

Set a custom domain for your static site. Supports domains hosted either on Route 53 or outside AWS.

{
domain: "domain.com"
}

Specify a www. version of the custom domain.

{
domain: {
name: "domain.com",
redirects: ["www.domain.com"]
}
}

domain.aliases?

Type Input<string[]>

Alias domains that should be used. Unlike the redirect option, this keeps your visitors on this alias domain.

So if your users visit app2.domain.com, they will stay on app2.domain.com in their browser.

{
domain: {
name: "app1.domain.com",
aliases: ["app2.domain.com"]
}
}

domain.cert?

Type Input<string>

The ARN of an ACM (AWS Certificate Manager) certificate that proves ownership of the domain. By default, a certificate is created and validated automatically.

The certificate will be created in the us-east-1 region as required by AWS CloudFront. If you are creating your own certificate, you must also create it in us-east-1.

To manually set up a domain on an unsupported provider, you’ll need to:

  1. Validate that you own the domain by creating an ACM certificate. You can either validate it by setting a DNS record or by verifying an email sent to the domain owner.
  2. Once validated, set the certificate ARN as the cert and set dns to false.
  3. Add the DNS records in your provider to point to the CloudFront distribution URL.
{
domain: {
name: "domain.com",
dns: false,
cert: "arn:aws:acm:us-east-1:112233445566:certificate/3a958790-8878-4cdc-a396-06d95064cf63"
}
}

domain.dns?

Type Input<false | sst.aws.dns | sst.cloudflare.dns | sst.vercel.dns>

Default sst.aws.dns

The DNS provider to use for the domain. Defaults to the AWS.

Takes an adapter that can create the DNS records on the provider. This can automate validating the domain and setting up the DNS routing.

Supports Route 53, Cloudflare, and Vercel adapters. For other providers, you’ll need to set dns to false and pass in a certificate validating ownership via cert.

Specify the hosted zone ID for the Route 53 domain.

{
domain: {
name: "example.com",
dns: sst.aws.dns({
zone: "Z2FDTNDATAQYW2"
})
}
}

Use a domain hosted on Cloudflare, needs the Cloudflare provider.

{
domain: {
name: "example.com",
dns: sst.cloudflare.dns()
}
}

Use a domain hosted on Vercel, needs the Vercel provider.

{
domain: {
name: "example.com",
dns: sst.vercel.dns()
}
}

domain.name

Type Input<string>

The custom domain you want to use.

{
domain: {
name: "example.com"
}
}

Can also include subdomains based on the current stage.

{
domain: {
name: `${$app.stage}.example.com`
}
}

domain.redirects?

Type Input<string[]>

Alternate domains to be used. Visitors to the alternate domains will be redirected to the main name.

Use this to create a www. version of your domain and redirect visitors to the apex domain.

{
domain: {
name: "domain.com",
redirects: ["www.domain.com"]
}
}

environment?

Type Input<Record<string, Input<string>>>

Set environment variables for your static site. These are made available:

  1. Locally while running your site through sst dev.
  2. In the build process when running build.command.
environment: {
API_URL: api.url
STRIPE_PUBLISHABLE_KEY: "pk_test_123"
}

Some static site generators like Vite have their concept of environment variables, and you can use this option to set them.

These can be accessed as import.meta.env in your site. And only the ones prefixed with VITE_ can be accessed in the browser.

environment: {
API_URL: api.url
// Accessible in the browser
VITE_STRIPE_PUBLISHABLE_KEY: "pk_test_123"
}

errorPage?

Type Input<string>

Default The indexPage of your site.

The error page to display on a 403 or 404 error. This is a path relative to the root of your site, or the path.

{
errorPage: "404.html"
}

indexPage?

Type string

Default “index.html”

The name of the index page of the site. This is a path relative to the root of your site, or the path.

By default this is set to index.html. So if a visitor goes to your site, let’s say example.com, example.com/index.html will be served.

{
indexPage: "home.html"
}

invalidation?

Type Input<false | Object>

Default {paths: “all”, wait: false}

Configure how the CloudFront cache invalidations are handled. This is run after your static site has been deployed.

Turn off invalidations.

{
invalidation: false
}

Wait for all paths to be invalidated.

{
invalidation: {
paths: "all",
wait: true
}
}

invalidation.paths?

Type Input<string[] | all>

Default “all”

The paths to invalidate.

You can either pass in an array of glob patterns to invalidate specific files. Or you can use the built-in option all to invalidation all files when any file changes.

Invalidate the index.html and all files under the products/ route.

{
invalidation: {
paths: ["/index.html", "/products/*"]
}
}

invalidation.wait?

Type Input<boolean>

Default false

Configure if sst deploy should wait for the CloudFront cache invalidation to finish.

Waiting for the CloudFront cache invalidation process to finish ensures that the new content will be served once the deploy finishes. However, this process can sometimes take more than 5 mins.

{
invalidation: {
wait: true
}
}

path?

Type Input<string>

Default ”.”

Path to the directory where your static site is located. By default this assumes your static site is in the root of your SST app.

This directory will be uploaded to S3. The path is relative to your sst.config.ts.

If you are using a static site generator, like Vite, you’ll need to configure the build options. When these are set, the build.output directory will be uploaded to S3 instead.

Change where your static site is located.

{
path: "packages/web"
}

transform?

Type Object

Transform how this component creates its underlying resources.

transform.assets?

Type BucketArgs | (args: BucketArgs => void)

Transform the Bucket resource used for uploading the assets.

transform.cdn?

Type CdnArgs | (args: CdnArgs => void)

Transform the CloudFront CDN resource.

vite?

Type Input<Object>

Configure Vite related options.

vite.types?

Type string

Default “src/sst-env.d.ts”

The path where the type definition for the environment variables are generated. This is relative to the path. Read more.

{
vite: {
types: "other/path/sst-env.d.ts"
}
}

Properties

nodes

Type Object

The underlying resources this component creates.

nodes.assets

Type Bucket

The Amazon S3 Bucket that stores the assets.

nodes.cdn

Type Cdn

The Amazon CloudFront CDN that serves the site.

url

Type Output<string>

The URL of the website.

If the domain is set, this is the URL with the custom domain. Otherwise, it’s the autogenerated CloudFront URL.

SDK

The following are accessible through the SDK at runtime.

url

Type string

The URL of the website.

If the domain is set, this is the URL with the custom domain. Otherwise, it’s the autogenerated CloudFront URL.