RizTech Academy logo
RizTech Academy
How a Full-Stack Application Fits TogetherLesson 1 of 425 min

The shape of a modern web application

Before any code, a mental model. Most confusion in full-stack work comes from not knowing which machine a piece of code is running on, and everything in this course attaches to the picture built here.

Two computers

A web application runs on two computers that do not trust each other.

The client is the user's browser, on their phone or laptop. It renders the interface, reacts to taps, and can be opened, inspected and modified by anyone.

The server is a machine you control. It holds the database, enforces the rules, and keeps the secrets.

They communicate over HTTP: the browser asks, the server answers. Nothing else passes between them.

That single fact — two computers, one of which you do not control — explains most of the design decisions in this course. Why validation happens twice. Why API keys never reach the browser. Why the price of an item is looked up on the server rather than read from the page.

What we are building with

Browser                          Server
────────                         ──────
Next.js + React      ⇄ HTTP ⇄    NestJS
                                    │
                                 Prisma
                                    │
                                PostgreSQL

React builds interfaces from components. It describes what the screen should look like for the current data, and updates it when the data changes.

Next.js is a framework around React. It adds routing, and — importantly for a shop — the ability to render pages on the server so they arrive as HTML that Google can read.

NestJS is the back end: a Node.js framework, written in TypeScript, that organises server code into modules with explicit dependencies.

Prisma talks to the database with types generated from your schema, so a misspelled column is a compile error rather than a runtime one.

PostgreSQL stores the data.

Both halves are TypeScript, which is the reason for that prerequisite. One language, and the types can travel between them.

The life of a page view

Somebody opens your shop and taps a product. Following the whole path:

  1. The browser requests /products/atta-5kg.
  2. Next.js, on the server, matches the route.
  3. It calls the NestJS API for that product.
  4. NestJS asks Prisma for it, which issues SQL to PostgreSQL.
  5. The row comes back, becomes a typed object, and is returned as JSON.
  6. Next.js renders React components to HTML on the server.
  7. The browser receives HTML and shows the page — including to Google's crawler, which does not wait for JavaScript.
  8. React then "hydrates" the page in the browser, attaching event handlers so the Add to Cart button works.

Steps 6 to 8 are the part worth slowing down on. The page is rendered twice in a sense: once on the server to produce HTML anyone can read, and once in the browser to make it interactive. Getting that division right is most of what the Next.js module is about.

Why not just one computer

You could serve HTML from the server and skip React entirely. For a blog, you should — that is what this site's own blog does.

A shop is different. A cart that updates without reloading, filters that apply instantly, a quantity stepper that responds to a tap: those need code running in the browser. React is how you manage that without the interface and the data drifting apart.

The trade-off is real. A React application ships JavaScript the user must download and run, which costs time on a cheap phone on a slow connection — which is most of your customers. This is why the course uses server components wherever it can and sends JavaScript only where interactivity requires it.

Why separate the API

We could put everything in Next.js. It can talk to a database directly, and for a small project that is a reasonable choice.

A separate NestJS API earns its place when:

  • Something else will use it. A delivery app for the shop owner, an admin tool, a partner integration. The API serves them all.
  • The rules are substantial. Stock, pricing, order state. NestJS gives that logic a structure that scales past a few files.
  • The two halves change at different speeds, or are worked on by different people.

Being straight with you: for the Kirana Store alone, Next.js on its own would work. We build both because learning the separation is the point — almost every job you take will have an API and a front end, often not even in the same language, and the seam between them is where the interesting problems live.

Where things run

A table to come back to:

Thing Runs on Visible to the user
React components (server) Server No — only their output
React components (client) Browser Yes, fully
Next.js route handlers Server No
Server actions Server No
NestJS controllers and services Server No
Database queries Server No
Environment variables without NEXT_PUBLIC_ Server No
Environment variables with NEXT_PUBLIC_ Browser Yes

The last two rows are worth committing to memory now. Prefixing a secret with NEXT_PUBLIC_ ships it to every visitor, and it is one of the easier ways to leak an API key.

The rules that follow from the model

Three, and everything else in the course is downstream of them.

Never trust the client. Anything the browser sends can be edited. A hidden field saying the price is ₹1 will be sent. Validate on the server, always, even when you also validate in the browser for a better experience.

Keep secrets on the server. Database passwords, payment keys, admin tokens. If the browser can read it, assume everyone can.

Decide where each piece of logic belongs. Formatting a date for display is a browser job. Deciding whether an order can be placed is a server job. When you are unsure, ask what happens if a user changes the answer — if that matters, it belongs on the server.

Check your work

The two computers: the client, which is the user's browser and which you do not control, and the server, which you do.

Where each runs: checking a password is the server — it needs the stored hash and must not be bypassable. A password strength meter is the browser, for instant feedback. Calculating an order total is the server, because the user must not be able to change it. Animating a dropdown is the browser. Checking stock before checkout is the server. Formatting ₹1,234.50 is either, but pick one place and keep it there.

The hidden price field attack: the user edits the hidden value in DevTools before submitting and is charged whatever they typed.

What renders without JavaScript: anything the server sent as HTML. A page that is blank with JavaScript off was rendered entirely in the browser, which means crawlers and social previews see nothing.

Why a request after page load: the first response did not include that data — usually because it is user-specific, slow, or only needed after an interaction.

Practice

No code. Get the model straight first.

  1. Draw the diagram from memory: browser, server, database, and what connects them.
  2. For each, say which machine it runs on and why: checking a password · showing a password strength meter · calculating an order total · animating a dropdown · checking stock before checkout · formatting ₹1,234.50.
  3. A hidden form field holds the price and the server trusts it. Describe the attack in one sentence.
  4. Open any large e-commerce site, disable JavaScript, and reload a product page. What still works? What does that tell you about how it was built?
  5. In the same site's network tab, find one request the browser makes after the page loads. What is it fetching, and why was that not part of the first response?

Next: the same question at a finer grain — what runs where, and the mistakes that follow from getting it wrong.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship