-
-
Notifications
You must be signed in to change notification settings - Fork 0
Home
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.
| 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. |
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.
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 (engine → global → layer → route), 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.
| 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.
- Source
- Issues
- Pull requests
- License: MIT