Project Setup
You can't learn Next.js by reading about it. You need a working application you can break, fix, and extend. This lesson gets you from zero to deployed in under 10 minutes, with a real app running on Vercel and automatic preview deployments on every push.
Every lesson in this course builds on this foundation. Get this right, and the rest will flow naturally.
Outcome
A working local development environment and a Vercel-connected repository that deploys previews on every push.
What You're Getting with the Starter
This isn't a blank canvas. You're deploying a working application with:
- Two Next.js apps:
apps/web(main app) andapps/blog(blog app) - Shared packages:
packages/api(data fetching) andpackages/ui(components) - Working routes: Home page, blog listing, dynamic post pages
- API layer: Blog posts, categories, and gallery data ready to use
Your job throughout this course is to extend and modify this foundation, not build from scratch. This mirrors real-world development where you'll rarely start with an empty folder.
Understanding the Dual-App Architecture
This starter contains two Next.js applications running side-by-side. This isn't accidental - it teaches you real-world monorepo patterns where teams share code but deploy independently.
nextjs-foundations/
├── apps/
│ ├── web/ # Main marketing + dashboard app
│ │ └── src/app/ # Port 3000 (Vercel-deployed)
│ │
│ └── blog/ # Content-focused blog app
│ └── src/app/ # Port 3001
│
└── packages/
├── api/ # Shared data fetching
└── ui/ # Shared components (shadcn)
Which app should I work in?
| App | Purpose | Port | When You'll Use It |
|---|---|---|---|
apps/web | Main marketing and dashboard app | 3000 | Most lessons (95% of your work) |
apps/blog | Content-focused blog app | 3001 | Dynamic Routing, Section 4 (Multi-app deployments) |
Why two apps instead of one?
Real companies organize apps this way:
- Separation of concerns: Marketing team owns
web, content team ownsblog - Independent deployment: Deploy blog changes without touching web
- Shared packages: Both apps import from
@repo/uiand@repo/api
When lessons switch to apps/blog, you'll see a callout like this:
This lesson works in apps/blog to explore dynamic routing in isolation. Most lessons use apps/web.
In Section 4, you'll connect both apps using Next.js rewrites, so users see a unified site (vercel.com/blog and vercel.com) while each app deploys independently behind the scenes.
Fast Track
- Click the Deploy Button below to copy and deploy
- Install Vercel CLI:
pnpm i -g vercel && vercel login - Clone your repo and link:
git clone ... && cd nextjs-foundations && vercel link - Install and run:
pnpm i && pnpm dev
Step 1: Deploy to Vercel
Click this button to copy the repository to your GitHub account and deploy to Vercel in one step:
Stop and do this now. Click the button, authorize GitHub if prompted, and wait for the deployment to complete. You'll see a success screen with your new repository URL.
Come back here once you see "Congratulations!" on Vercel.
What just happened:
- The starter repo was copied to your GitHub account
- Vercel deployed both apps automatically
- GitHub integration was configured for preview deployments
Step 2: Install the Vercel CLI
The Vercel CLI connects your local environment to your Vercel project. You'll use it throughout this course to check deployments, pull environment variables, and manage your project.
# Install globally
pnpm add -g vercel
# Authenticate (opens browser)
vercel loginThe CLI gives you superpowers: check deployment status without leaving your terminal, pull production env vars locally, and deploy from anywhere. We'll use it often.
Step 3: Clone and Install
Now get the code on your machine:
# Clone YOUR copy (replace with your GitHub username)
git clone https://github.com/YOUR_USERNAME/nextjs-foundations
cd nextjs-foundations
# Install dependencies
pnpm iYou need Node.js 24+ and pnpm installed. The repository uses pnpm workspaces.
# Check your versions
node -v # Should be v24.0.0 or higher
pnpm -v # Any recent version works
# Install pnpm if needed
corepack enable && corepack prepare pnpm@latest --activateStep 4: Link Your Project
Navigate to the web app and connect it to the Vercel project you deployed:
cd apps/web
vercel linkSelect your team and the nextjs-foundations project when prompted. When asked "Would you like to pull your environment variables?", answer Yes.
This creates:
- A
.verceldirectory linking your local app to the deployed project - A
.env.localfile with real working values:
NEXT_PUBLIC_APP_NAME="ACME Corporation"
INTERNAL_CONFIG="server-only-value"The deploy button baked these defaults into your Vercel project, so you get actual values immediately. No manual setup required.
Visit http://localhost:3000/env-demo after starting the dev server. You should see:
- Public: "ACME Corporation" (available in browser)
- Server-only: "server-only-value" (only visible on server)
If you see "undefined" for either value, run vercel env pull again from apps/web.
Return to the monorepo root for the remaining steps:
cd ../..Step 5: Run Locally
Start the development server:
pnpm devYou'll see the Turborepo TUI (terminal UI) showing both apps:
┌ @repo/web#dev ─────────────────────────────────────────────────┐
│ ▲ Next.js 16.1.1 (Turbopack) │
│ - Local: http://localhost:3000 │
│ ✓ Ready in 436ms │
└────────────────────────────────────────────────────────────────┘
┌ @repo/blog#dev ────────────────────────────────────────────────┐
│ ▲ Next.js 16.1.1 (Turbopack) │
│ - Local: http://localhost:3001 │
│ ✓ Ready in 436ms │
└────────────────────────────────────────────────────────────────┘
Use arrow keys to switch between apps and see their logs.
Both apps run simultaneously on different ports:
- http://localhost:3000:
apps/web(main app, deployed to Vercel) - http://localhost:3001:
apps/blog(blog app)
Open both URLs and confirm they load. The blog app fetches posts from the API layer (the shared data-fetching code in packages/api that both apps use).
Step 6: Verify Preview Deployments
Make a small change and push to confirm the deployment pipeline works:
# Create a branch
git checkout -b test-preview
# Make any small change (add a comment, fix a typo)
echo "// test" >> apps/web/src/app/page.tsx
# Commit and push
git add -A
git commit -m "test: verify preview deployment"
git push -u origin test-previewCheck the deployment status from your terminal:
vercel listYou should see output like this:
> Deployments for yourteam/nextjs-foundations
Age Deployment Status Environment
1m https://nextjs-foundations-abc123.vercel.app ● Ready Preview
5m https://nextjs-foundations-xyz789.vercel.app ● Ready Production
The Preview deployment is your branch. Production is the main branch.
You can also check deployments in the Vercel Dashboard, but the CLI is faster for quick status checks.
After confirming the preview works, clean up:
git checkout main
git branch -D test-preview
git push origin --delete test-previewDone-When
- Vercel CLI installed and authenticated (
vercel whoamishows your username) - Project linked (
vercel linkcompleted,.verceldirectory exists) pnpm devruns both apps (web on :3000, blog on :3001)- http://localhost:3001 shows blog posts from the API layer
- Pushing a branch triggers a Vercel preview deployment (
vercel listshows it)
Explore What You Got
Before moving on, take 2 minutes to look around:
| Path | What's There |
|---|---|
apps/web/src/app/page.tsx | Web app home page (Server Component) |
apps/web/src/app/env-demo/page.tsx | Environment variables demo |
apps/blog/src/app/page.tsx | Blog listing page |
apps/blog/src/app/[slug]/page.tsx | Dynamic blog post route |
packages/api/src/blog.ts | Blog data fetching functions |
packages/ui/src/components/button.tsx | Shared Button component (shadcn) |
You don't need to understand all of this yet. Just know it exists. We'll explore each piece in upcoming lessons.
The deploy button set up apps/web on Vercel. Later in the course, you'll learn how to deploy multiple apps from a monorepo. For now, focus on apps/web for Vercel previews.
Troubleshooting
Port already in use
Error: listen EADDRINUSE: address already in use :::3000Fix: Kill the process or use a different port:
lsof -ti:3000 | xargs kill -9
# or
PORT=3001 pnpm devModule not found
Error: Cannot find module 'zod'Fix: Clean install:
rm -rf node_modules .next apps/*/.next
pnpm installpnpm not recognized
Fix: Install pnpm with corepack:
corepack enable
corepack prepare pnpm@latest --activateWrong Node.js version
WARN Unsupported engine: wanted: {"node":"24.x"}Fix: Use fnm to manage Node versions:
# Install fnm (macOS/Linux)
curl -fsSL https://fnm.vercel.app/install | bash
# Install and use Node 24
fnm install 24
fnm use 24Vercel deployment fails
Check these in your Vercel project settings:
- Build Command: Should be auto-detected as
pnpm buildorturbo build - Root Directory: Leave empty (monorepo root)
- Node.js Version: 24.x
If builds fail with type errors, run pnpm build locally first to see the actual error.
Ask your coding agent for help. Paste the error message and it can diagnose the issue.
I'm setting up a Next.js 16 project and getting an error.
**Error message:**
```
___PASTE_ERROR_MESSAGE_HERE___
```
**My environment:**
- Node version: _____ (run `node -v` to check)
- Package manager: _____ (pnpm/npm/yarn)
- OS: _____ (macOS/Windows/Linux)
**What I was trying to do:**
___DESCRIBE_WHAT_YOU_WERE_DOING___
Example: "Running pnpm install" or "Starting dev server with pnpm dev"
Help me understand what's causing this error and how to fix it.What's Next
You now have a working Next.js application deployed to production. In the next lesson, you'll learn how the App Router organizes your code: how page.tsx, layout.tsx, and folder structure map to URLs.
Was this helpful?