Skip to content
Chris Michael edited this page Jul 25, 2026 · 10 revisions

Effuse

Effuse

Effuse is a TypeScript application framework built around fine-grained reactivity, define({ script, template }) components, and typed capability layers that own browser services and server endpoints in one vocabulary.

Project status: Experimental. The repository has production-oriented tests, diagnostics, SSR infrastructure, and CI gates, but it does not yet claim a stable production release contract.

This wiki is the source of truth for the implementation on the dev branch. When code comments, README files, or older documentation disagree with this wiki, follow the exported APIs and tests. Implemented, experimental, and planned behavior are marked separately throughout.

Start Here

Page Purpose
Why Effuse Framework thesis, audience, and non-goals.
Getting Started Minimal application, routing, layers, and commands.
Reference Index Public concepts and implementation status.
Runnable Examples Small examples aligned with current APIs.
Production Readiness Current guarantees and explicit release boundaries.
Server Request Schemas Framework-owned request validation without Effect in application code.
Performance Lab Reproducible benchmarks, budgets, and claim boundaries.
Dev App Probe Contract Stable browser targets for ecosystem verification.
DX Gaps And Roadmap Open architecture and documentation work.

One Capability, One Vocabulary

A layer owns a capability. The same declaration provides the browser service, the server endpoint, and the typed client, so a capability is named once instead of re-described per surface.

const UserLayer = defineLayer({
  name: 'users',
  services: {
    users: () => ({ find: (id: string) => db.users.find(id) }),
  },
  server: {
    api: {
      '/api/users/[id]': {
        GET: ({ params, services }) => services.users.find(params.id),
      },
    },
  },
});

A component declares a typed alias into that graph rather than reaching for a service by string:

const UserCard = define({
  layers: { users: UserLayer } as const,
  script: ({ layers, props }) => ({
    user: layers.users.service('users').find(props.id),
  }),
  template: ({ user }) => <article>{user.name}</article>,
});

The composition root calls app.useLayers(...) once. A missing registration fails with LayerBindingNotRegisteredError before user setup runs, and a local declaration never mutates a running layer graph.

What Works Today

Rendering and reactivity. Fine-grained signals, computed values, watchers, and reactive props. Components support lifecycle, context, refs, events, Suspense, and error boundaries. JSX event handlers carry the concrete element as event.currentTarget.

Routing. Nested routes, aliases, guards, grouped paths, colon and bracket params, and required or optional catch-alls, on both client and server.

Server APIs. Layer-owned routes and actions, typed file handlers, compiled registries, native serverSchema request contracts that decode without exposing Effect, manifests, and typed manifest clients.

Server middleware. Complete end to end: filesystem discovery, a compiled scope graph (enginegloballayerroute), onion dispatch with single-use next(), bounded rewrites that cannot bypass a destination's guards, abort propagation with exactly-once cleanup, tracing, and a reserved internal-path policy.

SSR and streaming. Hydration data, head management, and deferred-head streaming, where the shell flushes before the body renders so time-to-first-chunk does not grow with document size.

Caching. An origin response cache and a typed cached() data cache. Both are opt-in, both use single-flight coalescing so an expiring hot key cannot stampede the origin, and both invalidate through tags.

Performance. Server route matching is indexed in a radix trie, so lookup cost is independent of route count. Route and render hot paths have reproducible median and p95 budgets enforced in CI.

Background work. createTaskScheduler runs recurring tasks with overlap prevention, error isolation, and graceful-shutdown integration.

Tooling. The CLI builds and serves projects, generates client and server entry files, and regenerates server and middleware registries on change.

Open Work

Area Issue
Unified route manifest across client, server, metadata, and layouts #218
Portable server engine: remaining phases and release gate #279
Performance lab: hydration, memory, bundle, and competitor fixtures #249
Client bundle size #338
Public documentation migration to alias layers #176

A stable production claim additionally requires a versioned documentation set, a supported adapter matrix, and a compatibility and release policy. See Production Readiness for the current evidence and the explicit boundaries.

Repository

Clone this wiki locally