P
Recherches récentes

Our web stack, end to end

35 vues

A stack, not a pile

A stack isn't a list of trendy tools glued together. It's a set of choices that have to hold together — sharing a philosophy, complementing each other without stepping on each other.

We've covered the bricks one by one in this journal: HTMX, CodeIgniter 4, performance, the builder. Here's the big picture — how it all fits together, and why this assembly forms a coherent whole.

The guiding thread fits in one sentence: the server stays in charge, the client stays light.

The principle: the server stays the source of truth

At the center, an architectural conviction: the server is the source of truth. It returns HTML — not JSON that a front end would have to turn back into an interface. The browser displays, fires requests, and gets ready-made HTML fragments back.

recherche.html
<input type="search" name="q"
       hx-get="/recherche"
       hx-trigger="input changed delay:300ms"
       hx-target="#resultats">
<div id="resultats"></div>
SearchController.php
public function results()
{
    $q     = $this->request->getGet('q');
    $posts = $this->postModel->search($q);

    // We return a Blade FRAGMENT, not a whole page
    return view('partials/results', ['posts' => $posts]);
}

This loop — an HTMX attribute fires a request, the controller returns a Blade fragment, HTMX inserts it — is the beating heart of the whole stack. No duplicated logic between back and front, no client state to sync.

Everything else follows from this principle: each tool is chosen because it serves that loop, lightly.

The foundation: CodeIgniter 4 + MariaDB

The foundation is CodeIgniter 4 on PHP 8.2+: light, explicit, mastered end to end (we devoted a whole article to it). It handles routing, models, migrations, and authentication via Shield.

On the data side, MariaDB — a proven, reliable relational DBMS, perfectly at home on classic OVH/Plesk hosting. Nothing exotic: solid.

This foundation doesn't try to impress. It tries to last.

Rendering: BladeOne

HTML rendering goes through BladeOne, a standalone implementation of the Blade engine. We write readable templates, split into partials — and those partials are exactly the fragments HTMX comes to fetch.

It's a detail that matters: the same partial serves both the page's initial render and partial updates. A single source for the same piece of interface.

The builder, for its part, generates Blade files on disk (another topic we dug into). Everything converges toward Blade.

Interactivity: HTMX v2

For interactivity, HTMX v2: ~10 KB, zero dependencies, turning any element into a request trigger that swaps only a fragment. It's what gives the "app" feel without the weight or complexity of an SPA.

Live search, pagination, inline editing, refreshed dashboards, modals: most of the interactivity of a content site or a back-office fits in there.

And since it's declarative HTML, it reads right in the markup and debugs at a glance.

Micro-interactivity: Alpine.js

Not everything needs a server round-trip. A dropdown opening, a tab switching, a toggle: that's purely local. For that, Alpine.js — a touch of reactivity right in the HTML.

dropdown.html
<div x-data="{ open: false }">
  <button @click="open = !open">Menu</button>
  <ul x-show="open" @click.outside="open = false">
    <li>…</li>
  </ul>
</div>

HTMX and Alpine split the work cleanly: HTMX for anything touching the server (the data), Alpine for what stays in the browser (the display state). Neither treads on the other's turf.

Two small declarative libraries rather than one big imperative framework: the same logic of restraint, applied to the front end.

Styling: Tailwind CSS

Styling is Tailwind CSS: utility-first, you compose the look directly in the markup, with no round-trips to scattered CSS files. Purge keeps only the classes actually used — the final sheet is tiny.

It also carries our art direction: sharp borders (border-2), hard shadows (.hard), flat colors — the brutalism we praised elsewhere. Consistent tokens, reused everywhere.

Two separate configs (front and admin), two visual worlds, a single tool.

The build: Vite

For front-end tooling, Vite: instant startup, HMR (hot reload), optimized build. In dev, we run two Vite servers (front and admin) behind a proxy.

The concrete benefit: you code, you see the result immediately, with no sluggish bundler to wait on. In production, we serve compressed, versioned assets.

Vite even reads our environment variables (the active theme, for instance) to adapt the build — the configuration follows the content.

Performance: a reflex, not an add-on

Performance isn't an option you bolt on at the end. Redis caches what's expensive but stable (configs, menus, aggregates), serves sessions and job queues. AVIF slashes image weight, lazy-load only loads what's visible.

We detailed these recipes in a dedicated article. The idea: pay the cost once (at upload, at build, at save) and serve fast afterward.

On modest hosting, this discipline makes the difference between a snappy page and one that drags.

Why this assembly holds together

What makes this stack coherent isn't the list of tools — it's their shared philosophy. All are light, explicit, server-oriented. None imposes a cathedral of abstractions. You can read the whole chain, from an HTMX attribute down to a SQL query.

LayerTechRole
LanguagePHP 8.2+the runtime foundation
FrameworkCodeIgniter 4routing, models, security (Shield)
DatabaseMariaDBrelational persistence
Cache / queuesRediscache, sessions, queue
TemplatesBladeOneserver HTML rendering + fragments
HypermediaHTMX v2interactive fragments, no SPA
Micro-interactivityAlpine.jslight local state
StyleTailwind CSSutility-first + art direction
BuildVitebundling, HMR, versioned assets
MediaImageProcessor (WebP/AVIF)image optimization
HostingOVH / Pleskproduction

Compare with a classic SPA stack (a JS-framework front + API + state management + complex build): two applications to maintain, twice the business logic, a state to sync between the two. Here, a single application, a single source of truth. Fewer moving parts, fewer breakdowns.

It's not the right choice for everything — a very stateful client app still justifies a JS framework. But for the vast majority of sites and back-offices we build, it's the ideal balance.

Understanding the whole chain

A coherent stack is one you understand in full, maintain without crises, and grow brick by brick. It's less spectacular than a flashy SPA demo — but it lasts for years, and that's exactly what we sell our clients: durability.

The best stack isn't the most impressive one: it's the one you understand end to end.

Partager