Uitleg — Wat zijn API Routes?
In Next.js bouw je backend endpoints in hetzelfde project als je frontend. Geen aparte Express server nodig. API routes maak je door een route.js bestand aan te maken in app/api/.
app/
└── api/
└── workouts/
├── route.js → GET /api/workouts en POST /api/workouts
└── [id]/
└── route.js → GET /api/workouts/:id en DELETE /api/workouts/:id
💡 route.js vs page.js
page.js = een pagina die HTML teruggeeft (voor gebruikers)
route.js = een API endpoint dat JSON teruggeeft (voor code)
Stap 1 — Installeer Mongoose
Stop de dev server eerst (Ctrl+C), voer dan uit:
npm install mongoose
Start daarna de dev server weer op:
npm run dev
Stap 2 — Maak de databaseverbinding aan
Maak een nieuwe map lib aan naast de app/ map (dus in de root, niet erin):
workout-tracker/
├── app/ ← hier zit je al
├── lib/ ← nieuwe map hier aanmaken
│ └── mongodb.js ← nieuw bestand aanmaken
├── public/
└── package.json
// lib/mongodb.js
import mongoose from 'mongoose';
const MONGO_URI = process.env.MONGO_URI;
if (!MONGO_URI) {
throw new Error('Stel MONGO_URI in je .env.local in');
}
let cached = global.mongoose;
if (!cached) {
cached = global.mongoose = { conn: null, promise: null };
}
async function connectDB() {
if (cached.conn) {
return cached.conn;
}
cached.promise = mongoose.connect(MONGO_URI);
cached.conn = await cached.promise;
return cached.conn;
}
export default connectDB;
- Next.js herlaadt bestanden vaker dan Express
- Zonder caching maak je elke keer een nieuwe verbinding
- Met
global.mongoosebewaar je de verbinding
Stap 3 — Maak .env.local aan
Maak een nieuw bestand .env.local aan naast de app/ map (dus in de root, niet erin):
workout-tracker/
├── app/
├── lib/
├── .env.local ← nieuw bestand hier aanmaken
└── package.json
# .env.local
MONGO_URI=mongodb+srv://gebruiker:wachtwoord@cluster0.xxxxx.mongodb.net/jouwDatabaseNaam?retryWrites=true&w=majority
Let op: .env.local vs .env
Next.js gebruikt .env.local, niet .env. Controleer de bestandsnaam!
Stap 4 — Maak het Workout model aan
Maak een nieuwe map models aan naast de app/ map en maak daarin een nieuw bestand:
workout-tracker/
├── app/
├── lib/
├── models/ ← nieuwe map hier aanmaken
│ └── Workout.js ← nieuw bestand aanmaken
└── package.json
// models/Workout.js
import mongoose from 'mongoose';
const workoutSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
},
reps: {
type: Number,
required: true,
},
load: {
type: Number,
required: true,
},
},
{ timestamps: true }
);
// Voorkom dat Mongoose het model opnieuw aanmaakt bij hot reload
const Workout = mongoose.models.Workout || mongoose.model('Workout', workoutSchema);
export default Workout;
Belangrijk: de laatste regel
mongoose.models.Workout || mongoose.model(...) is essentieel in Next.js. Zonder dit krijg je een "Cannot overwrite model once compiled" fout bij hot reload.
Stap 5 — Maak de GET & POST route aan
Maak de mappen api en workouts aan binnen de app/ map, en maak daarin een nieuw bestand:
app/
├── api/ ← nieuwe map aanmaken
│ └── workouts/ ← nieuwe map aanmaken
│ └── route.js ← nieuw bestand aanmaken
└── workouts/
└── page.js
// app/api/workouts/route.js
import { NextResponse } from 'next/server';
import { revalidatePath } from 'next/cache';
import connectDB from '../../../lib/mongodb';
import Workout from '../../../models/Workout';
// GET /api/workouts — alle workouts ophalen
export async function GET() {
await connectDB();
const workouts = await Workout.find({}).sort({ createdAt: -1 });
return NextResponse.json(workouts, { status: 200 });
}
// POST /api/workouts — nieuwe workout aanmaken
export async function POST(request) {
await connectDB();
const body = await request.json();
const { title, reps, load } = body;
// Validatie
if (!title || !reps || !load) {
return NextResponse.json(
{ error: 'Vul alle velden in' },
{ status: 400 }
);
}
const workout = await Workout.create({ title, reps, load });
revalidatePath('/workouts'); // ← cache legen na toevoegen
return NextResponse.json(workout, { status: 201 });
}
- Elke HTTP methode (GET, POST) is een aparte
export function - Je gebruikt
NextResponse.json()in plaats vanres.json() - De request body lees je met
await request.json()
Stap 6 — Maak de dynamische route aan (GET & DELETE)
Maak een nieuwe map [id] aan binnen de bestaande app/api/workouts/ map:
app/
└── api/
└── workouts/
├── route.js ← al aangemaakt
└── [id]/ ← nieuwe map aanmaken
└── route.js ← nieuw bestand aanmaken
// app/api/workouts/[id]/route.js
import { NextResponse } from 'next/server';
import { revalidatePath } from 'next/cache';
import connectDB from '../../../../lib/mongodb';
import Workout from '../../../../models/Workout';
// GET /api/workouts/:id — één workout ophalen
export async function GET(request, { params }) {
await connectDB();
const { id } = await params;
const workout = await Workout.findById(id);
if (!workout) {
return NextResponse.json(
{ error: 'Workout niet gevonden' },
{ status: 404 }
);
}
return NextResponse.json(workout, { status: 200 });
}
// DELETE /api/workouts/:id — workout verwijderen
export async function DELETE(request, { params }) {
await connectDB();
const { id } = await params;
const workout = await Workout.findByIdAndDelete(id);
if (!workout) {
return NextResponse.json(
{ error: 'Workout niet gevonden' },
{ status: 404 }
);
}
revalidatePath('/workouts'); // ← cache legen na verwijderen
return NextResponse.json(
{ message: 'Workout verwijderd' },
{ status: 200 }
);
}
💡 params in API routes
De params staan in het tweede argument van de functie, niet in de request. Let op de destructuring: { params }.
Stap 7 — Testen
GET testen
Open je browser en ga naar: http://localhost:3000/api/workouts
Je ziet een lege array [] (want nog geen data).
POST testen met Postman
Stuur een POST request naar http://localhost:3000/api/workouts met als body:
{
"title": "Push Day",
"reps": 10,
"load": 50
}
✅ Verwacht resultaat
Je ontvangt het aangemaakte workout object terug met een _id en timestamps. Ververs daarna de browser — je ziet het workout in de GET response!
Mappenstructuur tot nu toe
workout-tracker/
├── app/
│ ├── api/
│ │ └── workouts/
│ │ ├── route.js
│ │ └── [id]/
│ │ └── route.js
│ ├── components/
│ │ └── AddWorkoutForm.js
│ ├── workouts/
│ │ ├── page.js
│ │ └── [id]/
│ │ └── page.js
│ ├── layout.js
│ └── page.js
├── lib/
│ └── mongodb.js
├── models/
│ └── Workout.js
└── .env.local
Checklist
✅ Check of je hebt:
- Mongoose geïnstalleerd
lib/mongodb.jsaangemaaktMONGO_URIin.env.localmodels/Workout.jsaangemaaktapp/api/workouts/route.jsmet GET en POSTapp/api/workouts/[id]/route.jsmet DELETE- GET
/api/workoutswerkt in browser - POST via Postman maakt een workout aan
Volgende Stap
API werkt! Nu gaan we data ophalen op de pagina's.
Nu de API werkt, haal je de data op in je pagina's