The Next.js marketing site promises server-side rendering, but your landing page doesn't need a Node.js process burning CPU for every request. A static export turns your React components into plain HTML at build time, then a CDN serves them globally with zero idle cost.
The catch: Next.js hides the static export behind a configuration flag, and forgetting output: 'export' means your build succeeds but deploys as a container instead of static files. PandaStack detects the export automatically when it's configured correctly, but you need to tell Next.js to create one first.
Configure the static export
Open next.config.js and add the output field:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
trailingSlash: true,
images: {
unoptimized: true
}
}
module.exports = nextConfigThe unoptimized: true line disables Next.js Image Optimization because it requires a server. Use standard tags or a third-party image CDN instead.
Build locally to verify it works:
npm run buildNext.js writes static files to out/. That directory becomes the deploy artifact.
Add the deploy button
Create a pandastack.json in your repository root so the deploy button knows where the built files live:
{
"type": "static",
"language": "nodejs",
"buildCommand": "npm run build",
"outputDir": "out"
}Now add the badge to your README.md:
[](https://dashboard.pandastack.io/deploy?repo=your-username/your-repo)Replace your-username/your-repo with your GitHub repository path. When someone clicks the button, PandaStack reads pandastack.json from the main branch, pre-fills the form, and prompts them to confirm. One click later, they have a running copy of your site.
How it deploys
Push the changes to GitHub and click your own button. The deploy screen shows:
- Type: Static
- Build command:
npm run build - Output directory:
out
Confirm, and PandaStack clones the repo, installs dependencies with npm install, runs the build command, and uploads everything from out/ to a CDN. The entire process streams to the Logs tab in real time.
Your site goes live at https:// with automatic HTTPS. HTML is edge-cached, and hashed assets like _next/static/chunks/main-abc123.js are served with immutable cache headers.
Verify the output
Static exports break server-dependent features silently. Test these before you assume everything works:
getServerSideProps: removed at build time; pages that use it won't render- Dynamic routes without
getStaticPaths: 404 at runtime - API routes: gone; a static site has no backend
If your app needs any of those, deploy it as a container instead (remove output: 'export' and let PandaStack detect the next start command). For a marketing site or documentation, the static export is faster and cheaper.
Deploy from the CLI
The deploy button is for distribution. For your own workflow, use the CLI:
panda login
panda projects create \
--name my-nextjs-site \
--repo your-username/your-repo \
--branch main \
--auto-deployPandaStack reads pandastack.json the same way the button does, so you don't repeat the build configuration. Redeploy on every push with --auto-deploy, or trigger manually with panda projects deploy .
What's happening under the hood
A static deploy doesn't run a pod. The build process uploads your files to object storage, then a CDN (backed by Kong ingress with Cloudflare DNS) serves them. Requests never touch Kubernetes. When you redeploy, the cache purges automatically and new content appears within seconds.
Free-tier bandwidth is 100 GB per month, which is enough for most side projects. Pro ($15/mo) bumps it to 500 GB. If you exceed the quota, the site stays online but you get billed for overage.
Common deploy button mistakes
Wrong repository format: Use owner/repo, not a full GitHub URL. https://github.com/acme/site fails; acme/site works.
Private repositories: The deploy button reads pandastack.json from GitHub's public API, which fails for private repos. Use the dashboard or CLI instead, and PandaStack authenticates with your connected GitHub account.
Missing outputDir: If pandastack.json omits outputDir, PandaStack guesses build or dist. Next.js uses out, so specify it explicitly or the deploy succeeds with an empty site.
Add environment variables
Static sites can't read server-side secrets, but build-time variables work. If your app calls an API during next build, inject the URL:
{
"type": "static",
"buildCommand": "npm run build",
"outputDir": "out",
"env": [
{
"key": "NEXT_PUBLIC_API_URL",
"description": "Base URL for the backend API"
}
]
}The deploy screen prompts for NEXT_PUBLIC_API_URL before starting the build. The value becomes available as process.env.NEXT_PUBLIC_API_URL during the build, and Next.js bakes it into the client-side bundle.
References
- [Next.js static exports](https://nextjs.org/docs/app/building-your-application/deploying/static-exports)
- [PandaStack deploy button docs](https://docs.pandastack.io/projects/deploy-button)
- [Static site deployment](https://docs.pandastack.io/projects/static)