L3 — + App (plugin lifecycle)
L2 + @nwire/app for the plugin lifecycle: provide / on / boot / shutdown. This is the layer where the framework starts being a framework.
What you add
bash
pnpm add @nwire/appThe shape
ts
import { httpInterface, endpoint } from "@nwire/http"
import { createApp, definePlugin } from "@nwire/app"
import { token } from "@nwire/container"
import { z } from "zod"
const Db = token<{ query(sql: string): Promise<unknown[]>; close(): Promise<void> }>("Db")
const dbPlugin = definePlugin("db", ({ provide, on, boot, shutdown }) => {
let connection: { query: typeof Db.T["query"]; close: () => Promise<void> }
provide(Db, () => connection)
boot(async () => {
connection = await openDb()
})
shutdown(async () => {
await connection.close()
})
on("AppBooted", () => console.log("db ready"))
})
const app = await createApp({ plugins: [dbPlugin] })
const api = httpInterface({ container: app.container })
api.get("/users", ({ resolve }) => resolve(Db).query("select * from users"))
await endpoint("api", { port: 3000 }).serve(api).run({ app })What's new vs L2
definePlugin(name, closure)packages bindings + lifecycle hooks together.boot(fn)runs once at startup. Plugins boot in dependency order.shutdown(fn)runs once at shutdown — in reverse boot order, so resources unwind in the correct sequence.on("AppBooted", fn)subscribes to framework events. See the full list in framework events.provide(Token, factory)registers a binding without the imperativecontainer.provideXcalls.
When to stay at L3
- Your domain is shaped like REST + a database.
- You don't need state machines, event sourcing, projections, or workflows.
- You're happy hand-rolling cross-cutting concerns (audit log, multi-tenancy, retries).
When to climb to L4
When the domain has rich state (a submission goes through submitted → graded → reviewed), or when you want one event to fan out to multiple consumers, or when you want a step to run two days after another step, climb to L4 and pull in @nwire/forge.
Next
- L4 — + Forge — actors, events, projections, workflows
- Reference: @nwire/hooks alone — the dispatch primitive behind framework events