Tour the Next.js Starter
The Next.js app is already working. Run it and you'll see a furniture listing page with eight items, a clean layout, in-stock badges. It looks real. The data isn't. It's a hardcoded array sitting right in the page component.
That's what we're going to replace. But first, let's see what we're working with.
Outcome
Get the Next.js starter running locally and locate the mock data that will be replaced by a real API call.
Fast Track
cd starter && npm installnpm run dev- Open
http://localhost:3000
Hands-On
Install and run
cd starter
npm install
npm run devYou'll see Turbopack start up. Next.js 16 uses it as the default bundler:
▲ Next.js 16.0.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 component is synchronous. No async, no fetch. It maps over a local array and renders cards. The whole thing works without a network request, which is exactly why it's the starter state.
In Section 2, we'll swap mockItems for a fetch call to /api/items. The component markup won't change at all. Just where the data comes from.
Check the project layout
The root of starter/ has two halves living side by side:
starter/
├── 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
Python on one side, JavaScript on the other, same project root. When you deploy, Vercel sees both and treats the api/ folder as Python functions while everything else is the Next.js app.
Check the project config
Open starter/package.json:
{
"dependencies": {
"next": "^16.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
}And starter/app/layout.tsx has the shell: the header, body wrapper, and global styles. You won't need to touch this file.
This project uses Tailwind CSS v4, which has a simpler setup than v3. The
entire configuration is a single import in globals.css:
@import "tailwindcss". No config file, no content paths.
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
Two working apps on two ports. Not connected yet.
You can leave these dev servers running or stop them. Section 2 opens by switching to vercel dev, which replaces both with a single command.
Troubleshooting
Port 3000 already in use: Next.js will automatically try port 3001 if 3000 is taken. You'll see "ready on http://localhost:3001" in the terminal. The app still works, just on a different port.
Node version error: Next.js 16 requires Node.js 18.17 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:3000shows the furniture listing page- You can locate the
mockItemsarray instarter/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?