Declarative by default
Describe routes alongside the code that owns them. Metadata stays inspectable through a small public API.
See a controllerSERVER ARCHITECTURE FOR THE ANGULAR ERA
Strata turns controllers and routes into clear, declarative layers—without taking ownership of the H3 runtime you already trust.
A thinner layer, a clearer boundary.
Built for the stack you already use
INTENT, NOT INDIRECTION
Strata is deliberately narrow: a common language for your server, while the runtime, routing model and escape hatches remain familiar.
Describe routes alongside the code that owns them. Metadata stays inspectable through a small public API.
See a controllerNo replacement server, no hidden transport. Register directly on H3—or on Nitro's router in Analog.
Explore the boundary Server controllers live under src/server, keeping implementation details outside the client graph.
THE WHOLE IDEA IN ONE FILE
import { Controller, Get } from "@strata/core";
@Controller("/users")
export class UsersController {
@Get()
findAll() {
return [{ id: "1", name: "Ada" }];
}
}ANALOG, WITHOUT A DETOUR
The Analog adapter registers controllers where Nitro expects them: in a server plugin, on the router it already owns.
import { registerControllers } from "@strata/analog";
import { defineNitroPlugin } from "nitropack/runtime";
import { UsersController } from "../strata/users.controller";
export default defineNitroPlugin((nitroApp) => {
registerControllers(nitroApp.router, [UsersController]);
});CLEAR LAYERS, CLEAR OWNERSHIP
It reads controller metadata and registers routes on the instance you pass in. Native routes keep working. Your framework continues to own the lifecycle.
EARLY, OPEN, AND DELIBERATE
Strata is experimental today. The design work is public, the boundaries are explicit, and contributions are welcome.
View on GitHub