A Progressive Complexity Manifesto

A manifesto for progressive web complexity. Reject the false binary between static sites and SPAs. Embrace the powerful middle ground with server-rendered HTML, HTMX, and intentional complexity escalation.


A Progressive Complexity Manifesto

We declare the end of the false binary. For too long, we’ve been forced to choose between static sites that can’t interact and SPAs that can’t ship fast. We reject this constraint. There is a vast, powerful middle ground that the industry has abandoned, and we’re taking it back.

GitHub Repository: Clone and run the demo locallyTechnical Guide: See the implementation

The Great Deception: Static vs. SPA

The industry sold us a lie. They said our choices were:

  1. Static HTML: “Dead” pages with no interaction
  2. Full SPA: “Modern” apps with endless complexity

This is a false binary that limits our options.

Between these extremes lies a vast continent of possibility that’s been overlooked. Interactive, dynamic, server-rendered applications that ship fast, perform well, and stay maintainable. This isn’t the distant past; this is the future we can build today.

We’re not going backwards. We’re going beyond. We also acknowledge that some products need a frontend framework from day one (real‑time collaboration, complex client graphs, offline‑first, heavy mobile code‑sharing). The point isn’t rejection; it’s choosing the right level of complexity for the job.

The Evidence: Real Numbers

Check out the demo app. It’s an interactive application: editable table cells, pagination, search, dynamic totals, optimistic updates, error handling. The complete user experience you’d find on any modern web platform.

Clone and run locally: git clone https://github.com/lorenseanstewart/progressive-complexity && cd progressive-complexity && npm install && npm run dev. Click any price or quantity to edit. To see optimistic updates, throttle your browser to “Slow 4G” in DevTools. You’ll see the pink text appear (optimistic update) and then revert to the original text color (server response). Change any price to 99.99 to trigger an error and see the graceful error handling.

The Result:

  • 70.4 kB total JavaScript (23.4 kB app + 47 kB HTMX)
  • 23.3 kB gzipped (smaller than most framework starter templates)
  • 418 lines of front-end TypeScript (268 vanilla JS utilities + 150 Web Components)
  • Standard build process (no complex bundling or framework tooling)
  • Navigation and pagination work without JavaScript; search and inline editing require JS/HTMX

Compare that to typical React applications that often ship 200-500 kB of JavaScript, before you write any business logic.

The Revolution: Five Levels of Intentional Complexity

We reject the binary. We embrace the spectrum. We climb only when we must:

Level 1: Static HTML           ⟶ The foundation
    ↓ (add server interaction)
Level 2: HTML + HTMX          ⟶ The sweet spot
    ↓ (add client-side polish)
Level 3: HTMX + Vanilla JS    ⟶ The enhancement
    ↓ (add complex components)
Level 4: HTMX + Web Components ⟶ The escalation
    ↓ (ecosystem required)
Level 5: Full Framework       ⟶ The summit

This is the revolution: Each level exists for a reason. Each level solves problems the previous cannot. But unlike the binary choice, you can live comfortably at any level. Most applications find their home at Level 2 or 3 and never need to leave.

The industry pushes Level 5 as the default. We reclaim Level 2 as the starting point.

Principles of Precision

Hard truths, gently told:

  • Complexity often masquerades as sophistication; simplicity requires confidence.
  • True mastery lies not in conquering all tools, but in wielding the fewest with precision.
  • Over-engineering is unclear thinking wearing a clever disguise.
  • We often choose the comfort of importing solutions over the discomfort of understanding problems.
  • Start where you are, not where you imagine you’ll be.
  • Each abstraction should simplify something; when it doesn’t, we’ve abstracted too soon.
  • The server that renders HTML has solved more problems than the framework that promises to.
  • The most dangerous moment comes with the first success of a complex solution, for it justifies all future complexity.

When to Start Where

Start at Level 2 (HTMX) if you’re building:

Consumer Products:

  • E-commerce sites (product catalogs, checkout, reviews)
  • Social media feeds (Reddit, Twitter-style timelines)
  • News and media sites (articles, comments, subscriptions)
  • Job boards and marketplaces (search, filtering, applications)
  • Travel and booking sites (listings, reservations)
  • Educational platforms (course catalogs, learning modules)
  • Forums and community sites (discussions, voting)
  • Review platforms (Yelp-style ratings and search)

Business Applications:

  • Admin panels and dashboards
  • Content management systems
  • SaaS functionality and workflows

Why HTMX first? It extends HTML’s capabilities without JavaScript complexity. Need a live search? Add hx-get and hx-trigger attributes. Need form validation? hx-post with error handling. It feels like HTML, not a framework.

Start at Level 5 (Framework) if you need:

  • Real-time collaboration (Google Docs, Figma)
  • Complex client-side state graphs (trading platforms)
  • Offline-first functionality
  • Heavy code sharing with mobile apps

We’re not anti-framework fundamentalists. Some problems genuinely need React/Vue/Svelte from day one. But most don’t. The revolution isn’t about rejecting tools; it’s about rejecting today’s defaults.

Addressing the Concerns

“But everyone knows React!”
Everyone knows HTML better, or can learn it better in a day. HTMX can be learned in an afternoon. Your backend developers can contribute immediately. Your junior developers learn web fundamentals instead of framework abstractions.

“What about component reuse?”
Server-side templates work great. NestJS with ETA, Astro, Go with Templ, Rails partials, Laravel Blade, Django templates: all proven at scale. You can still extract reusable server components (e.g., ETA partials, Templ components, Astro components) without client-side complexity.

“What about SEO and performance?”
Server-rendered HTML is faster and more SEO-friendly than SPAs. You get meaningful content on first paint, not loading spinners.

“What if we need to scale up?”
That’s the beauty of Progressive Complexity. With tools like Astro Islands, you can add React components exactly where needed while keeping the rest simple. It’s not a cliff; it’s a ramp.

“What about developer experience?”
Better than ever. TypeScript throughout. Hot reloading. Modern tooling. The difference? You’re not wrestling with framework complexity. You’re building. Pure, joyful building.

Framework Developer’s Guide: Your Skills, Revolutionized

For React Developers

Your expertise translates directly - we’re not asking you to abandon your knowledge, we’re showing you how to wield it more precisely:

Component Composition → Server Templates

// React Component
function ProductList({ products, filters }) {
  return (
    <div>
      {products.map(product => (
        <ProductCard
          key={product.id}
          product={product}
          onEdit={handleEdit}
        />
      ))}
    </div>
  );
}

// Progressive Complexity (Server Template)
<!-- ProductList.astro -->
<div>
  {products.map(product => (
    <ProductCard product={product} />
  ))}
</div>

Same component thinking, rendered on the server with full data available.

State Management → URL Parameters + Server State

// React: Complex state synchronization
const [filters, setFilters] = useState({});
const [sort, setSort] = useState("name");
const [page, setPage] = useState(1);

// Progressive Complexity: Bookmarkable by default
// URL: /?page=2&sort=price&filter=electronics
// Server reads URL, returns filtered HTML

Your state is now shareable, bookmarkable, and SEO-friendly by default.

useEffect → Not Needed

// React: Effect synchronization complexity
useEffect(() => {
  fetchProducts().then(setProducts);
}, [filters, sort, page]);

// Progressive Complexity: Server renders complete state
// No effects, no race conditions, no cleanup

Context/Redux → Server Session

// React: Prop drilling or complex context setup
<ThemeContext.Provider value={theme}>
  <UserContext.Provider value={user}>
    <App />
  </UserContext.Provider>
</ThemeContext.Provider>

// Progressive Complexity: Server handles it
// Session data available to all components during render
// Type-safe with TypeScript from server to template

What You Gain, Not What You Lose

Immediate Benefits: HTML is already interactive, so no hydration mismatches. You ship 10% of the JavaScript with no bundle size anxiety. The server is your single source of truth, eliminating state synchronization bugs. You write less code and ship faster, while your backend team can contribute immediately. You get real first contentful paint, not loading spinners.

Your Advanced Skills Still Matter: TypeScript provides full type safety from database to DOM. Server components are still components with the same architectural thinking. Your testing skills apply directly, and you’re still optimizing performance: just what actually matters. Most importantly, choosing the right complexity level is system design at its finest.

Migration Strategy for Your Team

Week 1: Proof of Concept : Pick one simple feature like search, filters, or a form. Implement it with HTMX alongside your React app and measure lines of code, bundle impact, and development time.

Week 2-3: Expand : Convert 2-3 CRUD interfaces, train 1-2 backend developers to contribute, and document patterns that work for your team.

Week 4: Evaluate and Plan : Compare metrics across performance, developer velocity, and code complexity. Identify features that should stay in React (Level 5) and plan progressive migration for Level 2-3 features.

Common Concerns from Framework Teams

“But we need type safety!” Progressive Complexity provides end-to-end type safety with TypeScript (or Golang with Templ, etc.). We have clean domain types for Product and API responses in /src/types. Types flow from database to server functions to templates to client utilities, with global type definitions for HTMX integration. Simple, effective type safety without the complexity overhead.

“What about our component library?” Level 4 (Web Components) integrates with any framework. Use Lit or vanilla Web Components. Your React components can even stay for complex features.

“How do we test this?” Unit tests work great for server functions with Jest/Vitest. Integration tests can verify HTML responses with Supertest. E2E tests with Playwright/Cypress work perfectly with HTMX. It’s actually simpler than testing SPAs since there’s no need to mock complex client state.

“What about developer experience?” Astro provides instant hot reload updates. TypeScript has full support with type inference. Debugging is simpler without virtual DOM or complex state trees to navigate. Code splitting is handled automatically by the server.

The Revolutionary Truth for Framework Experts

You’ve mastered complex tools. That mastery isn’t wasted; it’s evolved. Now you can choose complexity intentionally rather than by default, ship faster when the problem doesn’t require a framework, scale thoughtfully by adding complexity only where needed, and lead the revolution by showing others the power of the middle ground.

Your framework skills are your Level 5 superpower. But most problems are Level 2-3.

The Pragmatic Path Forward

For Your Next Project

Start at Level 2: Build it server-rendered with HTMX interactions
Stay at Level 2 until you hit a wall that HTMX can’t solve
Escalate to Level 3 (add some TS/JS) only when you need client-side polish HTMX can’t provide
Climb to Level 4 (bring in the web components) only when you need complex, stateful components
Reach Level 5 (it’s time for a framework) only when the ecosystem’s power becomes indispensable

Many projects never leave Level 2. Some need Level 3 polish. Few require Level 4 complexity. Fewer still justify Level 5 overhead.

For Existing Teams

React developers: Clone this repository and try HTMX for your next feature. That search interface, comment system, or checkout flow? You’ll be surprised how little JavaScript you need.

Backend developers: You already know HTML rendering. HTMX just makes it interactive. Run npm run dev and see how familiar it feels.

Tech leads: Your next project doesn’t need React if HTMX gets you there faster. Save your complexity budget for your actual differentiator.

Real-World Adoption

This isn’t theoretical. Companies are shipping consumer products:

  • GitHub uses server-rendered HTML + progressive enhancement for most of their UI (issues, pull requests, code browsing)
  • Basecamp built HEY email client primarily server-side (consumer email service)
  • Stack Overflow serves millions with server-rendered pages + progressive enhancement
  • Reddit (old.reddit.com) outperforms many modern SPAs with server-side rendering
  • Laravel Livewire and Phoenix LiveView power consumer-facing applications at scale
  • HTMX has 45k+ GitHub stars (as of Aug 10, 2025) with adoption across consumer and business products

The Technology Stack

Progressive Complexity works with any backend with a templating package:

  • Python: Django/FastAPI + HTMX
  • Ruby: Rails + Hotwire
  • PHP: Laravel + Livewire
  • TypeScript/JavaScript: Astro + HTMX (our demo)
  • Go: Templ + HTMX
  • C#/.NET: Razor + HTMX

Choose your backend, add HTMX, start building.

Implementation Patterns That Work

Smart HTMX Usage

<!-- Form submission: Update just the content that changed -->
<form
  hx-post="/products"
  hx-target="#product-list"
>
  <input
    name="name"
    placeholder="Product name"
  />
  <button type="submit">Add Product</button>
</form>

<!-- Navigation: Preserve URL for bookmarking -->
<button
  hx-get="/products?page=2"
  hx-target="#product-list"
  hx-push-url="true"
>
  Next Page
</button>

<!-- Field editing: Optimistic updates with server authority -->
<input
  hx-patch="/products/1/price"
  hx-target="#product-list"
  hx-on:htmx:beforeRequest="showOptimistic(this)"
/>

Server-Side State Authority

Let the server calculate totals, handle validation, manage state. The client shows immediate feedback, but the server has the final say. This prevents the data synchronization bugs that plague SPAs.

Graceful Enhancement

Navigation and pagination work without JavaScript; HTMX enhances search and inline editing when JS is available.

The Revolutionary Act: Choosing Your Level

This is not compromise; this is precision. We don’t accept less. We demand exactness. The right tool for the actual problem, not the problem we assume we’ll have someday.

The revolutionary act: Start at Level 2. Build your e-commerce site, your social platform, your news site, your marketplace with HTMX. Feel the speed, the simplicity, the joy of development that fits the problem. When you truly need more, climb. But climb with intention, not habit.

We call upon developers: Reject the false binary. Reclaim the middle ground. Show the industry that interactive web applications don’t require megabytes of framework overhead. Prove that server-rendered HTML can be as dynamic and engaging as any SPA.

We call upon teams: Question the default. When someone suggests React for a product page, ask why. When someone dismisses server-rendering as “old-fashioned,” show them this repository. When someone claims you need a framework for “real” consumer applications, prove them wrong.

We call upon the industry: Stop selling complexity as sophistication. Stop pushing Level 5 solutions for Level 2 problems. Stop teaching developers to reach for frameworks before understanding fundamentals. The web is powerful enough without your abstractions.

The Manifesto in Action

GitHub Repository: Clone, explore, and run the demo
Technical Deep Dive: Study the implementation
Bundle Size: 70.4 kB total of uncompressed JavaScript for a complete interactive application

This isn’t theory. This isn’t nostalgia. This is modern web development, liberated from artificial constraints.

Join the revolution. Reclaim the middle ground. Show the world what’s possible when we choose appropriately instead of conventionally.

The web remembers what it was built for: documents that can interact, servers that can render, HTML that can live. We’re bringing that power back.

Start simple. Scale intentionally. Revolution through restraint.