Alpha ZealPHP is early-stage and under active development. APIs may change between minor versions until v1.0. Feedback and bug reports welcome on GitHub.

React vs PHP

Why most web apps don't need a JavaScript framework — and what to use instead.

You will learn

  • What React actually solves — and what it doesn't
  • The hidden cost of a JavaScript-first architecture
  • Why server-rendered HTML + htmx covers 95% of web apps
  • When you SHOULD reach for React (and when you shouldn't)

The question nobody asks

When a team starts a new web project in 2026, the default is React. Not because they evaluated alternatives. Not because the project needs client-side state management. Just because "that's what you use." Nobody asks: does this project actually need a JavaScript framework?

This lesson asks that question. The answer, for most projects, is no.

What React actually solves

React was built at Facebook to solve a specific problem: complex, interactive UIs with lots of shared client-side state. The news feed, where a like on one post updates a counter in the header, a notification badge, and a sidebar — all at once, without a page reload. That's genuinely hard without a framework.

React is brilliant for:

  • Spreadsheet-like interfaces — cells that depend on other cells
  • Design tools — Figma, Canva, drag-and-drop builders
  • Collaborative editors — Google Docs, real-time cursors
  • Complex dashboards — 50+ interactive widgets, filters that affect each other

These are applications that live in the browser. The server is a data API. The client IS the application.

What most teams actually build

But most web projects aren't Figma. They're:

  • A SaaS dashboard with forms, tables, and charts
  • An admin panel for managing content
  • A landing page with a contact form
  • An e-commerce site with product listings and checkout
  • An internal tool for querying databases
  • A blog, a docs site, a learning platform (like this one)

These are document-centric applications. The server has the data. The client displays it. Interactions are form submissions, list filters, and page navigation. React solves a problem they don't have.

The hidden cost

Choosing React for a document-centric app doesn't just add complexity. It multiplies it:

graph LR
    subgraph "React + Node stack"
      R[React App] --> B[Bundler
Webpack/Vite] B --> H[Hydration] R --> S[State Mgmt
Redux/Zustand] R --> API[REST/GraphQL API] API --> N[Node.js Server] N --> DB[(Database)] N --> RD[(Redis)] N --> Q[Queue Worker] end style R fill:#fef2f2,stroke:#f87171 style B fill:#fef2f2,stroke:#f87171 style H fill:#fef2f2,stroke:#f87171 style S fill:#fef2f2,stroke:#f87171 style N fill:#fef2f2,stroke:#f87171 style RD fill:#fef2f2,stroke:#f87171 style Q fill:#fef2f2,stroke:#f87171
graph LR
    subgraph "ZealPHP + htmx"
      P["php app.php"] --> T[Templates
PHP + HTML] T --> HX[htmx attrs] P --> DB2[(SQLite/MySQL)] P --> WS2[WebSocket] P --> SSE[SSE Streaming] end style P fill:#ecfdf5,stroke:#059669,stroke-width:2px style T fill:#ecfdf5,stroke:#059669 style HX fill:#ecfdf5,stroke:#059669 style WS2 fill:#ecfdf5,stroke:#059669 style SSE fill:#ecfdf5,stroke:#059669
Concern React + Node ZealPHP + htmx
LanguagesJavaScript + TypeScript + JSX + CSS-in-JSPHP + HTML + CSS
Build stepWebpack/Vite, 30s–2minNone. Save and refresh.
Client JS200–500 KB (min+gzip)14 KB (htmx) + 0 custom
HydrationServer renders HTML, client re-renders it in JSServer renders HTML. Done.
State managementRedux / Zustand / Context + hooksServer is the state. Session + DB.
API layerREST or GraphQL + client fetching + loading stateshtmx posts, server returns HTML fragment
RoutingClient-side router + server routes + code splittingFile = URL. One router.
SEOSSR/SSG required (Next.js, Remix)Server-rendered by default
ProcessesNode + Redis + queue + maybe Nginxphp app.php

The htmx insight

React replaces the browser's rendering model. You write JSX, React builds a virtual DOM, diffs it, and patches the real DOM. This makes sense when the client IS the application.

But for document-centric apps, the browser's rendering model is fine. You just need to swap parts of the page without a full reload. That's exactly what htmx does:

<!-- React: 47 lines -->
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
  e.preventDefault();
  setLoading(true);
  const res = await fetch('/api/items', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({title: input})
  });
  const newItem = await res.json();
  setItems([newItem, ...items]);
  setLoading(false);
  setInput('');
};
// ... plus JSX template, useEffect for initial load,
// error handling, TypeScript types, etc.

<!-- htmx: 4 attributes -->
<form hx-post="/api/items"
      hx-target="#list"
      hx-swap="afterbegin"
      hx-on::after-request="this.reset()">

Same result. The server renders the HTML fragment. htmx swaps it in. No state management, no loading spinners, no JSON parsing, no TypeScript types for the response shape.

But what about...

🔎 "Interactivity! You can't do interactive UIs without React"

This tutorial app has: a counter that persists across sessions, a CRUD notes app with inline create/delete, an AI chat with streaming tokens and tool call cards, cross-tab WebSocket sync with green highlight animations, and an event log terminal. Total custom JavaScript: ~100 lines. Zero React.

htmx handles form submissions, list updates, and navigation. The ~100 lines of vanilla JS handle SSE streaming (for the AI chat) and WebSocket (for cross-tab sync) — things that are genuinely beyond request/response.

🔎 "Performance! React is faster because virtual DOM"

The virtual DOM exists to make React fast, not to make your app fast. It's overhead that wouldn't exist if you weren't using React in the first place. Server-rendered HTML arrives ready to display — no JavaScript parse, no hydration, no re-render.

ZealPHP on 4 workers: 117,000 req/s, 3ms p90 latency. The browser gets HTML it can render instantly. There's nothing faster than "the server already did the work."

🔎 "Ecosystem! npm has a package for everything"

And PHP has 25 years of battle-tested libraries on Packagist. PDO for databases, password_hash for security, OpenSwoole for async. The ecosystem argument is a wash — both are massive. The difference is that PHP's ecosystem doesn't require a bundler to use.

🔎 "Developer experience! Hot reload, TypeScript, DevTools"

ZealPHP: save the file, refresh the browser. No compile step, no waiting for webpack, no HMR socket disconnections. PHP errors show on the page with file + line number. Chrome DevTools shows the HTML the server sent — what you see is what you debug.

TypeScript catches bugs at compile time. PHP 8.3's type system catches them at runtime, and PHPStan catches them statically. Different tradeoff, same goal.

When to reach for React

Use React (or Vue, Svelte, etc.) when:

  • The UI has complex shared state — changing one thing updates many parts
  • The app is offline-first — the client needs to work without the server
  • You're building a design tool, game, or editor — the browser is the runtime
  • The team already has React expertise and the project benefits from it

Use server-rendered PHP + htmx when:

  • The UI is forms, tables, lists, and pages
  • The server has the data and the client displays it
  • You want zero build step and instant deploys
  • You need SEO without SSR/SSG complexity
  • You want one process instead of six

You're building an internal admin panel with user management, a settings page, and a dashboard with charts. Which approach fits best?

What this tutorial proves

You're reading a tutorial that is also a working app. It has auth, a database, CRUD, AI streaming, WebSocket sync, interactive quizzes, zoomable diagrams, and an event log. The entire client-side JavaScript is ~100 lines. No React. No bundler. No node_modules.

The next lesson shows you htmx — the 14 KB library that makes this possible.

Key Takeaways

  • React solves client-side state management — most web apps don't have that problem
  • Server-rendered HTML + htmx replaces React for forms, tables, lists, and pages
  • The hidden cost of React: bundler, hydration, state management, API layer, client-side routing
  • ZealPHP + htmx: one process, zero build step, 14 KB of JS, server is the single source of truth