How To Deploy A Nextjs App With Custom Domain On AWS Using SST
How To Deploy A Nextjs App With Custom Domain On AWS Using SST
Arunachalam B
Serverless architectures have transformed the way we build and deploy
applications in the cloud, bringing in more efficiency and scalability.
In this article, we'll dive into the Serverless Stack Toolkit (SST), a framework for
building serverless applications. We'll deploy a Next.js application and set up a custom
domain, all without visiting the AWS console.
1/18
With serverless, developers are billed based on actual usage rather than fixed server costs,
making it a cost-effective and scalable solution. It offers increased flexibility and agility, as
resources are automatically allocated and released based on demand. This eliminates the
need for developers to worry about infrastructure management.
Now that we have a good idea of what serverless means, let's see what the Serverless Stack
Toolkit (SST) is.
It aims to make it easier for developers to define their application's infrastructure using AWS
CDK (Cloud Development Kit).
You can use it to test applications in real-time with Live Lambda Development, debug code in
Visual Studio Code, manage applications through a web-based dashboard, and deploy to
multiple environments and regions seamlessly.
Infrastructure as Code
With SST, developers can define their application's infrastructure programmatically using
AWS CDK. This improves version control and collaboration among team members.
SST enables live Lambda development, making it easier to test and debug serverless
applications locally before deployment to AWS. This reduces potential issues and ensures
smoother deployment.
Simplified Deployment
Language Flexibility
SST supports multiple programming languages, including JavaScript, TypeScript, Go,
Python, C#, and F#, providing developers with the flexibility to use their preferred language
for building serverless applications.
2/18
Now that we have understood what SST is and some of its benefits, let's see the power of
SST in action.
aws configure
AWS Configure
You'll be required to enter your AWS Access Key ID, Secret Access Key, Region name and
output format. If you don't have these keys, please create an IAM user and enter the
credentials.
In this article, we'll create new Next.js project and add SST which follows drop-in mode
installation using the commands below:
Note: You should ensure that you have the index.tsx file inside the /pages folder. Without
the file, you'll get errors while deploying your app using SST. You don't need to make any
changes to this file.
3/18
Folder structure
Once you run the above commands, SST will create two new files —sst.config.ts and
sst-env.d.ts
We have to define all our infrastructure and stacks in the sst.config.ts file.
On executing the yarn sst dev command, you'll be asked to enter the stage name. Please
enter your environment name. I'll use dev for this project's stage name.
4/18
Just sit back and watch. It will automatically create the necessary IAM roles, permissions and
CloudFormation stacks.
Notice in the image above that you can see the Console URL,
https://console.sst.dev/sst-demo/dev. With the Console URL, you can view real-time
logs, invoke functions, replay invocations, make queries, run migrations, view uploaded files,
query your GraphQL APIs, and more!
Just awesome right? I would recommend you to visit the official documentation to learn more
about the services they offer.
Next, start the Next.js site by running yarn dev. You should see the default page after that.
5/18
Next.js default page
Our Next.js app is now ready to be deployed to AWS! Just run the following command and
see the magic.
6/18
OpenNext building the Next.js App
It will automatically start building the app using OpenNext , deploy it to AWS using CDK, and
output the CloudFront URL. Click on the link and you should be able to see your app up and
running.
Let's add a simple S3 file upload feature. Open sst.config.ts file and add the code below:
7/18
import { SSTConfig } from "sst";
import {Bucket, NextjsSite } from "sst/constructs";
export default {
config(_input) {
return {
name: "sst-tutorial",
region: "us-east-1",
};
},
stacks(app) {
app.stack(function Site({ stack }) {
const bucket = new Bucket(stack, "public");
const site = new NextjsSite(stack, "site",{
bind:[bucket],
});
stack.addOutputs({
SiteUrl: site.url,
});
});
},
} satisfies SSTConfig;
Here, we're creating a new public S3 bucket and binding it with our NextjsSite.
Open index.tsx file and create a function called getServerSideProps above the Home
function, as shown in the below code snippet.
8/18
...
import { Bucket } from "sst/node/bucket";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
...
export async function getServerSideProps() {
const command = new PutObjectCommand({
ACL: "public-read",
Key: crypto.randomUUID(),
Bucket: Bucket.public.bucketName,
});
const url = await getSignedUrl(new S3Client({}), command);
const bucketName = Bucket.public.bucketName
console.log(bucketName)
return { props: { url } };
}
9/18
import styles from "@/styles/Home.module.css";
export default function Home({ url }: { url: string }) {
return (
<main className={styles.main}>
<div className={styles.center}>
<a
href="https://5minslearn.gogosoon.com/?ref=github_sst_app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2 className={inter.className}>
5minslearn <span>-></span>
</h2>
<p className={inter.className}>Learn tech in 5mins</p>
</a>
</div>
<form
className={styles.form}
onSubmit={async (e) => {
e.preventDefault();
window.location.href = image.url.split("?")[0];
}}
>
<input name="file" type="file" accept="image/png, image/jpeg" />
<button type="submit" className={inter.className}>
Upload
</button>
</form>
</main>
);
}
I added an input with a file type and a button for submitting the form. The selected image will
be uploaded to S3 when the form is submitted. It's time to deploy the changes.
10/18
Next.js up and running with updated changes
Now you can upload any image and check your S3. The selected file will be uploaded to your
S3 bucket.
Great, we have successfully deployed the changes. But we still have the random URL
generated by CloudFront which may be difficult to memorize for humans. Let's configure a
custom domain.
If you have a domain on an external DNS provider, you'll need to create an SSL certificate on
AWS Certificate Manager (ACM).
I have my domain on Cloudflare. If you have yours with other providers like Namecheap or
GoDaddy, then the steps below should still work for you.
11/18
1. Login into your DNS provider.
2. Add a CNAME. In my case, I used aws as the name because my domain is
aws.gogosoon.com, and target as the CloudFront URL without https.
We've successfully pointed our CNAME to CloudFront. Now let's create an SSL certificate for
our domain.
However, there is a specific requirement for using ACM certificates with CloudFront: the
certificate must be created in the US East (N. Virginia) region (us-east-1). The reason for
this is that CloudFront has all of its provisioning/administrative infrastructure based in us-
east-1.
12/18
AWS ACM - Request Certificate
3. Enter the domain name you pointed to in your DNS provider configuration. Under
"Validation method", select "Email validation" and click next.
4. A certificate with the status of "Pending Validation" will be created. You'll receive an
email from AWS with a link to validate the request.
13/18
ACM certificate with pending status
5. Once you click on the link in the email, the status of the certificate will be changed to
"Issued". Copy the ARN – we'll need it in the next steps.
Now that we've created the certificate successfully, let's create the alternate domain for
CloudFront.
14/18
Edit CloudFront distribution
4. Enter the alternate domain name and select the certificate that we created. Leave all
other options as default and click on the "Save changes" button.
15/18
All set! Let's edit our app to deploy the changes to our custom domain.
export default {
config(_input) {
return {
name: "sst-tutorial",
region: "us-east-1",
};
},
stacks(app) {
app.stack(function Site({ stack }) {
const bucket = new Bucket(stack, "public");
const certArn = 'Paste the certificate arn'
const site = new NextjsSite(stack, "site",{
bind:[bucket],
customDomain: {
isExternalDomain: true,
domainName: "aws.gogosoon.com",
cdk: {
certificate: Certificate.fromCertificateArn(stack, "MyCert", certArn),
},
},
});
stack.addOutputs({
SiteUrl: site.customDomainUrl || site.url,
});
});
},
} satisfies SSTConfig;
16/18
sst.config.ts - File changes
Run yarn sst deploy to deploy the changes to a custom domain. Once deployed, you
should have the app running on the custom URL.
17/18
Next.js app up and running with custom domain
Conclusion
Voila! Our Next.js app is now deployed to AWS, and we've connected it with our custom
domain. Please check out the source code here.
The SST framework provides an excellent toolset for deploying serverless applications,
contributing significantly to development speed, scalability, and error handling.
Feel free to explore more about SST and its potential in transforming your cloud
development experience. Happy coding!
If you wish to learn more about AWS Services, subscribe to my email newsletter
(https://5minslearn.gogosoon.com/) and follow me on social media.
Arunachalam B
Read more posts.
Learn to code for free. freeCodeCamp's open source curriculum has helped more than
40,000 people get jobs as developers. Get started
18/18