The front end framework for correctness: built on Effect, architected like Elm

plucafs1 pts0 comments

Foldkit - TypeScript Frontend Framework Built on Effect-TS | Elm Architecture

Skip to main contentBeta<br>The frontend framework for correctness.<br>Built on Effect. Architected like Elm. Written in TypeScript.<br>npx create-foldkit-app@latest

Dive InLaunch Playground<br>View on GitHub674

Declare behavior. Ship. Repeat.<br>React, Vue, Svelte, and Solid solve rendering and leave the architecture to you. Foldkit gives you the architecture, so you can focus on your domain.

Predictable state<br>One immutable model holds your entire application state. Every change flows through a single update function. No hidden mutations, no stale closures, no surprises.

Explicit effects<br>Side effects are values you return from update, not imperative calls buried in handlers. Commands describe what should happen. The runtime handles when and how.

Scales with grace<br>Complexity grows linearly, not exponentially. A 50-file app follows the same patterns as a 5-file app, so each feature adds structure instead of entangling with what is already there. New team members read the code and understand it.

" class="inline-block -translate-x-1/4 text-accent-200/18 dark:text-accent-400/4 font-mono text-[18rem] md:text-[27rem] font-extrabold leading-none -z-10 relative whitespace-nowrap">

Built on Effect. Inside and out.<br>If you already know Effect, Foldkit feels natural. If you’re new to Effect, Foldkit is a great way to learn it.

Every Foldkit application is an Effect

All state is a single Schema

Side effects are modeled as Effects that never fail

" class="inline-block -translate-x-1/4 text-accent-200/18 dark:text-accent-400/4 font-mono text-[18rem] md:text-[27rem] font-extrabold leading-none -z-10 relative whitespace-nowrap -translate-y-1/4">

See it work.<br>Watch a message flow through update into the model. The code highlights in real time to show you what’s happening at each step.<br>Async CounterNote Player<br>On a larger screen, you can see the relevant code highlight in real time as your action runs.<br>// MODEL

const Model = S.Struct({<br>count: S.Number,<br>isResetting: S.Boolean,<br>resetDuration: S.Number,<br>})

// MESSAGE

const ClickedIncrement = m('ClickedIncrement')<br>const ChangedResetDuration = m('ChangedResetDuration', {<br>seconds: S.Number,<br>})<br>const ClickedResetAfterDelay = m('ClickedResetAfterDelay')<br>const CompletedDelayReset = m('CompletedDelayReset')

// COMMAND

const DelayReset = Command.define(<br>'DelayReset',<br>{ seconds: S.Number },<br>CompletedDelayReset,<br>)(({ seconds }) =><br>Effect.sleep(`${seconds} seconds`).pipe(<br>Effect.as(CompletedDelayReset()),<br>),

// UPDATE

M.tagsExhaustive({<br>ClickedIncrement: () => [<br>evo(model, { count: count => count + 1 }),<br>[],<br>],<br>ChangedResetDuration: ({ seconds }) => [<br>evo(model, { resetDuration: () => seconds }),<br>[],<br>],<br>ClickedResetAfterDelay: () => [<br>evo(model, { isResetting: () => true }),<br>[DelayReset({ seconds: model.resetDuration })],<br>],<br>CompletedDelayReset: () => [<br>evo(model, { count: () => 0, isResetting: () => false }),<br>[],<br>],<br>})

Add 1Reset Delay (seconds)−+

Reset after 2 seconds<br>Model State<br>count: 0<br>isResetting: false<br>resetDuration: 2

Phase

Idle

Message Log

Batteries included.<br>Most frameworks ask you to bring your own routing library, state manager, UI kit, and form validator. Foldkit ships them as one coherent system.

Routing<br>Type-safe bidirectional routing. URLs parse into typed routes and routes build back into URLs. No string matching, no mismatches between parsing and building.<br>Explore routing

UI Components<br>Accessible components (dialog, menu, tabs, listbox, disclosure, and more) built for The Elm Architecture. Easy to style and customize.<br>Browse the components

Submodels<br>A self-contained Model, Messages, update, and view, embedded inside a larger program. Children surface domain facts as typed OutMessages and parents handle them in update. Every stateful Foldkit UI component ships as a Submodel.<br>Explore Submodels

Subscriptions<br>Bind a slice of the Model to a scoped Stream that may emit Messages. The runtime opens the scope while the slice holds its value and closes it when the slice changes.<br>Explore Subscriptions

Managed Resources<br>Model-driven lifecycles for long-lived browser resources like WebSockets, AudioContext, and RTCPeerConnection. The runtime acquires when the Model calls for the resource and releases when it no longer does.<br>Explore Managed Resources

Field Validation<br>Per-field validation with sync and async support. Define rules as predicates, apply them in update, and the Model tracks every field state.<br>Explore field validation

Testing<br>Two test primitives. Story sends Messages through update and asserts on the resulting Model and Commands. Scene drives the rendered view through accessible locators and asserts on the re-rendered HTML.<br>Explore testing

DevTools<br>Inspect Messages, Model state, and Commands as your app runs. Time-travel mode rewinds your UI to any past Model. AI agents can connect to the same data over MCP.<br>Explore DevTools

Embedding<br>Run a Foldkit widget inside any host...

model seconds effect foldkit update text

Related Articles