The frontend framework for correctness.
Bring Effect’s explicitness to your frontend. Foldkit gives your entire application one architecture with an idiomatic place for every behavior.
npx create-foldkit-app@latest
See it work.
Watch a message flow through update into the model. The code highlights in real time to show you what’s happening at each step.
Declare behavior. Ship. Repeat.
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
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
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.
Shared structure
A 50-file application uses the same Model, Message, update, and Command structure as a 5-file application. New work has a known place, and reviews start from shared conventions.
Built on Effect. Inside and out.
If your backend already uses Effect, Foldkit carries the same tools and patterns into the browser. If Effect is new to your team, it is part of the learning curve.
- Every Foldkit application is an Effect
- The entire Model is defined by Schema
- Commands use Effect for services, interruption, resources, and concurrency
Architectural fit.
Foldkit uses The Elm Architecture. Application state does not live in component instances or hook lifecycles. The Model is the single source of truth, and every transition stays visible in update.
That discipline is a real commitment. Foldkit works best when the team wants one architecture across the application and is ready to build on Effect throughout.
A strong fit
Effect developers who need a frontend
Your backend already uses Effect. Foldkit carries Schema, services, Streams, and scoped resources into frontend architecture.
Applications with complex state
Auth flows, real-time data, and multi-step forms become explicit states and transitions instead of effects and refs spread across the tree.
Teams that want shared conventions
One pattern for state, effects, and views gives features a known shape and reviews a common vocabulary.
Think twice when
Large existing React codebases
Foldkit isn’t an incremental adoption. It’s a different architecture, and migrating means a rewrite. The middle path is embedding: Runtime.embed runs a Foldkit widget inside an existing app.
Projects that need the React ecosystem
The application depends on React component libraries, Next.js, or middleware built for that stack. Foldkit uses different foundations.
Sites that are mostly static content
A site that is mostly prose with a sprinkle of interactivity is better served by a content-first tool like Astro. Foldkit renders on the server too, but it is built for applications.
Project status.
Foldkit is in beta and under active development. The links below show the current version and what is ready to use today.
Version
v0.148.1
Example apps
34Production app
Typing TerminalChangelog
View releases
Batteries included.
Routing, server rendering, UI components, composition, and browser lifecycles all use the same Model and Message flow.
Routing
Type-safe bidirectional routing. URLs parse into typed routes and routes build back into URLs. No string matching, no mismatches between parsing and building.
Explore routingServer Rendering
One rendering pipeline: generate static HTML during the build, or render each request on a server. The same init, view, and Model run on both sides, and the browser hydrates the served HTML in place.
Explore server renderingUI Components
Accessible dialogs, menus, tabs, listboxes, disclosures, and more. Each stateful component follows The Elm Architecture and stays open to styling and composition.
Browse the componentsSubmodels
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.
Explore SubmodelsBrowser Lifecycles
Subscriptions open scoped event streams while a Model condition holds. Managed Resources acquire stateful handles like WebSockets and AudioContext. The runtime closes both when the Model no longer needs them.
Explore browser lifecyclesEmbedding
Run a Foldkit widget inside any host application with Runtime.embed. The host pushes data in and receives values out through Schema-typed Ports, and tears the widget down with dispose.
Explore embeddingTests that read like stories and scenes.
Pure update functions mean pure tests. Story tests the state machine. Scene tests features through the view (clicking buttons, typing into inputs) with accessible locators. No DOM, no mocking.
Learn about testingimport { Command, given, message, model, story } from 'foldkit/story'
import { expect, test } from 'vitest'
// Story: test the state machine
test('fetch weather updates the model', () => {
story(
update,
given(model),
message(SubmittedWeatherForm()),
model(model => {
expect(model.weather._tag).toBe('WeatherLoading')
}),
Command.expectExact(FetchWeather),
Command.resolve(FetchWeather, SucceededFetchWeather({ weather })),
model(model => {
expect(model.weather._tag).toBe('WeatherSuccess')
}),
)
})import {
Command,
click,
expect,
given,
inside,
label,
role,
scene,
text,
type,
} from 'foldkit/scene'
import { test } from 'vitest'
// Scene: test through the view
test('type a zip code, click get weather, see the forecast', () => {
scene(
{ update, view },
given(model),
type(label('Zip code'), '90210'),
click(role('button', { name: 'Get Weather' })),
expect(role('button', { name: 'Loading...' })).toExist(),
Command.expectExact(FetchWeather),
Command.resolve(FetchWeather, SucceededFetchWeather({ weather })),
inside(
role('article'),
expect(text('Beverly Hills, California')).toExist(),
expect(text('72°F')).toExist(),
),
)
})Watch your program think.
When every state change flows through Messages and one Model, DevTools can show the full history of the program. Every Message is logged. Every Model state is inspectable. Select any row to see what changed, then rewind the UI to that state.
The same runtime data is available to AI agents over MCP. They can inspect the current Model, walk Message history, rewind the UI to past states, and dispatch Messages.
This site runs on Foldkit. Look for the tab on the bottom right of this page to try DevTools live.
Learn about DevToolsBuilt for
b.
Every feature has the same visible structure: a Schema-defined Model, fact-named Messages, exhaustive update, and explicit Commands. AI-generated changes follow code paths a person can inspect and test.
AI agents can also connect directly to a running Foldkit app over the Model Context Protocol. They read the current Model, inspect Message history, rewind the UI to past states, and dispatch Messages.
Set up AI-assisted developmentStart building.
Scaffold an application, define the Model, and make the first state transition explicit.