Learn

Navigate through learn topics

SSR, SSG, CSR

How a Web Page is Born & How Different Rendering Methods Shape the Web

Last updated: 8/15/2025

The Many Roads to a Web Page

There are many ways to make a web page appear on your screen.
Some are as simple as passing a handwritten note.
Others are more like a choreographed dance between your browser and distant computers, each step timed perfectly to bring your screen to life.

If you’ve ever visited Wikipedia, booked a place on Airbnb, watched a video on YouTube, or browsed a shop like Amazon, you’ve been walking one of these roads, even if you didn’t know it.

Let’s start with the simplest path, then we’ll gradually turn up the technical microscope.

Static HTML - The Printed Poster

In the earliest days of the web, sites were just files. You wrote them once and they stayed that way until someone edited them by hand.

Example:
A personal “About Me” page from the 90s, or a local café’s one-page website.

How it works:

  • You request index.html.
  • The server sends the file exactly as it’s stored.
  • No database, no APIs - just pure HTML.

Pros:

  • Super fast to load.
  • Easy to host anywhere.

Cons:

  • No dynamic updates without editing the file.
  • Everyone sees the same thing.

SSR - Server-Side Rendering (Made to Order)

Think of Server-Side Rendering like ordering a fresh sandwich at a deli.
When you request a page:

  1. The server fetches the latest data.
  2. It “mixes” that data into HTML.
  3. It sends the finished HTML to your browser.

Examples:

  • Airbnb listing pages - loads fresh availability & price every time.
  • BBC News articles - the text is already in the HTML when you load it.

View Source test:
Right-click → View Page Source. If you see the content (headlines, text, product names) in the HTML, it’s likely SSR.

SSG - Static Site Generation (Prebuilt Goodness)

This is like making sandwiches in the morning so you can hand them out all day.
Static Site Generation builds the HTML ahead of time, often at deployment.

Examples:

  • Documentation sites (Next.js docs, React docs).
  • Wikipedia (yes, many Wikipedia pages are pre-generated for speed).

Pros:

  • Very fast - can be served from a CDN.
  • Almost no server cost per visitor.

Cons:

  • The data can get stale until you rebuild.

ISR - Incremental Static Regeneration (Auto Freshness)

ISR is the magical fridge that replaces the sandwich with a fresh one every so often - without shutting down the shop.

Examples:

  • eCommerce category pages that don’t change every second but need periodic updates.
  • Blog homepages on platforms like Vercel or Netlify with Next.js.

CSR - Client-Side Rendering (Fill It In Yourself)

With Client-Side Rendering, the server sends a mostly empty page and JavaScript fills in the blanks later.

Examples:

  • YouTube video pages - the base loads fast, then comments, recommendations and other dynamic sections load via JavaScript.
  • Gmail - loads a blank shell, then fetches your email data.

View Source test:
If the text isn’t in the HTML but appears later, it’s CSR.

The Big Three (and Friends) - Side-by-Side Pipelines

A Visual Diagram

Here’s how each approach moves data from the database to your screen.  
Follow the numbers in each column to see the order of events.

                          ┌──────────────────┐
                          │    Browser       │
                          │ (User's Device)  │
                          └───────┬──────────┘
                                  │
                  (1) Ask for a page
         ┌────────────────────────┼──────────────────────────┐
         │                        │                          │
   ┌─────▼───────┐          ┌─────▼───────┐            ┌─────▼───────┐
   │   SSR       │          │   SSG       │            │   CSR       │
   │ (Made live) │          │ (Prebuilt)  │            │ (Fill later)│
   └─────┬───────┘          └─────┬───────┘            └─────┬───────┘
 (2a) Server calls          (2b) HTML was prebuilt     (2c) HTML shell sent now
      API for fresh data         at build time              (empty lunchbox)
         │                        │                          │
         ▼                        ▼                          │
 (3a) Call API to get       (3b) Serve HTML instantly   (3c) Browser calls API
      data for this page         from cache/CDN               after load
         │                        │                          │
         ▼                        │                          ▼
   ┌─────────────┐          ┌─────────────┐            ┌─────────────┐
   │   API       │<---------│   ISR       │            │    API      │
   │  Endpoints  │    (3b1) │ ISR refresh │            │  Endpoints  │
   └─────┬───────┘          │ when stale  │            └─────┬───────┘
 (4a) Pass data to          └─────────────┘             (4c) Pass data
      the server                                         to browser
         │                                                  │
         ▼                                                  │
   ┌─────────────┐                                     ┌─────────────┐
   │  Database   │                                     │  Database   │
   │ (Supabase)  │                                     │ (Supabase)  │
   └─────┬───────┘                                     └─────┬───────┘
  (5a) Query data                                     (5c) Query data
         │                                                   │
   (6a) Apply RLS                                     (6c) Apply RLS
         ▼                                                   ▼
   ┌─────────────┐                                     ┌─────────────┐
   │    RLS      │                                     │    RLS      │
   │ (Security)  │                                     │ (Security)  │
   └─────────────┘                                     └─────────────┘

Side-by-side Vertical "Pipelines"

┌──────────────────────── SSR (Server-Side Rendering) ────────────────────────┐
│ (1) Browser asks for page                                                   │
│  │                                                                          │
│ (2a) Server prepares to fetch fresh data                                    │
│  │                                                                          │
│ (3a) Server calls API for this request                                      │
│  │                                                                          │
│ (4a) API fetches from Database                                              │
│  │                                                                          │
│ (5a) Database runs query                                                    │
│  │                                                                          │
│ (6a) RLS policies applied (who can see what)                                │
│  │                                                                          │
│  ▼                                                                          │
│ HTML with data is returned to Browser (content appears in View Source)      │
└─────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────── SSG/ISR (Static + Regen) ───────────────────────────┐
│ (1) Browser asks for page                                                   │
│  │                                                                          │
│ (2b) Page was prebuilt at build-time (static HTML exists)                   │
│  │                                                                          │
│ (3b) Serve cached/prebuilt HTML instantly (often from CDN)                  │
│  │                                                                          │
│ ── ISR background refresh when stale:                                       │
│     (3b1) Trigger regeneration in background                                │
│       │                                                                     │
│     (4a)  Regen calls API                                                   │
│       │                                                                     │
│     (5a)  Database query                                                    │
│       │                                                                     │
│     (6a)  RLS policies applied                                              │
│       ▼                                                                     │
│     New static HTML replaces old cache (future visitors get fresh content)  │
│                                                                             │
│ Result: Fast initial load; content is in View Source; stays fresh on timer  │
└─────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────── CSR (Client-Side Rendering) ────────────────────────┐
│ (1) Browser asks for page                                                   │
│  │                                                                          │
│ (2c) Server sends HTML shell + JS (mostly empty at first)                   │
│  │                                                                          │
│ (3c) Browser runs JS and calls API after load                               │
│  │                                                                          │
│ (4c) API fetches from Database                                              │
│  │                                                                          │
│ (5c) Database runs query                                                    │
│  │                                                                          │
│ (6c) RLS policies applied                                                   │
│  │                                                                          │
│  ▼                                                                          │
│ JSON returned to Browser → JS injects data into the page (NOT in Source)    │
└─────────────────────────────────────────────────────────────────────────────┘

The Role of APIs and RLS

  • API Endpoints are messengers - special URLs that return data (often JSON) instead of full pages.
  • Database is the treasure chest where all the data lives.
  • RLS (Row Level Security) is the lock on that treasure chest. It decides which rows and columns each visitor can see.

Real example:
On Airbnb, the public can see listing details, but host contact info is locked behind an account with permission - that's RLS in action.

Security Takeaway

Anything you send to the browser - whether in HTML (SSR, SSG, ISR) or via JSON (CSR) - is public to anyone who can open DevTools.
To protect sensitive data:

  • Only request the fields you actually need (.select('headline, price, beds') not *).
  • Use RLS in Supabase/Postgres.
  • Keep secret keys and admin data on the backend only.

Putting It All Together

When you click on a link:

  1. Routing decides which rendering method to use.
  2. Data fetching happens from an API or database.
  3. Rendering turns that data into HTML or injects it later with JS.
  4. Your browser paints it on your screen.

And that's how a web page is born - whether it's a Wikipedia article (SSG), an Airbnb listing (SSR), or a YouTube video page (CSR).