Deploying NextJS
How to deploy Next.js to Freestyle
Next.js is a popular React framework for building full-stack web applications. This guide shows you how to deploy Next.js apps to Freestyle using the v2 SDK.
Prerequisites
- A Next.js application (create one with
npx create-next-app@latest) - Freestyle API key from the Freestyle Dashboard
- The Freestyle SDK installed:
npm install freestyle
Configure Next.js for Deployment
Next.js defaults to a serverless bundle that requires additional configuration. You need to set the output mode to standalone and disable image optimization (since Freestyle doesn't support Sharp binaries).
Update your next.config.mjs:
const nextConfig = {
output: "standalone", // Required for Freestyle deployment
images: {
unoptimized: true, // Disable Sharp image optimization
},
};
export default nextConfig;The standalone output mode creates a minimal production build that includes
only the necessary files for deployment.
Deployment Methods
There are two primary ways to deploy Next.js apps to Freestyle:
Method 1: Deploy from Git Repository (Recommended)
The simplest approach is to deploy directly from your Git repository. Freestyle will automatically detect Next.js and build it for you.
Sign up at dash.freestyle.sh, create an api key, and configure it in your environment.
FREESTYLE_API_KEY=your-api-keynpm i freestyleimport { freestyle } from "freestyle";
async function deploy() {
const { deployment, domains } = await freestyle.serverless.deployments.create(
{
repo: "https://github.com/your-username/your-nextjs-app",
// branch: "main", // Optional: specify branch
// rootPath: "./web", // Optional: for monorepos
domains: ["my-nextjs-app.style.dev"], // Use any available *.style.dev subdomain
build: true, // Freestyle auto-detects and builds Next.js
},
);
console.log("Deployed to:", domains);
console.log("Deployment ID:", deployment.deploymentId);
}
deploy();For Freestyle Git repositories, you can use the repository ID directly: ts repo: "your-repo-id-here" See the Git documentation for more
details.
Method 2: Deploy from Local Files
For more control over the build process, you can build locally and deploy the output using the new readFiles utility.
Step 1: Build Your Next.js App
npm run buildThis creates the production build in .next/standalone, along with static assets.
Step 2: Prepare Build Artifacts
Copy the necessary files to the standalone directory:
# Copy public files
cp -r public .next/standalone/public
# Copy static assets
cp -r .next/static .next/standalone/.next/static
# Copy your lockfile (for dependency installation)
cp package-lock.json .next/standalone/package-lock.jsonReplace package-lock.json with your package manager's lockfile: - npm:
package-lock.json - yarn: yarn.lock - pnpm: pnpm-lock.yaml - bun:
bun.lockb
Step 3: Deploy Using the SDK
Use the new readFiles utility to read all files from the standalone directory:
import { freestyle } from "freestyle";
import { readFiles } from "freestyle/utils";
async function deploy() {
// Read all files from the standalone output directory
const files = await readFiles(".next/standalone");
const { deployment, domains } = await freestyle.serverless.deployments.create(
{
files,
entrypointPath: "server.js", // Next.js standalone entrypoint
domains: ["my-nextjs-app.style.dev"], // Use any available *.style.dev subdomain
},
);
console.log("Deployed to:", domains);
console.log("Deployment ID:", deployment.deploymentId);
}
deploy();The readFiles utility:
- Automatically reads all files in the directory
- Excludes
node_modules/(Freestyle installs dependencies separately) - Base64-encodes file contents for reliable transmission
- Handles binary files correctly
Advanced Configuration
Environment Variables
Set environment variables for your Next.js app:
await freestyle.serverless.deployments.create({
repo: "https://github.com/your-username/your-nextjs-app",
build: true,
domains: ["app.style.dev"],
envVars: {
NEXT_PUBLIC_API_URL: "https://api.example.com",
DATABASE_URL: "postgresql://...",
},
});Network Permissions
Control which external domains your Next.js app can access:
await freestyle.serverless.deployments.create({
repo: "https://github.com/your-username/your-nextjs-app",
build: true,
domains: ["app.style.dev"],
networkPermissions: [
{
action: "allow",
domain: "api.stripe.com",
behavior: "exact",
},
{
action: "allow",
domain: ".*\\.amazonaws\\.com",
behavior: "regex",
},
],
});Custom Timeout
Increase the timeout for long-running requests:
await freestyle.serverless.deployments.create({
repo: "https://github.com/your-username/your-nextjs-app",
build: true,
domains: ["app.style.dev"],
timeoutMs: 30000, // 30 seconds (default is lower)
});Waiting for Deployment
Wait for the deployment to be fully rolled out before the API call returns:
const { deployment, domains } = await freestyle.serverless.deployments.create({
repo: "https://github.com/your-username/your-nextjs-app",
build: true,
domains: ["app.style.dev"],
waitForRollout: true, // Wait for full deployment
});
// Deployment is now ready to serve traffic
const response = await deployment.fetch();
console.log(await response.text());Monorepo Setup
For Next.js apps in a monorepo, specify the rootPath:
await freestyle.serverless.deployments.create({
repo: "https://github.com/your-org/monorepo",
rootPath: "./apps/web", // Path to Next.js app
build: true,
domains: ["app.style.dev"],
});Troubleshooting
Build Fails
If automatic framework detection doesn't work, you can specify build options manually:
await freestyle.serverless.deployments.create({
repo: "https://github.com/your-username/your-nextjs-app",
domains: ["app.style.dev"],
build: {
command: "npm run build",
outDir: ".next/standalone",
envVars: {
NODE_ENV: "production",
},
},
});Image Optimization Errors
If you see Sharp-related errors, ensure images.unoptimized is set to true in next.config.mjs.
Module Not Found
Make sure your lockfile is included in the deployment. The lockfile tells Freestyle which dependencies to install.