🚀 Next.js Deployment with Paketo Buildpacks (No Dockerfile Needed)
🔍 Introduction
Deploying a Next.js 15 app to the cloud usually involves Docker or vendor lock-in, but with Paketo Buildpacks and Miget Platform, you get zero-config, containerized deployment+SSL, no Docker expertise needed. This guide gives you a step-by-step walkthrough:
- Scaffold Next.js
- Structure your app/ folder
- Configure build settings
- Run and test locally via pack
- Deploy seamlessly to Miget Platform
📌 Why Use Paketo Buildpacks + Miget Platform for Next.js?
- Abstract Docker complexity: no need to write or maintain
Dockerfiles
- Standardized, reproducible builds - perfect for CI/CD
- Built‑in security & SBOM through Paketo
- Paketo Buildpacks
- One-command deploy with
git push miget
- Automatic HTTPS, scaling, environment variables, and edge network support
Read more about Node.js Paketo Buildpacks here
🛠️ Prerequisites
pack
CLI (Paketo's Cloud Native Buildpacks tool)Install pack
CLI (macOS via Homebrew):
brew install buildpacks/tap/pack
Or follow the official pack install guide.
Step 1: Create a Next.js 15 Project
> npx create-next-app@15 hello-world-app
Need to install the following packages:
create-next-app@15.4.1
Ok to proceed? (y) y
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack for `next dev`? … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
(...)
Step 2: Add the Main Page
Create app/page.tsx
:
export default function Home() {
return (
<div className="container">
<h1 className="title">Hello World!</h1>
<p className="description">Welcome to your Next.js 15 app deployed to Miget!</p>
</div>
)
}
Step 3: Set Up Global Layout
Create app/layout.tsx
:
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
}
Step 4: Add Global Styles
Create app/globals.css
:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 2rem;
}
.title {
font-size: 3rem;
color: white;
margin-bottom: 1rem;
text-align: center;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.description {
font-size: 1.2rem;
color: rgba(255, 255, 255, 0.9);
text-align: center;
max-width: 600px;
line-height: 1.6;
}
@media (max-width: 768px) {
.title {
font-size: 2rem;
}
.description {
font-size: 1rem;
}
}
Step 5: Configure Next.js for Production
Create next.config.js
:
/** @type {import('next').NextConfig} */
module.exports = {
output: 'standalone',
};
➡️ This enables standalone server output - ideal for container builds.
🗑️ Delete any TypeScript config (next.config.ts
) to avoid confusion.
Step 6: Build Locally with Paketo (Optional)
Test your build WITHOUT writing Dockerfile
:
pack build --env NODE_ENV=production hello-world-app
This uses Paketo’s Node.js buildpack, auto-detecting your Node version (via engines
in package.json
or BP_NODE_VERSION
) and build a docker image that you can run in a next step.
If pack build
fails, more likely Miget build will fail too! Fix your code and retry this step.
Step 7: Run Locally in Docker (Optional)
docker run -e NODE_ENV=production -e PORT=5000 -p 5000:5000 hello-world-app
Visit: http://localhost:5000
Step 8: Deploy to Miget Platform
Create an App in Miget Platform
Navigate to Applications section in the sidebar and click + Create your first application.
Fill out basic info:
Choose a project and region (e.g., Default Project and Europe), then click Continue.
Allocate CPU and RAM depending on your needs. For a basic app, start with 0.1 CPU
and 128Mi RAM
. Then, select the Paketo Buildpacks builder.
Review the configuration, and click Create to finalize your application.
Once the app is created, you need to add NODE_ENV
variable to your newly created App. To do so, click Settings, then Variables. Add NODE_ENV
as a key, and production
as a value, then click Save Changes
Now, you can deploy your Next.js to Miget. Click Deploy button to start the deployment process.
You have been redirected to the Settings > Git Tokens section. Add a new token to enable Git-based deployment. The token acts as the password, while the username is auto-generated based on the token name.
Deploy your Next.js app to Miget
Initialize git and push:
cd hello-world-app
git init
git add .
git commit -m "Initial Next.js 15 app"
git config push.autoSetupRemote true
git remote add miget <YOUR‑MIGET‑GIT‑URL>
git push miget main
Miget Platform auto-detects Next.js, uses Paketo, and deploys with HTTPS, scaling, and automatic builds.
📈 Final Thoughts
Deploying Next.js doesn’t need to be complicated. With Paketo Buildpacks and Miget Platform, you get fast, secure deployment without needing Docker expertise.