# Adding a Backend: API Routes and Database

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

<div class="concept-box">
<h4>Concept</h4>
Every web application has the same basic flow:
<br><br>
<strong>User's Browser (Frontend)</strong> → <strong>API Route (Backend)</strong> → <strong>Database</strong> → <strong>Response back to Browser</strong>
<br><br>
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.
</div>

## 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."

<div class="try-it">
<h4>Try It</h4>
In Claude Code, type:<br><br>
<strong>"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"</strong>
</div>

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:

```json
[
  { "email": "user@example.com", "timestamp": "2026-04-11T10:30:00Z" }
]
```

<div class="honest-note">
<h4>Honest Note</h4>
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.
</div>

## Connecting Frontend to Backend

Now let's update the signup form to actually POST data to our new API route:

<div class="try-it">
<h4>Try It</h4>
In Claude Code:<br><br>
<strong>"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"</strong>
</div>

### Testing It

1. Make sure your dev server is running (`npm run dev`)
2. Go to http://localhost:3000
3. Enter an email and submit the form
4. Check `data/signups.json` — your email should be there!
5. Try submitting the same email again — you should see a "duplicate" error

<div class="try-it">
<h4>Try It</h4>
Submit a few different emails through the form. Then open <code>data/signups.json</code> in VS Code to verify they're all there. You just built a full-stack feature!
</div>

## 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.

<div class="concept-box">
<h4>Concept</h4>
<strong>Never trust data from the client.</strong> 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).
</div>

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:**
1. Open Developer Tools (F12)
2. Go to the Network tab
3. Submit the form
4. Click on the `signup` request 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

<div class="honest-note">
<h4>Honest Note</h4>
This is a learning project, and that's okay. But a production application needs more:
<br><br>
- <strong>Authentication</strong> — verifying who is making requests
- <strong>Rate limiting</strong> — preventing abuse (we added basic limiting above)
- <strong>Input sanitization</strong> — preventing injection attacks
- <strong>HTTPS</strong> — encrypting data in transit
- <strong>Environment variables</strong> — keeping secrets out of code
<br><br>
Claude can help you add all of these, but it's important to know they exist. Security isn't optional in real applications.
</div>

## 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.

<div class="checkpoint">
<h4>Checkpoint</h4>
Your signup form now actually stores data. Emails are validated on both client and server, duplicates are rejected, and everything is saved to a file. Git committed. Next: building an admin dashboard to see your data.
</div>
