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.

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

Change the path

Change the path that should be uploaded.

sst.config.ts
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.

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

Deploy a Jekyll site

Use Jekyll to deploy a static site.

sst.config.ts
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.

sst.config.ts
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.

sst.config.ts
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.

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

Redirect www to apex domain

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

sst.config.ts
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.

sst.config.ts
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 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.bucket?

Type Input<string>

Default Creates a new bucket

The name of the S3 bucket to upload the assets to.

{
assets: {
bucket: "my-existing-bucket"
}
}

When using an existing bucket, ensure that the bucket has a policy that allows CloudFront to access the bucket. For example, the bucket policy might look like this:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-existing-bucket/*"
}
]
}

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.path?

Type Input<string>

Default Root of the bucket

The path into the S3 bucket where the assets should be uploaded.

{
assets: {
path: "websites/my-website"
}
}

assets.purge?

Type Input<boolean>

Default true

Configure if files from previous deployments should be purged from the bucket.

{
assets: {
purge: false
}
}

assets.textEncoding?

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

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"
}
}

dev?

Type false | Object

Configure how this component works in sst dev.

Instead of deploying your static site, this starts it in dev mode. It’s run as a separate process in the sst dev multiplexer. Read more about sst dev.

To disable dev mode, pass in false.

dev.autostart?

Type Input<boolean>

Default true

Configure if you want to automatically start this when sst dev starts. You can still start it manually later.

dev.command?

Type Input<string>

Default “npm run dev”

The command that sst dev runs to start this in dev mode.

dev.directory?

Type Input<string>

Default Uses the path

Change the directory from where the command is run.

dev.title?

Type Input<string>

The title of the tab in the multiplexer.

dev.url?

Type Input<string>

Default http://url-unavailable-in-dev.mode

The url when this is running in dev mode.

Since this component is not deployed in sst dev, there is no real URL. But if you are using this component’s url or linking to this component’s url, it can be useful to have a placeholder URL. It avoids having to handle it being undefined.

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"]
}
}

edge?

Type Input<Object>

Configure CloudFront Functions to customize the behavior of HTTP requests and responses at the edge.

edge.viewerRequest?

Type Input<string | Object>

Configure the viewer request function.

The viewer request function can be used to modify incoming requests before they reach your origin server. For example, you can redirect users, rewrite URLs, or add headers.

By default, a viewer request function is created to:

  • Disable CloudFront default URL if custom domain is set.
  • Rewrite URLs to append index.html to the URL if the URL ends with a /.
  • Rewrite URLs to append .html to the URL if the URL does not contain a file extension.

You can pass in the code to inject into the function. The provided code will be injected at the end of the function.

async function handler(event) {
// Default behavior code
// User injected code
return event.request;
}

To add a custom header to all requests.

{
edge: {
viewerRequest: {
injection: `event.request.headers["x-foo"] = "bar";`
}
}
}

You can use this add basic auth, check out an example. Alternatively you can pass in the ARN of an existing CloudFront function to override the default behavior.

{
edge: {
viewerRequest: "arn:aws:cloudfront::123456789012:function/my-function"
}
}
edge.viewerRequest.injection

Type Input<string>

The code to inject into the viewer request function.

To add a custom header to all requests.

{
edge: {
viewerRequest: {
injection: `event.request.headers["x-foo"] = "bar";`
}
}
}
edge.viewerRequest.kvStores?

Type Input<Input<string>[]>

The KV stores to associate with the viewer request function.

Takes a list of CloudFront KeyValueStore ARNs.

{
edge: {
viewerRequest: {
kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
}
}
}

edge.viewerResponse?

Type Input<string | Object>

Configure the viewer response function.

The viewer response function can be used to modify outgoing responses before they are sent to the client. For example, you can add security headers or change the response status code.

By default, no viewer response function is set. A new function will be created with the provided code.

You can pass in the code to inject into the function. And a CloudFront function will be created with the provided code injected into it.

async function handler(event) {
// User injected code
return event.response;
}

To add a custom header to all responses.

{
edge: {
viewerResponse: {
injection: `event.response.headers["x-foo"] = "bar";`
}
}
}

Alternatively you can pass in the ARN of an existing CloudFront function.

{
edge: {
viewerResponse: "arn:aws:cloudfront::123456789012:function/my-function"
}
}
edge.viewerResponse.injection

Type Input<string>

The code to inject into the viewer response function.

To add a custom header to all responses.

{
edge: {
viewerResponse: {
injection: `event.response.headers["x-foo"] = "bar";`
}
}
}
edge.viewerResponse.kvStores?

Type Input<Input<string>[]>

The KV stores to associate with the viewer response function.

Takes a list of CloudFront KeyValueStore ARNs.

{
edge: {
viewerResponse: {
kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
}
}
}

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, opts: ComponentResourceOptions, name: string) => void

Transform the Bucket resource used for uploading the assets.

transform.cdn?

Type CdnArgs | (args: CdnArgs, opts: ComponentResourceOptions, name: string) => 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 undefined | Bucket

The Amazon S3 Bucket that stores the assets.

nodes.cdn

Type undefined | 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

Use the SDK in your runtime to interact with your infrastructure.


This is accessible through the Resource object in the SDK.

  • url 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.