Skip to main content

The Big Picture

When you build an app, you’re really building two things that talk to each other: a frontend (what users see) and a backend (where data lives and logic happens). Think of it like a restaurant: the frontend is the dining room where customers interact, and the backend is the kitchen where the real work gets done.

Where Does Your Data Live?

This is the #1 source of confusion. Your data exists in three different places, and understanding this is critical:

Browser Memory

Temporary data while the page is open. Disappears on refresh.

Session Storage

Temporary data for your browsing session. Gone when you close the tab.

Database

Permanent storage. Data persists forever (until you delete it).

The Todo List Example

Imagine you’re building a todo list app:
// This only lives in browser memory
let todos = ["Buy milk", "Walk dog"];

// When you refresh the page... POOF! It's gone.
To make it permanent, you need to save it to a database. That’s what databases do - they remember things even after you close your app.
If you’re building something and refreshing the page loses your data, you haven’t connected to a database yet. Your data is only living in browser memory.

Frontend vs Backend: The Restaurant Analogy

Frontend (Dining Room)Backend (Kitchen)
What users see and interact withWhere data is stored and processed
Runs in the browserRuns on a server
HTML, CSS, JavaScriptNode.js, Python, databases
Makes requests for dataResponds with data
Cannot directly access databasesHas full database access

Why They’re Separate

Your frontend code runs on the user’s computer (in their browser). Your backend runs on your server. This means:
  • The frontend has to ask the backend for data
  • The backend decides if the request is allowed
  • The frontend waits for the response
  • The backend sends data back
This is called the request/response cycle, and it’s fundamental to how the web works.

The Request/Response Cycle

Here’s what actually happens when you click a button in an app:
1

User Action

You click “Show my todos”
2

Frontend Sends Request

Browser sends: GET /api/todos
3

Backend Processes

Server receives request, queries database
4

Database Returns Data

Database sends todos back to backend
5

Backend Sends Response

Backend sends JSON data to frontend
6

Frontend Displays

Browser renders the todos on screen
This happens in milliseconds, but it’s not instant. That’s why you see loading spinners - the frontend is waiting for the backend to respond.

Code Example

// Frontend code
async function getTodos() {
  // This ASKS the backend for data
  const response = await fetch('/api/todos');
  const todos = await response.json();
  
  // Now we can display them
  displayTodos(todos);
}
// Backend code (Node.js/Express)
app.get('/api/todos', async (req, res) => {
  // Backend queries the database
  const todos = await database.collection('todos').find();
  
  // Backend sends data back to frontend
  res.json(todos);
});
Notice how the frontend cannot directly access the database. It must go through the backend. This is a security feature - you don’t want users able to access your database directly from their browser.

What Is a Database?

A database is permanent storage for your app’s data. Think of it like a super-organized filing cabinet that never forgets.

MongoDB Basics

MongoDB stores data in collections of documents. Think of it like this:
  • Database = The entire filing cabinet
  • Collection = A drawer in the cabinet (e.g., “users”, “todos”, “posts”)
  • Document = An individual file/record in that drawer

Documents Look Like JavaScript Objects

// This is a document in your "users" collection
{
  _id: "507f1f77bcf86cd799439011",  // MongoDB's auto-generated ID
  name: "Sarah",
  email: "sarah@example.com",
  age: 28,
  todos: [
    { task: "Buy milk", done: false },
    { task: "Walk dog", done: true }
  ]
}
If you know how to work with JavaScript objects, you already know how to work with MongoDB documents!

CRUD: The Four Things You Do With Data

Every app is basically doing these four operations in different combinations:

Create

Add new data (signup, create post, add todo)

Read

Get existing data (login, view profile, show todos)

Update

Change existing data (edit profile, mark todo done)

Delete

Remove data (delete account, remove todo)
Once you realize that 90% of your app is just CRUD operations, everything becomes much clearer.

How Code Actually Runs

Frontend Code (Browser)

// This runs on the USER'S computer
console.log("Hello from the browser!");

// Users can see this code if they open dev tools
const apiKey = "secret123";  // NEVER DO THIS
Everything in your frontend code is visible to users. Never put passwords, API keys, or secrets in frontend code. Users can read every line.

Backend Code (Server)

// This runs on YOUR server
console.log("Hello from the server!");

// Users CANNOT see this code
const secretKey = process.env.DATABASE_PASSWORD;  // This is safe
The backend is where you:
  • Connect to databases
  • Store secrets and API keys
  • Validate data before saving
  • Control who can access what

Environment Variables: Keeping Secrets Secret

Your database password, API keys, and other secrets go in a special file called .env:
# .env file (never commit this to GitHub!)
DATABASE_URL=mongodb://username:password@host:27017
API_SECRET_KEY=your-secret-key-here
In your code, you access them like this:
const dbPassword = process.env.DATABASE_URL;
Always add .env to your .gitignore file so it’s never uploaded to GitHub. If you accidentally expose your database password, change it immediately.

Collections and Relationships

What Is a Collection?

A collection is a group of similar documents. Common collections include:
  • users - All your user accounts
  • posts - All blog posts or content
  • comments - All comments on posts
  • todos - All todo items
Let’s say you have users and posts. How do you know which posts belong to which user?
// User document
{
  _id: "user123",
  name: "Alex"
}

// Post document
{
  _id: "post456",
  title: "My First Post",
  authorId: "user123",  // This links to the user!
  content: "Hello world..."
}
When you want to show a post with the author’s name, you:
  1. Get the post
  2. Look up the user by authorId
  3. Display both together
This is called referencing or relational data.

The Schema Question

MongoDB doesn’t enforce a schema (structure) by default, which means you can do this:
// These are both valid in MongoDB
{ name: "Alex", age: 30 }
{ name: "Sarah", age: "twenty-eight", favoriteColor: "blue" }
But you shouldn’t. Your app expects consistent data structures. This is why, in the Emergent environment, you should prompt the agent to maintain consistent schema.
Even though MongoDB is “schema-less”, treat it like it has a schema. Your future self will thank you when debugging.

Async/Await: Why Things Don’t Happen Instantly

When you fetch data from a database or API, it takes time. You need to wait for the response:
// This doesn't work
const todos = fetch('/api/todos');
console.log(todos);  // This runs before data arrives!

// This works
const todos = await fetch('/api/todos');
console.log(todos);  // Now we have the data
The await keyword says “pause here until the data arrives”. Any function using await must be marked async as a best practice.
async function getTodos() {
  const response = await fetch('/api/todos');
  const data = await response.json();
  return data;
}

Putting It All Together

Here’s the complete flow of a typical app feature, using the same example of the to-do app:
1

User Interacts

Clicks “Add Todo” button in the frontend
2

Frontend Sends Request

POST request to /api/todos with todo data
3

Backend Validates

Checks if the request is valid and allowed
4

Backend Saves to Database

Inserts the new todo into the todos collection
5

Database Confirms

Returns the saved document with its new _id
6

Backend Responds

Sends success response back to frontend
7

Frontend Updates

Displays the new todo on screen

Key Takeaways

Frontend = Display

Shows data and collects input. Runs in the browser.

Backend = Logic

Processes requests and stores data. Runs on your server.

Database = Memory

Permanent storage. Survives refreshes and restarts.

API = Middleman

Connects frontend and backend through endpoints.
The hardest part about learning to code isn’t the syntax - it’s understanding where code runs, where data lives, and how it all connects. Master these concepts and everything else falls into place.