UCE Docs
PHP energy, C++ runtime

Make dynamic websites like it's 2006.

UCE is a direct web runtime: files are pages, templates live next to control flow, nginx fronts the whole thing, and a request can compile into a wasm module on first hit. It is built in the image of PHP's non-architecture, but with an explicit request object, component rendering, and a built-in WebSocket broker.

Files are routes A .uce page is the thing you edit and the thing nginx serves.
Compile on demand First request builds a wasm module, later requests reuse it.
WebSockets included Same runtime, same page path, broker-managed connection state.
Why UCE

The old web had the right instincts.

Put code where the page lives. Let runtime state die with the request. Keep deployment boring. Treat server-rendered HTML as the default, and add richer behavior only where it pays for itself.

templating

Inline markup without framework tax

UCE templates live directly inside handler code with escaped and raw output modes, so rendering stays local to the request logic that owns it.

composition

Components and sub-rendering

Components are just .uce files. Props flow through context.props. Full pages can call other units without inventing a second application runtime.

transport

FastCGI for pages, HTTP for sockets

Normal page renders stay on the FastCGI socket. WebSocket upgrades for .uce endpoints are proxied to the built-in HTTP listener.

operations

nginx in front, systemd behind

Static files stay static, nginx does the edge work, and the runtime handles compilation, request execution, and socket fan-out.

Non-architecture

It is not trying to save you from the web.

What it leans into

Files on disk, explicit request handlers, template tags, reusable partials, request-scoped state, and operationally plain deployment.

What it resists

Mandatory client-side hydration, giant application shells, hidden routing layers, and pretending every website is a desktop app in a trench coat.

What it adds

Built-in components, markdown rendering, current request data in one place, and a broker-backed WebSocket story that stays inside the same runtime.

Code first

Common things in UCE

The examples below are modeled on the current runtime API and the published demo pages. The point is not abstraction depth. The point is that the code stays obvious.

templating

A page with request data

Drop from C++ into markup, escape output by default, and keep request handling next to the HTML it controls.

uce
RENDER(Request& context)
{
	String name = first(context.get["name"].to_string(), "guest");
	<>
		<h1>Hello, <?= name ?>.</h1>
		<p>Rendered at <?= time_format_utc("%F %T") ?></p>
	</>
}
See the live demos for forms, headers, sessions, JSON, markdown, and more.
forms

POST + session flash

Old-school dynamic websites still matter. UCE keeps form handling and page rendering in one file when that is the simplest thing.

uce
RENDER(Request& context)
{
	if(context.post.has("email"))
		context.session["flash"] = "Saved " + context.post["email"].to_string();
	<>
		<form method="post">
			<input name="email" placeholder="you@example.com"></input>
			<button>Save</button>
		</form>
		<? if(context.session.has("flash")) { ?>
			<p><?= context.session["flash"] ?></p>
		<? } ?>
	</>
}
Request data lives on context.get, context.post, context.cookies, and context.session.
components

Reusable UI without a second framework

Components are ordinary .uce files. Pass props through context.props and choose when to render or return markup.

uce
COMPONENT(Request& context)
{
	<>
		<article class="card">
			<h3><?= context.props["title"] ?></h3>
			<p><?= context.props["body"] ?></p>
		</article>
	</>
}

RENDER(Request& context)
{
	DValue props;
	props["title"] = "Shipping note";
	props["body"] = "Components are just .uce files with structured props.";
	<>
		<?: component("components/card", props, context) ?>
	</>
}
Named handlers and component_render() are also available for direct output flows.
content

Markdown when you want it

UCE also ships a markdown module, so content-heavy pages do not need an external rendering stack.

uce
RENDER(Request& context)
{
	String src = "# Release Notes\n\n- fast path\n- docs\n- demos";
	<>
		<section class="prose">
			<?: markdown_to_html(src) ?>
		</section>
	</>
}
The runtime supports markdown_to_ast() and markdown_to_html() for content pipelines and component hooks.
realtime

WebSockets with broker-owned state

Any .uce page can render HTML and also accept live socket messages with WS(Request& context). Connection-local state lives on context.connection.

uce
RENDER(Request& context)
{
	<>
		<script>
			const ws = new WebSocket(`ws://${window.location.host}${window.location.pathname}`);
			ws.onopen = () => ws.send(JSON.stringify({ type: "join", name: "guest" }));
		</script>
	</>
}

WS(Request& context)
{
	DValue payload = json_decode(context.in);
	String connection_id = context.params["WS_CONNECTION_ID"];
	context.connection["name"] = payload["name"];
	payload["connection_id"] = connection_id;
	ws_send(json_encode(payload));
}
Route WebSocket upgrade requests for .uce paths to the runtime HTTP listener.
deploy

nginx wiring

Use FastCGI for ordinary requests and send websocket upgrades to the runtime's built-in HTTP listener.

nginx
location ~ \.uce$ {
	error_page 418 = @uce_websocket;
	if ($http_upgrade = "websocket") { return 418; }
	include fastcgi_params;
	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	fastcgi_pass unix:/run/uce/fastcgi.sock;
}

location @uce_websocket {
	proxy_http_version 1.1;
	proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection $connection_upgrade;
	proxy_pass http://127.0.0.1:8080;
}
Route upgrade requests for .uce paths to HTTP_PORT; plain page loads stay on FastCGI.
Deployment

Put nginx in front. Keep the runtime focused.

The intended shape

  • nginx serves static files directly from `/var/www/html`
  • ordinary `.uce` page loads go through FastCGI
  • websocket upgrade traffic for `.uce` paths goes to the built-in HTTP listener
  • systemd manages the runtime binary and restart policy

The practical settings

  • `FCGI_SOCKET_PATH=/run/uce/fastcgi.sock` for normal requests
  • `HTTP_PORT=8080` for `.uce` websocket upgrades
  • `scripts/systemd/manage-uce-service.sh` for build and service control
  • published root should be `/var/www/html`, not the repo root
Explore

Go straight to the useful parts.

Reality check

What this is and what it is not

Is UCE production ready?

The runtime is still experimental. The point of this site is to explain the model, show the current surface area, and make it easy to evaluate the demos and docs.

Why compare it to PHP?

Because the design instinct is similar: dynamic pages as files, shallow deployment, and a bias toward solving the request in front of you instead of building an application architecture altar.

What makes it different from old PHP?

The request object is explicit, components and named handlers are first-class, markdown support is built in, and WebSockets use a broker-owned connection model inside the runtime.