Everything so far runs in the user's browser. When someone submits their email, it goes nowhere — we just show a fake success message. In this lesson, we add a backend so data actually gets saved.
The Big Picture
Concept
Every web application has the same basic flow:User's Browser (Frontend) → API Route (Backend) → Database → Response back to Browser
The frontend collects user input. The backend processes it. The database stores it. The response confirms it. That's how every app in the world works — from Google to a simple signup form.
Next.js API Routes
Here's the beautiful thing about Next.js: it handles backend logic too. You don't need a separate server. API Routes are special files inside your app/api/ folder that handle server-side logic.
An API Route is simply a URL on your server that accepts data and returns a response. For example: POST /api/signup — receives an email, stores it, returns "success."
Try It
In Claude Code, type:"Create an API route at app/api/signup/route.ts that: - Accepts POST requests with a JSON body containing an email field - Validates the email format on the server side - Checks for duplicate emails - Stores the email with a timestamp in a local JSON file at data/signups.json - Returns a JSON response with success: true or an error message - Create the data directory if it doesn't exist"
Claude will create the API route file. This is your first backend code!
Starting Simple: JSON File Storage
For learning purposes, we're storing data in a local JSON file. This is the simplest possible "database" — a file that contains a list of emails. It works perfectly for development.
After Claude creates the API route, your data/signups.json file will look something like this:
[
{ "email": "user@example.com", "timestamp": "2026-04-11T10:30:00Z" }
]
Honest Note
A JSON file is not a real database. It works fine for learning and small-scale testing, but it has real limitations: no concurrent access handling, no querying, no backup, and it lives on a single machine. In Lesson 10, we'll switch to DynamoDB — a real cloud database. But for now, this is the perfect learning tool.Connecting Frontend to Backend
Now let's update the signup form to actually POST data to our new API route:
Try It
In Claude Code:"Update the signup form component to POST to /api/signup instead of simulating a delay. Send the email as JSON in the request body. Handle the response: - If the API returns success: true, show the success message - If the API returns an error (like duplicate email), show the error message from the API - Handle network errors with a generic 'Something went wrong. Please try again.' message"
Testing It
- Make sure your dev server is running (
npm run dev) - Go to http://localhost:3000
- Enter an email and submit the form
- Check
data/signups.json— your email should be there! - Try submitting the same email again — you should see a "duplicate" error
Try It
Submit a few different emails through the form. Then opendata/signups.json in VS Code to verify they're all there. You just built a full-stack feature!
Data Validation on the Server
Client-side validation (in the browser) is nice for user experience, but it's not enough. Anyone can bypass it by sending requests directly to your API.
Concept
Never trust data from the client. Always validate on the server too. Client-side validation is for user experience (showing helpful errors). Server-side validation is for security (rejecting bad data regardless of how it was sent).Our API route already validates emails on the server — Claude included this. But let's make it more robust:
Add rate limiting to the signup API — maximum 5 signups per IP address
per hour. If exceeded, return a 429 status with a friendly message.
Testing Your API
Besides using the form in the browser, you can test your API directly:
Using the browser's Network tab:
- Open Developer Tools (F12)
- Go to the Network tab
- Submit the form
- Click on the
signuprequest to see the request and response details
Using curl in your terminal (optional):
curl -X POST http://localhost:3000/api/signup \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com"}'
Security Note
Honest Note
This is a learning project, and that's okay. But a production application needs more:- Authentication — verifying who is making requests - Rate limiting — preventing abuse (we added basic limiting above) - Input sanitization — preventing injection attacks - HTTPS — encrypting data in transit - Environment variables — keeping secrets out of code
Claude can help you add all of these, but it's important to know they exist. Security isn't optional in real applications.
Git Checkpoint
git add .
git commit -m "backend API route with email storage and server-side validation"
Make sure to add data/signups.json to your .gitignore file — you don't want to commit user data:
echo "data/signups.json" >> .gitignore
git add .gitignore
git commit -m "ignore signup data file"
Key Takeaway
You just built a full-stack feature. Data flows from the user's browser, through your API route, into a database (JSON file for now). This is the same pattern used by every application in the world — you just did it with AI assistance.