Cookbook
Real recipes for the shapes most apps actually need — each built from the plain files you'd write yourself, with no build step and Zoijs's safe-by-default rendering throughout. Every recipe uses only the public API; copy a page, change the endpoints, and you have a working feature.
Recipes#
- CRUD — list, create, edit, and delete against a REST API, with
@zoijs/resourcefor reads and@zoijs/actionfor writes. - Debounced search — a typeahead that waits for the user to stop typing, cancels stale results, and never races.
- Infinite scroll — load more as the user reaches the end, with an
IntersectionObserverand clean teardown. - File upload — a native file input, a real progress bar, and a safe object-URL preview.
- Data table — a sortable, filterable table over a keyed
each, so rows are reused (not rebuilt) as the view changes. - Charts (via a plain library) — drop in any vanilla chart library with a
ref; no wrapper, no plugin. - Animations — enter, toggle, and leave with CSS transitions and the Web Animations API via
ref; no motion library. - Icons — inline SVG, a
<use>sprite, or a tiny icon component; no icon package.
Two more common shapes have their own dedicated pages:
- Forms & validation → Forms (
@zoijs/forms). - Authentication → Authentication (a recipe, not a package — by design).
The pattern behind them#
Most of these recipes are the same three moves:
- Reads are a
resource—loading()/data()/error()/refresh(). - Writes are an
action—pending()/error()/run(), thenrefresh()the read. - The view is a function returning
html, where${() => …}binds the reactive readers to the DOM. One value changes, one node updates — no re-render.
Because rendering is fine-grained and text is inert by default, these stay fast and safe without extra ceremony. Where a recipe touches a sink that can be unsafe (an object URL, a third-party library's DOM), the page calls it out and shows the safe form.
Next: CRUD.