Listen to this lesson
Course: From Vibe Coder to Developer | Pathway: Builder | Level: Advanced
Estimated Reading Time: 10 minutes
You've been vibe coding — describing what you want and letting AI generate the code. It works. But when you look at the files it created, you might see a blur of folders, filenames, and code you don't fully understand.
This lesson pulls back the curtain. We're going to look at what the AI is actually building when it generates a project, and give you the vocabulary to read and navigate any codebase.
Before diving into architecture, let's clarify which tools enable vibe coding in 2026. The most prominent is Cursor — an AI-native code editor that has become the industry standard for AI-assisted development. With Cursor surpassing $2 billion in annualized revenue in early 2026, it's validated as the primary tool transforming how developers build software.
Why Cursor matters: Unlike traditional editors with AI bolted on, Cursor rebuilt the entire editing experience around AI. You can describe what you want to build in plain English, and Cursor's integrated agents understand your full codebase — not just the file in front of you. This contextual awareness means it generates code that respects your project's conventions, imports existing utilities, and fits naturally into your architecture.
Other tools like GitHub Copilot, Claude Code, and Windsurf also support vibe coding workflows, but Cursor's combination of accuracy, full-project context, and competitive pricing ($20/month) has made it the default choice for developers transitioning from pure vibe coding to understanding the code they're creating.
The market split: The AI coding assistant market is now splitting rather than converging — different tools targeting different parts of the developer stack based on workflow needs rather than raw model capability alone. With Cursor hitting $2B ARR, we're seeing established players dominate specific niches: IDE-based assistance (Cursor/Windsurf), terminal agents (Claude Code), and cloud environments (Replit/GitHub Codespaces). Understanding this landscape helps you choose the right tool for your level and goals — there's no single best choice anymore.
When AI generates a project, it doesn't dump everything into one file. It creates a structure. Here's a typical web application:
my-app/
├── src/
│ ├── index.js # Entry point — where the app starts
│ ├── routes/
│ │ ├── users.js # Handles /users URL paths
│ │ └── products.js # Handles /products URL paths
│ ├── models/
│ │ ├── user.js # Defines what a "user" looks like in the database
│ │ └── product.js # Defines what a "product" looks like
│ └── utils/
│ └── helpers.js # Shared utility functions
├── tests/
│ └── users.test.js # Tests for user functionality
├── package.json # Project dependencies and scripts
├── .env # Secret configuration (API keys, etc.)
└── .gitignore # Files Git should ignore
This isn't random. There's a logic:
src/ — All your actual code lives here. "Source" code.routes/ — Code that handles incoming web requests. Each file covers a different area.models/ — Code that defines your data structures. What does a user look like? What fields does a product have?utils/ — Helper functions used across the project. Things like formatting dates or validating email addresses.tests/ — Code that checks if your other code works correctly.Python projects follow similar patterns with slightly different conventions:
my-app/
├── app/
│ ├── __init__.py # Makes this folder a Python package
│ ├── main.py # Entry point
│ ├── routes/
│ ├── models/
│ └── utils/
├── tests/
├── requirements.txt # Python dependencies
└── .env
A function is a named block of code that does one thing. When the AI generates code, it's mostly writing functions:
// A function that calculates a total with tax
function calculateTotal(price, taxRate) {
const tax = price * taxRate;
return price + tax;
}
// Using the function
const total = calculateTotal(100, 0.15); // Returns 115
# Same thing in Python
def calculate_total(price, tax_rate):
tax = price * tax_rate
return price + tax
total = calculate_total(100, 0.15) # Returns 115
Functions take inputs (parameters), do something, and return an output. The beauty is reuse — write it once, call it anywhere. When you see the AI creating functions, it's breaking the problem into manageable pieces.
No file exists alone. Code in one file uses code from another through imports:
// In utils/helpers.js
export function formatCurrency(amount) {
return `$${amount.toFixed(2)}`;
}
// In routes/products.js
import { formatCurrency } from "../utils/helpers.js";
const priceDisplay = formatCurrency(29.99); // "$29.99"
# In utils/helpers.py
def format_currency(amount):
return f"${amount:.2f}"
# In routes/products.py
from utils.helpers import format_currency
price_display = format_currency(29.99) # "$29.99"
The ../ in the JavaScript import means "go up one folder." These relative paths tell the computer where to find the file. When you see AI-generated imports, they're just connecting the dots between files.
The handler pattern — A function that receives a request and sends a response:
// Express.js route handler
app.get("/users/:id", async (req, res) => {
const user = await database.findUser(req.params.id);
if (!user) {
return res.status(404).json({ error: "User not found" });
}
res.json(user);
});
The model pattern — A definition of what your data looks like:
# A simple data model
class User:
def __init__(self, name, email):
self.name = name
self.email = email
def to_dict(self):
return {"name": self.name, "email": self.email}
The middleware pattern — Code that runs before your main logic, often for checking authentication or logging:
// Check if user is logged in before allowing access
function requireAuth(req, res, next) {
if (!req.headers.authorization) {
return res.status(401).json({ error: "Not authorised" });
}
next(); // Continue to the actual route handler
}
app.get("/dashboard", requireAuth, dashboardHandler);
The configuration pattern — Settings separated from logic:
# config.py
import os
from dotenv import load_dotenv
load_dotenv()
DATABASE_URL = os.getenv("DATABASE_URL")
API_KEY = os.getenv("API_KEY")
DEBUG = os.getenv("DEBUG", "false").lower() == "true"
When you open an AI-generated project (or any project), here's how to orient yourself:
Find the entry point. Look for index.js, main.py, app.py, or whatever package.json/requirements.txt references. This is where execution begins.
Read the configuration files. package.json tells you what libraries are used. requirements.txt does the same for Python. These are your dependency list.
Follow the flow. Start at the entry point and trace what happens when a request comes in or the program runs. Which files get imported? Which functions get called?
Look at the folder names. They tell you the architecture. routes/ means web endpoints. models/ means data definitions. services/ means business logic.
Check the tests. Test files often show you how the code is meant to be used, with clear examples of inputs and expected outputs.
package.json and requirements.txt ExplainedThese files list your project's dependencies — other people's code that your project uses:
// package.json (JavaScript)
{
"name": "my-app",
"scripts": {
"start": "node src/index.js",
"test": "jest"
},
"dependencies": {
"express": "^4.18.0",
"dotenv": "^16.0.0"
}
}
# requirements.txt (Python)
flask==3.0.0
anthropic==0.40.0
python-dotenv==1.0.0
When you run npm install or pip install -r requirements.txt, these files tell the package manager exactly what to download. The AI generates these automatically — now you know what they are.
routes/, models/, and utils/ follow conventions that organise code by responsibility.index.js or main.py and follow the flow from there.package.json and requirements.txt list the external libraries your code uses.Take a project you've built with AI (or generate a new one — ask an AI to "build a simple to-do list API with Express.js"). Before running it, read through every file and write a plain-English description of what each file does and how they connect to each other. Draw a simple diagram showing which files import from which other files.
1. What does the src/ folder typically contain in a project?
a) Configuration files and environment variables
b) The actual application source code
c) Test files and documentation
Answer: b) The src/ (source) folder contains the actual application code — your routes, models, utilities, and entry point. Configuration and tests typically live outside it.
2. What do import statements do?
a) Download new code from the internet
b) Make code from one file available for use in another file
c) Create backup copies of your functions
Answer: b) Import statements connect files together by making functions, classes, and variables from one file available in another. They're how code gets shared across a project.
3. Where should you start when trying to understand an unfamiliar project?
a) The largest file, since it contains the most logic
b) The entry point file (like index.js or main.py) and trace the flow from there
c) The test files, since they're the easiest to read
Answer: b) The entry point is where execution begins. Starting there and following the imports and function calls gives you a top-down understanding of how the application flows.