Boring multi-page software, in plain HTML.
plainkit is a vanilla JavaScript toolkit for pages served as files. Dashboards, data entry, settings, lists, and the occasional live page. DataProvider owns each resource. Interceptor is the only fetch. An agent stays fast because every screen is that same small job: copy a recipe, point it at a URL, and leave the English in the HTML.





One page, one URL
An app is many HTML files. Navigation is a real link. A full page load stays a full page load.
One owner for each fact
DataProvider owns a resource. Interceptor owns fetch. LiveProvider owns the socket. The page script paints what they report.
Recipes, not a widget kit
Copy a whole page when you need a list, a table, settings, or a live room. The next screen uses the same verbs.
A few owners, and that is the design.
The kit is small on purpose. These four pieces cover HTTP, the socket, and how a page paints. There is no second data layer to learn on the next screen.
DataProvider
One provider, one resource: a list, a user, or a settings object. The page calls load, create, save, or remove. subscribe hands back data, status, and error. SessionProvider is a DataProvider whose payload includes roles.
Interceptor
Every DataProvider request goes through one fetch. A request hook sets a header. An error hook can send 401 and 403 to real HTML pages. Buttons never attach credentials themselves.
Bind
HTML is the page. bindText, bindField, and bindList paint from the provider event. English stays in the markup, so the first paint does not wait on JSON.
LiveProvider
A live room is still one document. LiveProvider connects, sends, and closes. The page script does not construct a WebSocket. A clock on the page reads seconds from the provider.
Cheap when an agent builds the site.
The same concepts show up in every file: one prefix, small modules, and a page script that calls load, create, save, or send. An agent spends its context on the screen in front of it. The next session can change that screen without reconstructing a framework.
The same job every screen
Name the URL, pick a page shape, write the HTML, construct a provider, bind, then call a verb. An agent can start a form without first choosing a router, a store, and a component library.
Copy the nearest recipe
Lists, tables, settings, and the live room already exist as whole pages. The new file keeps the same imports, the same verbs, and the pk- classes. The model edits a known page.
Cross-cutting work is one hook
A bearer token or a redirect on 401 is an Interceptor hook for that page. The agent adds it once. Later edits stay on that page, because there is no client store shared with the next URL.