On this pageOverview
View
The view function is a pure function that transforms your model into HTML. Given the same model, it always produces the same HTML output. The view never directly modifies state — instead, it dispatches messages through event handlers.
import { Class, Html, OnClick, button, div } from '../html'
// VIEW - Renders your state as HTML
// Pure function: same state always produces the same HTML — no side effects
const view = (model: Model): Html =>
div(
[Class(containerStyle)],
[
div(
[Class('text-6xl font-bold text-gray-800')],
[model.toString()],
),
div(
[Class('flex flex-wrap justify-center gap-4')],
[
// OnClick takes a Message, not a callback. The Message doesn't
// execute anything — it just declares what should happen on click.
// Foldkit dispatches it to your update function.
button([OnClick(Decrement()), Class(buttonStyle)], ['-']),
button([OnClick(Reset()), Class(buttonStyle)], ['Reset']),
button([OnClick(Increment()), Class(buttonStyle)], ['+']),
],
),
],
)
// STYLE
const containerStyle =
'min-h-screen bg-cream flex flex-col items-center justify-center gap-6 p-6'
const buttonStyle =
'bg-black text-white hover:bg-gray-700 px-4 py-2 transition'Pure functions, no hook rules
The view is like a functional component, but guaranteed pure — no hooks, no effects, no local state. It's a function from Model to Html. This simplicity means no "rules of hooks" to follow.
Foldkit's HTML functions are typed to your Message type. This ensures event handlers only accept valid Messages from your application. You create these helpers by calling html<Message>() and destructuring the elements and attributes you need:
import { html } from 'foldkit/html'
// Create typed HTML helpers for your Message type.
// This ensures event handlers like OnClick only accept your Message variants.
export const {
// Attributes
Class,
Id,
Href,
OnClick,
OnInput,
OnSubmit,
Value,
// Elements
a,
button,
div,
form,
h1,
input,
p,
span,
} = html<Message>()This pattern might seem unusual if you're coming from React, but it provides strong type safety. If you try to pass an invalid Message to OnClick, TypeScript will catch it at compile time. You only need to do this once per module — most apps create a single html.ts file and import from there.
Event handlers in Foldkit work differently from React. Instead of passing a callback function, you pass a Message. When the event fires, Foldkit dispatches that Message to your update function.
// Event handlers take Messages, not callbacks.
// When the button is clicked, Foldkit dispatches the Message
// to your update function.
button(
[OnClick(ClickedIncrement()), Class('button-primary')],
['Click me'],
)
// For input events, Foldkit extracts the value and passes it
// to your function:
input([
OnInput(value => ChangedSearch({ text: value })),
Value(model.searchText),
Class('input'),
])For simple events like clicks, you pass the Message directly. For events that carry data (like input changes), you pass a function that receives the event and returns a Message. This keeps your view declarative — it describes what Messages should be sent, not how to handle them.