-
Notifications
You must be signed in to change notification settings - Fork 8
feat: add nextjs-app example template #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| node_modules | ||
| .next | ||
| .alien | ||
| alien.ts | ||
| template.toml | ||
| README.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Node | ||
| node_modules/ | ||
| package-lock.json | ||
| pnpm-lock.yaml | ||
|
|
||
| # Next.js | ||
| .next/ | ||
| next-env.d.ts | ||
|
|
||
| # Alien | ||
| .alien/ | ||
|
|
||
| # OS | ||
| .DS_Store |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| FROM node:22-alpine AS build | ||
| WORKDIR /app | ||
| COPY package.json package-lock.json* ./ | ||
| RUN npm install | ||
| COPY . . | ||
| RUN npm run build | ||
|
|
||
| FROM node:22-alpine | ||
| WORKDIR /app | ||
| ENV NODE_ENV=production | ||
| # .next/static and public are not part of the standalone output and must be | ||
| # copied alongside it for server.js to serve them. | ||
| COPY --from=build /app/.next/standalone ./ | ||
| COPY --from=build /app/.next/static ./.next/static | ||
| COPY --from=build /app/public ./public | ||
| ENV HOSTNAME=0.0.0.0 | ||
| ENV PORT=3000 | ||
| EXPOSE 3000 | ||
| CMD ["node", "server.js"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # Next.js App | ||
|
|
||
| The smallest containerized Next.js app: one container, one page, one API route. Use it as the starting point for dashboards, internal tools, or any web app that needs to run where the customer's data lives. | ||
|
|
||
| The app builds with the included Dockerfile (Next.js [standalone output](https://nextjs.org/docs/app/api-reference/config/next-config-js/output)) and runs as a single replica behind an HTTPS load balancer. | ||
|
|
||
| ## What's included | ||
|
|
||
| | Resource | Type | Description | | ||
| |----------|------|-------------| | ||
| | `app` | Container | The Next.js app, built from the Dockerfile and exposed over HTTP | | ||
|
|
||
| ## Local development | ||
|
|
||
| Run the Next.js dev server directly: | ||
|
|
||
| ```bash | ||
| npm install | ||
| npm run dev | ||
| ``` | ||
|
|
||
| Then check it works: | ||
|
|
||
| ```bash | ||
| curl http://localhost:3000/api/health | ||
| # {"status":"ok"} | ||
|
|
||
| open http://localhost:3000 | ||
| ``` | ||
|
|
||
| ## Deploying | ||
|
|
||
| ```bash | ||
| alien deploy production --platform aws # or gcp / azure | ||
| ``` | ||
|
|
||
| Alien builds the container image from the Dockerfile, pushes it, and provisions the compute and load balancer. The deploy output prints the public URL. | ||
|
|
||
| ## Learn more | ||
|
|
||
| - [Quickstart guide](https://alien.dev/docs/quickstart) -- build a worker, test locally, send remote commands | ||
| - [How Alien Works](https://alien.dev/docs/how-alien-works) -- stacks, isolated areas, push vs pull | ||
| - [Stacks](https://alien.dev/docs/stacks) -- workers, storage, queues, vaults |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import * as alien from "@alienplatform/core" | ||
|
|
||
| const app = new alien.Container("app") | ||
| .code({ type: "source", src: ".", toolchain: { type: "docker", dockerfile: "Dockerfile" } }) | ||
| .cpu(0.5) | ||
| .memory("512Mi") | ||
| .port(3000) | ||
| .expose("http") | ||
| // Next's standalone server reads these; HOSTNAME=0.0.0.0 binds all interfaces. | ||
| .environment({ PORT: "3000", HOSTNAME: "0.0.0.0" }) | ||
| .permissions("app") | ||
| .build() | ||
|
|
||
| export default new alien.Stack("nextjs-app") | ||
| .platforms(["aws", "gcp", "azure"]) | ||
| .add(app, "live") | ||
| .permissions({ profiles: { app: {} } }) // no linked resources → empty profile | ||
| .build() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export async function GET() { | ||
| return Response.json({ status: "ok" }) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import type { Metadata } from "next" | ||
| import type { ReactNode } from "react" | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: "Next.js on Alien", | ||
| description: "The smallest containerized Next.js app deployed with Alien.", | ||
| } | ||
|
|
||
| export default function RootLayout({ children }: { children: ReactNode }) { | ||
| return ( | ||
| <html lang="en"> | ||
| <body>{children}</body> | ||
| </html> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| export default function Home() { | ||
| return ( | ||
| <main style={{ fontFamily: "sans-serif", maxWidth: "40rem", margin: "4rem auto" }}> | ||
| <h1>Next.js on Alien</h1> | ||
| <p> | ||
| This app runs as a single container inside the cloud account it was deployed to. Edit{" "} | ||
| <code>app/page.tsx</code> and redeploy to ship changes. | ||
| </p> | ||
| <p> | ||
| Try the API route at <a href="/api/health">/api/health</a>. | ||
| </p> | ||
| </main> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import type { NextConfig } from "next" | ||
|
|
||
| const nextConfig: NextConfig = { | ||
| // The container runs the generated .next/standalone/server.js without node_modules. | ||
| output: "standalone", | ||
| } | ||
|
|
||
| export default nextConfig |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||||||||
| { | ||||||||||||
| "name": "nextjs-app", | ||||||||||||
| "version": "1.0.0", | ||||||||||||
| "private": true, | ||||||||||||
| "scripts": { | ||||||||||||
| "dev": "next dev", | ||||||||||||
| "build": "next build" | ||||||||||||
|
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The Dockerfile runs
Suggested change
Prompt To Fix With AIThis is a comment left during a code review.
Path: examples/nextjs-app/package.json
Line: 6-7
Comment:
**Missing `start` script for local production testing**
The Dockerfile runs `node server.js` directly, but there is no `start` script for users who want to preview the standalone output locally before deploying. Without it, users must know to run `node .next/standalone/server.js` manually. A `start` script keeps parity with the README's `npm install && npm run dev` workflow and matches community expectations for Next.js projects.
```suggestion
"dev": "next dev",
"build": "next build",
"start": "node .next/standalone/server.js"
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||||||||||||
| }, | ||||||||||||
| "dependencies": { | ||||||||||||
| "next": "^16.2.9", | ||||||||||||
| "react": "^19.0.0", | ||||||||||||
| "react-dom": "^19.0.0" | ||||||||||||
| }, | ||||||||||||
| "devDependencies": { | ||||||||||||
| "@alienplatform/core": "^1.7.0", | ||||||||||||
| "@types/node": "^24.0.15", | ||||||||||||
| "@types/react": "^19.0.0", | ||||||||||||
| "@types/react-dom": "^19.0.0", | ||||||||||||
| "typescript": "^5.8.3" | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| User-agent: * | ||
| Allow: / |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| name = "nextjs-app" | ||
| description = "Deploy a Next.js app as a single container in the customer's cloud." | ||
| language = "TypeScript" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "target": "ES2022", | ||
| "lib": ["dom", "dom.iterable", "esnext"], | ||
| "allowJs": true, | ||
| "skipLibCheck": true, | ||
| "strict": true, | ||
| "noEmit": true, | ||
| "esModuleInterop": true, | ||
| "module": "esnext", | ||
| "moduleResolution": "bundler", | ||
| "resolveJsonModule": true, | ||
| "isolatedModules": true, | ||
| "jsx": "react-jsx", | ||
| "incremental": true, | ||
| "plugins": [ | ||
| { | ||
| "name": "next" | ||
| } | ||
| ] | ||
| }, | ||
| "include": [ | ||
| "next-env.d.ts", | ||
| "**/*.ts", | ||
| "**/*.tsx", | ||
| ".next/types/**/*.ts", | ||
| ".next/dev/types/**/*.ts" | ||
| ], | ||
| "exclude": ["node_modules"] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
package-lock.jsonis listed in the template's.gitignore, so the file is never committed and therefore never present whenalien releasebuilds this image.COPY package-lock.json* ./silently copies nothing, andnpm installthen resolves semver ranges at build time, meaning successivealien releaseruns can produce images with different transitive dependency versions. Every other Node.js template in this repo has the same gitignore entry, but here it is the primary production build path. Consider generating and committing apackage-lock.jsonfor the example (removing it from the example's.gitignore), or switching the build stage to pnpm so it shares the workspace lock file.Prompt To Fix With AI