# Nextjs App Scaffold

> Scaffold a Next.js App Router project with TypeScript, Tailwind CSS v4, and optional custom server (e.g. Socket.io). Use when the user wants to create a new Next.js project, initialize a web application, set up a TypeScript + Tailwind project, or needs a custom Node.js server wrapping Next.js.

- Skill: `ph13917403910/nextjs-app-scaffold` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ph13917403910/nextjs-app-scaffold`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ph13917403910/nextjs-app-scaffold/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: PH13917403910 (https://skillmd.com/u/ph13917403910)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/ph13917403910/nextjs-app-scaffold

---


# Next.js App Router Scaffold

## When to use

- Starting a new web project from scratch
- User asks to "create a Next.js app" or "scaffold a project"
- Need a custom server (WebSocket, Socket.io, SSE alongside Next.js)

## Stack decisions

| Layer | Default choice | Why |
|-------|---------------|-----|
| Framework | Next.js (App Router) | Server components, file-based routing, streaming |
| Language | TypeScript (strict) | Catch errors at build time |
| Styling | Tailwind CSS v4 | `@theme` design tokens, no runtime CSS-in-JS |
| Runtime | Node.js 22 LTS | Long-term support, native fetch |

## Project init

```bash
npx create-next-app@latest PROJECT_NAME \
  --typescript --tailwind --eslint --app \
  --src-dir --import-alias "@/*"
cd PROJECT_NAME
```

Tailwind v4 uses `@import "tailwindcss"` in CSS — no `tailwind.config.js` needed. Design tokens go in `@theme {}` block inside `globals.css`.

## Directory structure

```
PROJECT_NAME/
├── src/
│   ├── app/              # Routes (App Router)
│   │   ├── layout.tsx    # Root layout (fonts, metadata, providers)
│   │   ├── page.tsx      # Home page
│   │   └── globals.css   # @theme tokens + global styles
│   ├── components/
│   │   ├── layout/       # Shell, nav, footer, overlays
│   │   ├── shared/       # Reusable UI (cards, modals, inputs)
│   │   └── [feature]/    # Feature-specific components
│   ├── hooks/            # Custom React hooks
│   └── lib/              # Utilities, types, data, API clients
├── public/               # Static assets
├── server.mjs            # Custom server (if needed)
├── Dockerfile            # Multi-stage build
├── package.json
├── tsconfig.json
└── next.config.ts
```

## Custom server pattern (server.mjs)

Use when you need to run additional services (Socket.io, cron, etc.) alongside Next.js on a single port. This is the escape hatch — only use it when Next.js API routes are insufficient.

```javascript
import { createServer } from "node:http";
import next from "next";

const dev = process.env.NODE_ENV !== "production";
const hostname = "0.0.0.0";
const port = parseInt(process.env.PORT || "3000", 10);

const app = next({ dev, hostname, port });
const handler = app.getRequestHandler();

await app.prepare();

const httpServer = createServer(handler);

// Attach additional services to httpServer here
// e.g. new Server(httpServer, { cors: { origin: "*" } })

httpServer.listen(port, hostname, () => {
  console.log(`> Ready on http://${hostname}:${port}`);
});
```

Update `package.json` scripts:

```json
{
  "scripts": {
    "dev": "node server.mjs",
    "build": "next build",
    "start": "node server.mjs"
  }
}
```

## Root layout pattern

```tsx
import type { Metadata } from "next";
import { Inter, Space_Grotesk } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
const display = Space_Grotesk({ subsets: ["latin"], variable: "--font-space-grotesk" });

export const metadata: Metadata = {
  title: "Your App",
  description: "Description",
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={`${inter.variable} ${display.variable}`}>
      <body className="font-sans antialiased">{children}</body>
    </html>
  );
}
```

## Tailwind v4 globals.css skeleton

```css
@import "tailwindcss";

@theme {
  --color-primary: #your-color;
  --color-accent: #your-accent;
  --font-sans: var(--font-inter, "Inter"), ui-sans-serif, system-ui, sans-serif;
  --font-display: var(--font-space-grotesk, "Space Grotesk"), ui-sans-serif, system-ui, sans-serif;
}
```

## Content-data separation

Keep all content (text, config, questions, scenarios) in `src/lib/` data files, separate from components. Components import data — never hardcode content strings in TSX.

```typescript
// src/lib/types.ts — shared interfaces
export interface PageInfo {
  title: string;
  description: string;
  slug: string;
}

// src/lib/page-data.ts — content
import type { PageInfo } from "./types";
export const pages: PageInfo[] = [ /* ... */ ];
```

## Key dependencies to install

Only add what you need:

```bash
# Animation (if interactive UI)
npm install framer-motion

# Real-time (if multi-user)
npm install socket.io socket.io-client

# Email (if transactional email)
npm install resend

# Drag & drop (if sortable UI)
npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
```

## Checklist

- [ ] `src/app/layout.tsx` has metadata, fonts, global CSS import
- [ ] `globals.css` uses `@theme {}` for design tokens (no tailwind.config.js)
- [ ] Types in `src/lib/types.ts`, content in `src/lib/*-data.ts`
- [ ] Components organized by role: `layout/`, `shared/`, `[feature]/`
- [ ] If custom server: `server.mjs` at root, scripts updated
- [ ] `.gitignore` includes `.next/`, `node_modules/`, `.env*.local`

