Module 16: The Server-Side Era
How the web began — static pages, CGI scripts, and the rise of PHP (1991–2005)
Learning Objectives
By the end of this module, you will:
- Understand the original architecture of the web
- Know why CGI was revolutionary (and limited)
- See how PHP dominated web development
- Recognize server-side patterns still used today
- Appreciate why the "page refresh" era had to end
Time: 1-2 hours (reading)
Introduction
Before React. Before JavaScript frameworks. Before AJAX. There was... a page refresh.
Every interaction required:
- Click a link or submit a form
- Browser sends request to server
- Server generates entire HTML page
- Browser loads completely new page
This seems primitive now. But it was revolutionary in 1991.
Part 1: The Original Web (1991-1993)
Tim Berners-Lee's Vision
The web started as a document sharing system at CERN. The original components:
- HTML — Markup language for documents
- HTTP — Protocol for requesting documents
- URLs — Addresses for documents
- Web Server — Software that serves documents
- Browser — Software that displays documents
That's it. No JavaScript. No CSS. No interactivity.
What "Web Page" Meant
<html>
<head>
<title>CERN Information</title>
</head>
<body>
<h1>Welcome to CERN</h1>
<p>This is a paragraph about physics.</p>
<p>Here is a <a href="other-page.html">link</a> to another document.</p>
</body>
</html>
Web servers were file servers. You requested page.html, and the server sent page.html. Simple.
The Request-Response Model
Browser Server
│ │
│ GET /index.html HTTP/1.0 │
│ ─────────────────────────────►│
│ │
│ HTTP/1.0 200 OK │
│ <html>...</html> │
│ ◄─────────────────────────────│
│ │
│ (User clicks link) │
│ │
│ GET /other.html HTTP/1.0 │
│ ─────────────────────────────►│
│ │
Every navigation = new request = full page load.
Part 2: Dynamic Pages with CGI (1993-1998)
The Problem
Static HTML was limiting. What if you wanted:
- A page counter showing visits
- A guestbook where users leave messages
- Search results based on a query
- Content from a database
You can't do this with static files.
The CGI Solution
CGI (Common Gateway Interface) let web servers run programs.
Instead of:
GET /page.html → Server sends file
You could:
GET /cgi-bin/counter.pl → Server runs program → Program outputs HTML
A CGI Program (Perl)
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "<html><body>\n";
print "<h1>Page Views: 12,456</h1>\n";
print "</body></html>\n";
The program runs, outputs HTML to stdout, and the server sends that output to the browser.
CGI Architecture
┌─────────┐ ┌─────────┐ ┌──────────┐
│ Browser │ ───► │ Web │ ───► │ CGI │
│ │ ◄─── │ Server │ ◄─── │ Program │
└─────────┘ └─────────┘ └──────────┘
│ │
(passes request) (generates HTML)
CGI's Problems
- Performance: New process spawned for every request
- State: Each request independent (no sessions)
- Complexity: Managing HTML in print statements
- Security: Easy to create vulnerabilities
A busy site might spawn thousands of processes. Servers struggled.
Part 3: PHP Changes Everything (1995-2005)
The PHP Revolution
PHP (originally "Personal Home Page") solved CGI's problems:
- Ran as a module inside the web server (no new process)
- Mixed HTML and code naturally
- Built-in features for forms, databases, sessions
- Easy to learn for non-programmers
PHP Templating
Instead of printing HTML from code, embed code in HTML:
<html>
<body>
<h1>Welcome, <?php echo $username; ?>!</h1>
<?php if ($isLoggedIn): ?>
<p>You have <?php echo $messageCount; ?> new messages.</p>
<?php else: ?>
<p>Please <a href="login.php">log in</a>.</p>
<?php endif; ?>
<h2>Recent Posts</h2>
<?php foreach ($posts as $post): ?>
<div class="post">
<h3><?php echo $post['title']; ?></h3>
<p><?php echo $post['content']; ?></p>
</div>
<?php endforeach; ?>
</body>
</html>
The LAMP Stack
PHP's dominance was powered by LAMP:
- Linux (operating system)
- Apache (web server)
- MySQL (database)
- PHP (language)
Free, open-source, and available from every hosting provider. WordPress, Facebook, and Wikipedia all started on PHP.
Server-Side Rendering Pattern
Every page request:
1. Browser requests /posts.php
2. Apache receives request, invokes PHP
3. PHP:
- Connects to MySQL
- Queries for posts
- Loops through results
- Generates complete HTML
4. Apache sends HTML to browser
5. Browser renders page
The browser receives finished HTML. No JavaScript required.
Part 4: The Full Page Refresh Problem
What Users Experienced
Every interaction = white flash + wait:
Action Result
─────────────────────────────────────────
Click "Add to Cart" → Full page reload
Submit comment → Full page reload
Click pagination → Full page reload
Change dropdown → Full page reload
Users in 2004 waited 2-5 seconds per page load. Interactions felt slow and disconnected.
The Architecture Limitation
The protocol was designed for documents:
┌──────────────────────────────────────────────────────────────┐
│ HTTP was designed for: │
│ │
│ "I want document X" → "Here is document X" │
│ │
│ NOT for: │
│ │
│ "Update this small part of the page" │
│ "Add this item without losing scroll position" │
│ "Show new comments without refreshing" │
└──────────────────────────────────────────────────────────────┘
Desktop Apps vs Web Apps
Desktop applications (Outlook, Word) had rich, responsive interfaces. Web applications felt primitive by comparison.
People asked: "Why can't the web work like a desktop app?"
Part 5: JavaScript's Early Days
JavaScript Arrives (1995)
Brendan Eich created JavaScript in 10 days at Netscape. Original purpose: small interactions without server round-trips.
// Early JavaScript (1995-2005)
function validateForm() {
if (document.forms[0].email.value == "") {
alert("Please enter your email!");
return false;
}
return true;
}
What JavaScript Could Do
- Form validation before submit
- Image rollovers (hover effects)
- Pop-up windows
- Simple animations
- Browser detection
What JavaScript Couldn't Do (Yet)
- Update page content dynamically
- Communicate with servers
- Complex data manipulation
- Reliable cross-browser behavior
JavaScript was seen as a toy. "Real" applications were built server-side.
Part 6: Session and State Management
The Stateless Problem
HTTP is stateless. Each request is independent. The server doesn't remember you.
Request 1: "Show me products" → Server: "Here are products"
Request 2: "Add item to cart" → Server: "Who are you?"
Solutions That Emerged
Cookies (1994):
Server: "Here's a cookie: session_id=abc123"
Browser: (stores cookie)
Browser: "GET /cart (cookie: session_id=abc123)"
Server: "Ah, you're user abc123. Here's your cart."
Server-side sessions:
sessions/abc123.txt:
username=john
cart=[item1, item2]
last_seen=2004-03-15
Database storage:
SELECT * FROM sessions WHERE session_id = 'abc123';
SELECT * FROM carts WHERE user_id = 42;
These patterns are still used today. Your React app's authentication probably uses cookies and sessions.
Part 7: What Worked (And Still Does)
Patterns That Survive
URL-based routing:
/products/123 → Show product 123
/users/john/posts → Show john's posts
/search?q=lemonade → Search results
Form handling:
<form action="/submit" method="POST">
<input name="email" type="text">
<button type="submit">Subscribe</button>
</form>
Template composition:
<?php include 'header.php'; ?>
<main>Page content</main>
<?php include 'footer.php'; ?>
MVC architecture (emerged in this era):
- Model: Data and business logic
- View: HTML templates
- Controller: Request handling
Why Server-Side Rendering Is Back
Modern frameworks (Next.js, Remix) bring back server-side rendering because:
- Better SEO (search engines see content)
- Faster first paint (no JavaScript needed for initial view)
- Works without JavaScript
- Simpler mental model for some apps
The wheel turns.
Part 8: The Tipping Point
By 2004-2005
The web had:
- Millions of PHP/ASP/JSP applications
- Rich desktop-like needs
- Users frustrated with page refreshes
- JavaScript improving in browsers
Gmail Changes Expectations (2004)
Google launched Gmail. It felt different:
- No page refresh when reading emails
- Instant search
- Smooth, app-like experience
- Still running in the browser
How? A technique called AJAX (which we'll cover in Module 17).
The Stage Was Set
The server-side era built the foundation:
- HTTP and URL conventions
- Session management
- Template-based rendering
- Database-driven applications
But users wanted more. The AJAX revolution was about to begin.
Exercise 1: Trace a Traditional Request
Think through what happens when a user submits a form on a PHP site:
- User fills out form, clicks Submit
- List every step until they see the response
Solution
- User fills form, clicks Submit
- Browser collects form data
- Browser sends POST request to server (full page navigation)
- Server receives request
- PHP script runs:
- Parses form data
- Validates input
- Connects to database
- Inserts/updates data
- Queries for page data
- Renders complete HTML template
- Server sends HTML response
- Browser discards current page entirely
- Browser parses new HTML
- Browser loads CSS, images, JavaScript (even if same as before)
- Browser renders page
- User sees result (scroll position reset, UI state lost)
Every navigation repeated this entire cycle.
Exercise 2: Identify the Limitations
For each scenario, explain why full-page refresh is problematic:
- User adds item to shopping cart
- User submits a comment on a post
- User filters a product list by category
- Chat application showing new messages
Discussion
-
Shopping cart: User loses scroll position, maybe in the middle of browsing. Cart update should be instant, not disruptive.
-
Comment submission: After posting, user is back at top of page, not seeing their comment in context. Other comments they were reading are "reset."
-
Product filtering: Every filter change = full reload. Users want to quickly toggle filters and see results update. Multi-second waits for each filter are frustrating.
-
Chat application: Impossible with page refresh. Can't poll for new messages smoothly. User would see page flash every few seconds.
Exercise 3: Server-Side Template
Write a simple server-side template (pseudocode or PHP-like) that:
- Shows a welcome message with username
- Lists items in a shopping cart
- Shows total price
Example
<html>
<body>
<h1>Welcome, <?= $user->name ?>!</h1>
<h2>Your Cart</h2>
<?php if (empty($cart->items)): ?>
<p>Your cart is empty.</p>
<?php else: ?>
<ul>
<?php foreach ($cart->items as $item): ?>
<li>
<?= $item->name ?> - $<?= number_format($item->price, 2) ?>
× <?= $item->quantity ?>
</li>
<?php endforeach; ?>
</ul>
<p><strong>Total: $<?= number_format($cart->total, 2) ?></strong></p>
<?php endif; ?>
<a href="/checkout">Proceed to Checkout</a>
</body>
</html>
Notice: All logic runs on server. Browser just displays HTML.
Key Takeaways
-
The web started as documents — HTML files served statically
-
CGI enabled dynamic pages — But with performance costs
-
PHP dominated — By mixing code and HTML seamlessly
-
Full page refresh was the only option — Every interaction reloaded everything
-
Sessions solved statelessness — Cookies and server storage
-
Server-side patterns persist — URLs, forms, MVC, templates
-
User expectations grew — Desktop-like apps demanded better
What's Next
Module 17: The AJAX Revolution
You'll learn:
- How XMLHttpRequest changed everything
- The rise of jQuery
- "Web 2.0" and rich internet applications
- Why this era created both possibilities and chaos
You've completed Module 16! You now understand the web's origins. Everything that came after was a response to the limitations you've just learned about.