Primate Is the Last Great Web Framework

I'm the creator of Primate, so take the title with the

appropriate grain of salt. By "great web framework", I mean something specific:

a tool that takes ownership of the whole stack. Routing, rendering, data,

validation, sessions, deployment targets, runtime support. The pieces should be

designed to fit together.

Primate

I grew up building web apps with PHP frameworks: mostly Yii, some Laravel. What

I loved about them was not PHP itself, but the feeling that the framework owned

the stack. Databases, templates, routing, validation, patterns like MVC. You

could swap pieces inside one coherent system. You could go to the framework's

website and see what was officially supported. You knew what was familiar

territory, and what was outside the map.

As JavaScript moved to the server, that idea mostly disappeared. The JavaScript

ecosystem strongly prefers composition over cohesion. You choose a server

framework, then a database client, then validation, then sessions, then a

frontend, then a build tool, then glue it all together. Each piece may be

excellent on its own, but nobody owns the seams.

A UNIX purist might say that is the right model: each tool should do one thing

well. But web applications are not just pipelines of isolated tools. They are

full of shared assumptions: request shapes, validation boundaries, session

handling, rendering, routing, serialization, deployment targets. In practice,

things often fail in subtle ways exactly where those tools meet.

Meta-frameworks improved the situation, but only by straitjacketing the world.

Next gives you a coherent stack, but it is a React stack. If you discover Solid

and want to try it, you do not simply switch the view layer. You move to a

different meta-framework with different conventions, different routing details

and different backend assumptions.

The same pattern repeats across the ecosystem: filesystem routes plus one

blessed frontend, rebuilt again and again. React gets one meta-framework. Solid

gets another. Svelte gets another. Vue gets another. Each one solves mostly the

same backend problems, but in slightly different ways you have to relearn every

time.

Runtime fragmentation made this worse. Node, Deno, and Bun are all capable

JavaScript runtimes, but some frameworks are now effectively runtime-specific.

That means your app can be tied not only to a frontend, but also to a runtime.

And when a framework says it "supports" Deno or Bun, that often just means the

runtime is compatible enough to run Node code. It does not necessarily mean the

framework was designed to use each runtime's own APIs and execution model.

There is no reason for this. Frontends are ways to describe browser UI.

Backends are ways to handle requests, data, and application logic. Runtimes are

execution targets. These things should be allowed to vary independently.

You should be able to write one route with React, another with Svelte, another

with Marko, and keep the same backend model.* You should be able to write backend

routes in TypeScript, Go, Ruby, or Python, and compose them inside one app. You

should be able to run the same app on Node, Deno, or Bun without changing a

single line of code or using runtime-specific packages to bridge the gap.

And the framework should still provide official support for validation, database

stores, sessions, i18n, routing, and rendering. That is what Primate is built

to be.

Primate is a web framework that does not belong to one frontend, one backend

language, or one runtime. It gives you one application model, then lets you

choose the pieces route by route. Use React where React makes sense. Use Svelte

where Svelte feels better. Use TypeScript for most routes, but Go, Ruby, or

Python where their ecosystems or runtime characteristics fit better. Run on

Node today, Deno tomorrow, Bun later.

Primate is not hype. It is not benchmark theater. The point is not novelty. The point is removing coupling, lock-in, and decisions other people make for you.

You can still reach outside the official stack when you need to, but when you

stay inside it, the seams are Primate's responsibility.

A web framework should own the stack without owning your choices.

A Small Example

Here is a tiny app that already shows the point: one backend model, multiple

frontends, no framework switch.

Create a project:

Configure the frontends:

Create a React route and collocated page:

Add another React route and page:

Add a Svelte route in the same app:

Run it:

Or, if you prefer Deno, use deno run -A npm:primate; for Bun, use bunx --bun primate.

This is the part that matters: the backend route model did not change. The app

did not become a React app or a Svelte app. It stayed a Primate app, and each

route chose the frontend that made sense for it.

  • There are limits to this, even in Primate. Different frontend frameworks

cannot currently share layouts, because a layout is itself rendered by one

frontend. This may become possible later with web components.