The Astro logo in dark blue with the SST logo behind in a slightly blurred background layer.

Deploy an Astro Site Using SST

Combine Astro's powerful and performant site generation capabilities with SST's streamlined deployment technology to make deployments seamless.

Astro is a powerful modern static site generator that focuses on performance and developer experience. With SST, deploying an Astro site to AWS becomes a streamlined and flexible process. In this blog post, we’ll walk through the configuration and deployment process of an Astro site using SST, including a detailed breakdown of the sst.config.ts file used in this setup.

What is SST?

SST (Serverless Stack) is an open-source framework that makes it easy to build serverless applications on AWS. SST simplifies the management of AWS infrastructure by allowing you to define cloud resources directly within your application’s code using TypeScript.

Step 1: Install SST and Astro

To get started, you’ll need to install SST and Astro in your project. Run the following commands to install both:

npm install sst astro-sst

This will install SST for managing your AWS infrastructure.

Step 2: Add SST stack file

SST uses a configuration file, sst.config.ts, to define how your infrastructure should be deployed to AWS. Below is a sample sst.config.ts file that sets up an Astro site with custom domain support and cache configuration.

sst.config.ts Breakdown

Here’s the configuration file we’ll use to deploy the Astro site:

import { AstroSite } from 'sst/constructs'
import type { SSTConfig } from 'sst'
import { Tags } from 'aws-cdk-lib'

export default {
  config(_input) {
    return {
      name: 'astro-website',
      region: 'us-west-2',
      bootstrap: {
        tags: {
          'Cost Center': 'Shared',
          Environment: 'Production',
          IaC: 'SST',
          Stack: 'IaC SST'
        }
      }
    }
  },
  stacks(app) {
    const isProdStage = app.stage === 'production'
    const hostedZone = 'example.com'
    const domainName = isProdStage ? hostedZone : `${app.stage}.${hostedZone}`
    const unversionedTTL = isProdStage ? 86400 : 3600
    const unversionedCacheControl = `public,max-age=${unversionedTTL},must-revalidate`

    const PUBLIC_SITE_URL = `https://${domainName}`

    Tags.of(app).add('Environment', isProdStage ? 'Production' : 'Development')
    Tags.of(app).add('IaC', 'SST')
    Tags.of(app).add('Stack', 'Astro Site')

    if (!isProdStage) {
      app.setDefaultRemovalPolicy('destroy')
    }

    app.stack(function Site({ stack }) {
      const site = new AstroSite(stack, 'astro-website', {
        memorySize: '1024 MB',
        customDomain: {
          domainName,
          hostedZone
        },
        environment: {
          PUBLIC_SITE_URL
        },
        assets: {
          fileOptions: [
            {
              files: '**/*.svg',
              cacheControl: unversionedCacheControl,
              contentType: 'image/svg+xml'
            },
            {
              files: '**/*.png',
              cacheControl: unversionedCacheControl,
              contentType: 'image/png'
            },
            {
              files: 'favicon.ico',
              cacheControl: unversionedCacheControl,
              contentType: 'image/x-icon'
            },
            {
              files: 'favicon.svg',
              cacheControl: unversionedCacheControl,
              contentType: 'image/svg+xml'
            },
            {
              files: 'site.webmanifest',
              cacheControl: unversionedCacheControl,
              contentType: 'application/manifest+json'
            }
          ],
          nonVersionedFilesCacheHeader: unversionedCacheControl
        }
      })
      stack.addOutputs({
        url: site.customDomainUrl
      })
    })
  }
} satisfies SSTConfig

Key Sections Explained:

  1. Project Configuration (config function)

    • The config function sets the project name (astro-website), the AWS region (us-west-2), and the bootstrap tags, which include meta information such as stack and the environment type for the SST bootstrap components (not the Astro site components).

    • These tags are helpful for managing infrastructure costs and differentiating environments (e.g., Production vs. Development).

  2. Stacks Setup (stacks function)

    • Stage Detection: This configuration checks if the current environment is production (app.stage === 'production') to customize certain settings such as the domain name and cache controls.

    • Domain and Cache Configuration:

      • In production, the site uses example.com, while in non-production stages, the domain is prefixed by the stage name (e.g., dev.example.com for the development environment).

      • Cache control is adjusted depending on the stage. In production, assets are cached for 24 hours (86400 seconds), and in development, they are cached for one hour (3600 seconds).

    • PUBLIC_SITE_URL: The URL of the deployed website is dynamically generated based on the domain and the stage.

  3. Tags:

    • Tags are added to the infrastructure to help with cost management and resource tracking. SST uses AWS CDK’s Tags module to apply tags, which are later visible in the AWS console.

    • For example, the tag Environment will reflect whether the current stack is in production or development.

  4. Site Stack (AstroSite):

    • The AstroSite construct is used to deploy the Astro site. It configures the site with:

      • Memory Size: 1024 MB allocated for the site.

      • Custom Domain: The domain is set to either the production domain or a stage-prefixed version, and the hosted zone (example.com) is provided for the domain name resolution.

      • Environment Variables: The public URL of the site is passed into the environment.

      • Assets Configuration: Specific file types such as .svg, .png, favicon.ico, and the web manifest file (site.webmanifest) are configured with appropriate cache control headers and content types.

    • Outputs: After deployment, SST outputs the custom domain URL of the site, which you can use to access your live Astro site.

Step 3: Configure Astro for SST Deployment

To ensure Astro is compatible with AWS Lambda, you need to update the astro.config.mjs file to use the AWS adapter.

import { defineConfig } from 'astro/config'
import aws from 'astro-sst'

export default defineConfig({
  output: 'static',
  adapter: aws({
    deploymentStrategy: 'static',
    serverRoutes: []
  }),
})

Key Changes:

Step 4: Deploy the Site

With the configuration in place, you can now deploy your Astro site using SST. First, run the following command to deploy the site:

npx sst deploy

This command will deploy your Astro site to AWS, provision the necessary resources (such as Lambda functions, S3 buckets, and CloudFront distributions), and configure the custom domain if specified.

Step 5: Access the Deployed Site

Once the deployment is complete, SST will output the URL of your site, which you can use to view the deployed version of your Astro website. If everything is configured correctly, your site will be live on AWS and accessible via the custom domain you specified.

Conclusion

Deploying an Astro site using SST makes it easy to manage serverless infrastructure on AWS. By leveraging SST’s constructs and CDK under the hood, you can focus on developing your site while letting SST handle the heavy lifting of deployment, scaling, and resource management.

With this approach, you can confidently deploy static sites with custom domains and optimized asset delivery, ensuring both performance and cost-efficiency.