Skip to main content

Use Next.js with SST

Create and deploy a Next.js app to AWS with SST and OpenNext.


Prerequisites

You'll need at least Node.js 16 and npm 7. You also need to have an AWS account and AWS credentials configured locally.


1. Create a new app

Create a new Next.js app.

npx create-next-app@latest

Now initialize SST in your project root.

cd my-app
npx create-sst@latest
Ready to deploy

Your Next.js app is now ready to be deployed to AWS! Just run — npx sst deploy. But let's take a second to look at how SST makes it easy to add other features to your app.

Start your local dev environment.

# Start SST locally
npx sst dev
# Start Next.js locally
npm run dev

2. Add file uploads

Let's add a file upload feature to our Next.js app.


Add an S3 bucket

Add an S3 bucket to your sst.config.ts.

sst.config.ts
const bucket = new Bucket(stack, "public");

Bind it to your Next.js app.

sst.config.ts
const site = new NextjsSite(stack, "site", {
+ bind: [bucket],
});

Generate a presigned URL

To upload a file to S3 we'll generate a presigned URL. Add this to pages/index.tsx.

pages/index.tsx
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);

return { props: { url } };
}
tip

With SST we can access our infrastructure in a typesafe way — Bucket.public.bucketName. Learn more.


Add an upload form

Let's add the form. Replace the Home component in pages/index.tsx with.

pages/index.tsx
export default function Home({ url }: { url: string }) {
return (
<main>
<form
onSubmit={async (e) => {
e.preventDefault();

const file = (e.target as HTMLFormElement).file.files?.[0]!;

const image = await fetch(url, {
body: file,
method: "PUT",
headers: {
"Content-Type": file.type,
"Content-Disposition": `attachment; filename="${file.name}"`,
},
});

window.location.href = image.url.split("?")[0];
}}
>
<input name="file" type="file" accept="image/png, image/jpeg" />
<button type="submit">Upload</button>
</form>
</main>
);
}

This will upload an image and redirect to it!


3. Add a cron job

Next, we'll add a cron job to remove the uploaded files every day. Add this to sst.config.ts.

sst.config.ts
new Cron(stack, "cron", {
schedule: "rate(1 day)",
job: {
function: {
bind: [bucket],
handler: "functions/delete.handler",
},
},
});

Just like our Next.js app, we are binding the S3 bucket to our cron job.


Add a cron function

Add a function to functions/delete.ts that'll go through all the files in the bucket and remove them.

functions/delete.ts
export async function handler() {
const client = new S3Client({});

const list = await client.send(
new ListObjectsCommand({
Bucket: Bucket.public.bucketName,
})
);

await Promise.all(
(list.Contents || []).map((file) =>
client.send(
new DeleteObjectCommand({
Key: file.Key,
Bucket: Bucket.public.bucketName,
})
)
)
);
}

And that's it. We have a simple Next.js app that uploads files to S3 and runs a cron job to delete them!


4. Deploy to prod

Let's end with deploying our app to production.

npx sst deploy --stage prod
note

The sst deploy command internally uses OpenNext to build your app.

Next.js app deployed to AWS with SST

info

View the source for this example on GitHub.


Next steps

  1. Learn more about SST
  2. Have a Next.js app on Vercel? Migrate it to SST.
  3. Ready to dive into the details of SST? Check out our tutorial.