Vercel Logo

Tour the Next.js Starter

Hazel Home already has furniture and a suspiciously polished product grid. Every item comes from a hardcoded array in the page component, which gives us a working interface before the API enters the picture.

Outcome

Get the Next.js starter running locally and locate the mock data that will be replaced by a real API call.

Hands-on exercise 1.3

Install and run

cd starter
npm install
npm run dev

You'll see Turbopack start up. Next.js 16 uses it as the default bundler:

▲ Next.js 16.3.0 (Turbopack)
- Local:        http://localhost:3000
- Network:      http://192.168.x.x:3000

✓ Starting...
✓ Ready in 612ms

Open http://localhost:3000. You'll see the Hazel Home storefront with all eight furniture items displayed.

Read the page component

Open starter/app/page.tsx. The relevant part is at the top:

const mockItems: Item[] = [
  { id: 1, name: "Fernwood Sectional", category: "Seating", price: 2499, in_stock: true },
  { id: 2, name: "Knotted Oak Coffee Table", category: "Tables", price: 849, in_stock: true },
  // ...
];
 
export default function Home() {
  return (
    <>
      <h2>All Furniture</h2>
      <div>
        {mockItems.map((item) => (
          // ...
        ))}
      </div>
    </>
  );
}

The synchronous component maps over mockItems and renders a card for each entry. Because the data lives in the same file, the page does not make a network request yet.

In Section 2, we'll replace mockItems with a request to /api/items. We can keep the card markup and change its data source.

Check the project layout

The root of starter/ has two halves living side by side:

starter/
├── .gitignore            # Local build and Vercel metadata
├── api/
│   └── index.py          # FastAPI lives here
├── app/                  # Next.js app router
│   ├── globals.css
│   ├── layout.tsx
│   └── page.tsx
├── package.json          # Next.js dependencies
├── pyproject.toml        # Python dependencies
├── next.config.ts
├── postcss.config.mjs
└── tsconfig.json

Vercel treats the api/ folder as Python functions and the rest of the project as the Next.js app. Keeping both at the same root lets one Vercel project build them together.

Check the project config

Open starter/package.json:

{
  "dependencies": {
    "next": "^16.3.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  }
}

The shared page shell lives in starter/app/layout.tsx, including the header, body wrapper, and global stylesheet import. We won't change it in this course.

Tailwind v4

This project uses Tailwind CSS v4. Its setup begins with @import "tailwindcss" in globals.css, so this starter does not include a Tailwind config file.

Try It

With both apps running simultaneously, FastAPI on port 8000 and Next.js on port 3000, open a second terminal and confirm both are up:

curl http://localhost:8000/api/items | head -c 100
[{"id":1,"name":"Fernwood Sectional","category":"Seating","price":2499.0,"in_stock":true}
curl http://localhost:3000 -s -o /dev/null -w "%{http_code}"
200

The two responses confirm that both sides work independently. Stop the dev servers before the next lesson, where vercel dev will serve them from the same local URL.

Commit

We only ran and inspected the starter, so there are no changes to commit. The starter's .gitignore already excludes node_modules/, .next/, virtual environments, and .vercel/ project metadata.

Troubleshooting

Port 3000 already in use: Next.js will automatically try port 3001 if 3000 is taken. The terminal will show the port that it selected; open that URL instead.

Node version error: Next.js 16 requires Node.js 20.9 or later. Run node --version to check. If you're below that, update via nodejs.org or use a version manager like nvm.

Done-When

  • http://localhost:3000 shows the furniture listing page
  • You can locate the mockItems array in starter/app/page.tsx
  • Both apps are running at the same time without port conflicts

Solution

The starter page component with mock data in place:

// starter/app/page.tsx
const mockItems: Item[] = [
  { id: 1, name: "Fernwood Sectional", category: "Seating", price: 2499, in_stock: true },
  { id: 2, name: "Knotted Oak Coffee Table", category: "Tables", price: 849, in_stock: true },
  { id: 3, name: "Garrison Bookshelf", category: "Storage", price: 629, in_stock: false },
  { id: 4, name: "The Long Table", category: "Tables", price: 1199, in_stock: true },
  { id: 5, name: "Pivot Desk Chair", category: "Seating", price: 449, in_stock: true },
  { id: 6, name: "Ember Side Table", category: "Tables", price: 299, in_stock: true },
  { id: 7, name: "Stacked Nightstand", category: "Storage", price: 389, in_stock: false },
  { id: 8, name: "Canvas Floor Lamp", category: "Lighting", price: 219, in_stock: true },
];
 
export default function Home() {
  return (
    <>
      <h2>All Furniture</h2>
      <div>{mockItems.map((item) => ...)}</div>
    </>
  );
}

Was this helpful?

supported.