After this lesson, you will be able to: Navigate an unfamiliar codebase with a repeatable strategy, recognize how real projects are structured (monorepo vs multi-repo, layers, modules, services), and orient yourself fast on day one of a new job.
On your first day at any job, you inherit a codebase someone else wrote. Nobody hands you a tour. Reading unfamiliar code quickly is the skill that separates engineers who are productive in week one from engineers who flail for a month. It is a learnable, repeatable process, and most schools never teach it.
Studies of working engineers put time spent reading code at roughly ten times time spent writing it. Every feature you add, every bug you fix, every review you do starts with understanding code you did not write. The instinct of a beginner is to read a file top to bottom like a book. That does not work for a 200-file project. You need a strategy that starts from a question and follows the code that answers it.
Two big shapes. A monorepo keeps many projects (web app, API, shared libraries) in one Git repository, usually under a top-level `packages/` or `apps/` folder. A multi-repo (polyrepo) splits each project into its own repository. Inside any one project you will usually find: `src/` for source, `tests/` or `__tests__/` for tests, a config layer (`package.json`, `tsconfig.json`, `.env.example`), and often a layered structure: routes or controllers at the edge, services or domain logic in the middle, and data access at the bottom. Learn to recognize these so a new repo feels familiar even when the product is not.
Do these in order the first time you open a repo you have never seen.
Read the README and any docs/ folder first. It tells you what the thing is and how to run it.
Run it locally. A project you can start and click through is ten times easier to understand than one you only read.
Find the entry point: `main`, `index`, the server bootstrap, or the route table. Start where execution starts.
Pick one real feature and trace it end to end: from the URL or button, to the handler, to the service, to the database, and back.
Use search (grep / ripgrep / editor 'find in files') to jump to a symbol instead of scrolling. Search the error message, the route string, the function name.
Read the tests for the area you care about. Tests are executable documentation of what the code is supposed to do.
Use `git log` and `git blame` on a confusing file to see why it looks the way it does.
Following a single request through the layers is the fastest way to build a mental model.
// 1. The route (edge layer): where the request enters// src/routes/orders.tsrouter.post("/orders", requireAuth, createOrderHandler);// 2. The handler: validates input, calls the service// src/handlers/orders.tsexport async function createOrderHandler(req, res) {const input = CreateOrderSchema.parse(req.body); // search: CreateOrderSchemaconst order = await orderService.create(req.user.id, input); // search: orderServiceres.status(201).json({ data: order });}// 3. The service: the business logic// src/services/orderService.tsexport async function create(userId, input) {// ...rules live here. This is usually what you actually need to change.return db.order.create({ data: { userId, ...input } }); // search: db.order}// You just learned the whole vertical slice by following ONE feature// instead of reading 40 files in alphabetical order.
Reading top to bottom, file by file, instead of following one feature through the layers. Trying to understand everything before changing anything. You only need to understand the slice you are touching. Not running the project first. Reading code you cannot execute is guessing. Ignoring the tests. They tell you the intended behavior faster than the implementation does. Refactoring code you do not yet understand. Understand first, change second, or you will reintroduce the bug the weird-looking line was fixing.
Pick the most effective first move.
Sign in and purchase access to unlock this lesson.