Foldkit Documentation Audit
Foldkit's docs are in unusually good shape for a pre-1.0 framework — llms.txt and llms-full.txt both resolve, every docs page is also served as Markdown by appending .md (verified for 30+ pages), all 167 internal and ~128 external links referenced from llms-full.txt return HTTP 200, npm package versions and engine requirements match the docs' claims exactly, and the docs were cleaned of a removed API (Update.noOp) within one release of its removal. The remaining issues are localized: the flagship testing example isn't runnable as written, and a couple of cross-page references assume knowledge the docs never supply.
1. "Testable by Design" Story example references an app that is never shown (significant)
Location: /core/commands (section "Testable by Design")
Problem: The page's headline testing example — Story.story(update, Story.with({ count: 5 }), Story.message(ClickedResetAfterDelay()), Story.Command.expectExact(DelayReset), Story.Command.resolve(DelayReset, CompletedDelayReset()), ...) — depends on update, ClickedResetAfterDelay, DelayReset, and CompletedDelayReset, none of which are defined or imported anywhere on the page. The counter app documented on /core/counter-example (the only complete app in the core docs) has no delay or DelayReset Command, so there is no documented app this test runs against. The only imports shown are Story from foldkit and expect, test from vitest.
Consequence: A developer (or AI agent — code verification is a stated consumer of these docs) who copies the snippet gets four undefined-identifier errors and must reverse-engineer an entire delayed-reset application (a Message, a Command with a timer Effect, a completion Message, and an update branch) just to make the docs' central testability claim executable. The docs sell "Commands aren't just a fancy way to organize side effects. They're the reason Foldkit programs are easy to test" — and then the proof can't be run.
The fix: Either show the delayed-reset app's Model/Message/Command/update definitions above the test (a ~30-line addition), or rewrite the Story example against the counter app already documented on /core/counter-example so the test is runnable by combining two adjacent pages.
2. The counter app is called "complete" but the two files shown cannot run without undocumented scaffold files (minor)
Location: /core/counter-example
Problem: The page opens with "Here's a complete counter application" and states "A Foldkit app lives in two files" — src/main.ts and src/entry.ts. But entry.ts mounts into document.getElementById('root'), which requires an index.html with a #root element, and the view is styled entirely with Tailwind utility classes (min-h-screen bg-white flex flex-col ...), which require the Tailwind entry point and Vite config. Those files exist only in the scaffold documented on a different page (Getting Started's project-structure table lists index.html, src/styles.css, and vite.config.ts), and the counter-example page neither shows them nor links to that table.
Consequence: An agent or developer who extracts the "complete" two files into a bare Vite project gets an app that fails to mount (no #root) or renders unstyled. Humans infer the scaffold; agents extracting the example verbatim fail silently.
The fix: Add one sentence and a link: "Run this inside a project scaffolded by create-foldkit-app — the scaffold provides index.html, Tailwind, and the Vite config (see Project Structure)." Or include the minimal index.html on the page.
3. MCP page gates a feature on a Message DevToolsConfig field the docs never define (minor)
Location: /ai/mcp (section "Notes"), cross-referenced against /core/devtools ("Configuration")
Problem: The MCP page states: "Without Message in your DevToolsConfig, dispatch is rejected. The other tools (read-only) work without it." Neither the MCP page nor the DevTools page's Configuration section explains what Message is here — the DevTools page enumerates the devTools object's optional properties as show and mode (its own example additionally passes overlay and position), and no page shows Message being set on the config or explains why the dispatch tool needs it.
Consequence: A developer who wants agents to dispatch Messages via MCP hits "dispatch is rejected" with no documented way to fix it. They can guess it means passing the app's Message union schema into devTools, but that's an inference, not documentation — and an agent reading the docs can't make the leap at all.
The fix: Document Message in the DevTools Configuration section alongside show and mode (what it is, what enabling it unlocks, a one-line example), and link to it from the MCP page's Notes.
4. Node requirement is documented only for the scaffolder, not for the framework itself (minor)
Location: /get-started/getting-started (section "Requirements")
Problem: The Requirements section says "create-foldkit-app requires Node.js 22.22.2 or newer" — and that is the only Node version statement in the docs. But the same page's next paragraph documents manually installing foldkit into an existing project, and the foldkit npm package itself declares engines: node >=18.0.0. The docs never state the framework's own Node support range.
Consequence: A team pinned to Node 20 reads "Node.js 22.22.2 or newer" as a hard framework requirement and rules Foldkit out — when manual install (the path the page documents immediately below) is supported on their runtime. The inverse failure also exists: a reader can't tell whether the 22.22.2 floor applies to the built app or only to the scaffolding CLI.
The fix: One sentence in Requirements: "The foldkit package itself supports Node.js 18+; the 22.22.2 requirement applies only to the create-foldkit-app scaffolder."
What they do well
- Agent-first delivery done right: llms.txt (23 KB index) and llms-full.txt (1.43 MB concatenation) both resolve, and every docs page is genuinely available as Markdown via
.md— the promise was spot-checked against 30+ pages and held. - Zero dead links: all 167 internal URLs and ~128 external URLs referenced from the docs return HTTP 200, including GitHub source links pinned to a specific commit; sitemap and llms.txt index are aligned.
- Unusual candor: the performance page publishes benchmark numbers in which Foldkit is the slowest framework listed, explains why, and links the harness so readers can reproduce it; the Getting Started page proactively warns about the exact Effect v4 beta peer-dependency pin and its conflict with Effect v3.
Top 3 recommendations
- Make the /core/commands Story test runnable — define (or link to) the app it tests so the framework's central testability claim can be executed by copy-paste.
- On /core/counter-example, state the scaffold prerequisites (index.html, Tailwind, Vite config) or include them, so the "complete" app is complete outside a scaffolded project.
- Document the
MessageDevToolsConfig field referenced by the MCP page, and state the framework's own Node.js support range (18+) next to the scaffolder's 22.22.2 requirement.