- Dependencies
- 5
- Runtimes
- Node · Bun
- Features tracked
- 58
- License
- MIT
The mental model
One file per job. Readable at a glance.
Data lives in JSON, the page declares what it shows, a typed function renders it. No template language to learn, no magic to reverse-engineer: you, your teammates and your coding agent can read every page and know where everything comes from.
UIsrc/app/pages/index.html
<main>
<!-- component="site/header.html" -->
<h1 data-t="HOME.TITLE">Talks</h1>
<ul class="talks">
<!-- create-from-data-source="talks.json" renderer="talkList" options="{"limit":3}" -->
</ul>
</main>Datadata-sources/talks.json
[
{
"title": "Static sites in 2026",
"date": "2026-03-12",
"place": "Milan"
},
{
"title": "Agents and the web",
"date": "2026-05-02",
"place": "Online"
}
]Logicbuilder/renderers.ts
import { RendererProps } from 'yassb-web';
export function talkList({ source, options }:
RendererProps<Talk[], { limit?: number }>) {
return source
.slice(0, options?.limit)
.map(t => `<li>${t.title} · ${t.place}</li>`)
.join('');
}Everything included
All a static site needs. Nothing it doesn't.
Components
Pages are just HTML
Reuse headers, footers and sections with one comment. HTML, SVG and Markdown components, nested as deep as you like, with front matter placeholders.
{ "title": "Agents" },
{ "title": "Speed" }
]
Data + renderers
Content in JSON, markup from TypeScript
A page names the file it shows and the function that renders it. Typed props, no template language, nothing hidden.
---
title: Hello world
date: 2026-01-15
---
# Hello
Write **Markdown**, get a page.
Markdown
Blogs and docs
One page per Markdown file, with front matter. These docs are built that way.
<h1 data-t="HOME.TITLE">
Translations
One markup, every language
Mark text with a key; each page is built once per language, and missing keys are reported.
Assets
Bring your CSS, keep your TS
Sass by default, Tailwind or any PostCSS pipeline in five lines, TypeScript and JSX bundled with esbuild.
Agent-ready
Built to be read by coding agents.
An agent needs a map, the rules and a way to know it got it right. YASSB ships all three in the command line, in plain text and JSON.
$ npx yassb inspect YASSB project my-site@1.4.0 (yassb-web 2.1.0) Languages: en, it (first one served at /) Pages (6): src/app/pages/index.html "Home" components: site/footer.html, site/header.html data: talks.json→talkList, team.json→peopleCards Data sources (4): talks.json array(12) of {title, date, place} ← src/app/pages/index.html:18 Renderers: talkList custom used 2× peopleCards custom used 1×
yassb inspect
A map of any site in one command
Pages, components, data sources, renderers and every directive with file and line. Read-only, half a second, and --json for a full manifest.
$ npx yassb check error DATA_SOURCE_NOT_FOUND src/app/pages/index.html:18 Data source "talk.json" not found. hint: paths are relative to data-sources/ ✗ 1 error(s), 0 warning(s) → exit 1
yassb check
Knows when a change is right
Builds and validates: directives, data, translations, links, undeclared packages. Exit code 0 means done.
{
"level": "error",
"code": "RENDERER_FAILED",
"file": "src/app/pages/index.html",
"line": 18,
"message": "Renderer \"talkList\" failed: …",
"fatal": true
}Diagnostics
Errors an agent can act on
Every problem has a stable code, the source file, the line and a hint. No more guessing from a stack trace.
$ npx yassb docs features directive (8) directive.component directive.create-from-data-source directive.url-to … config (21) cli (8) i18n (2) …
yassb docs
The manual, in the terminal
The whole guide ships with the package and always matches the installed version. No browsing, no hallucinated APIs.
58
features · 100% documented
Feature catalogue
Docs that can't fall behind
Every feature is tagged in the code. If one is missing from the docs, YASSB's own build fails.
Developer experience
A watch mode you can trust.
Save a file, see the page. Change a renderer, the config, even package.json: picked up, every time.
- 1Fast, then verified.
- A warm process rebuilds a content change at once, then a clean one checks it gives the same output as
yassb build. Change your code or the config and a new process picks it up. - 2Only what changed.
- A stylesheet edit swaps the CSS without reloading; a script edit only rebundles the scripts.
- 3Errors in the page, not in a log.
- If your code throws, the server stays up and the browser shows what broke, with file and line.
- 4TypeScript with zero setup.
- Config, renderers and directives in TS or TSX, compiled by esbuild. No ts-node, no build step.
$ yassb watch YASSB v2.1.0 watch node 22.20.0 › assets 0 ms › texts 9 ms › html en 16 ms › html it 3 ms › post-processing 2 ms › styles 102 ms › scripts 1 ms ● i18n missing translations: en 2, it 3 (yassb check lists them) 07:12:34 ✓ built in 211 ms (html, styles, scripts) 0 errors · 9 warnings ● ready http://localhost:3000 dist/public · watching for changes · ctrl+c to stop 07:12:35 change src/app/styles/styles.scss › assets 0 ms › styles 5 ms 07:12:35 ✓ built in 7 ms (styles) 0 errors · 0 warnings 07:12:35 ✓ verified in 156 ms · same output as yassb build 07:12:41 change builder/renderers.ts › assets 1 ms › texts 9 ms ✗ error RENDERER_FAILED src/app/pages/index.html:18 Renderer "talkList" failed on `<!-- create-from-data-source="talks.json" renderer="talkList" options="{"limit":3}" -->`: Cannot read properties of undefined (reading 'title') TypeError: Cannot read properties of undefined (reading 'title') at Object.talkList (/home/me/my-site/builder/renderers.ts:6:35) › html en 15 ms › html it 4 ms › post-processing 2 ms › styles 98 ms › scripts 1 ms 07:12:41 ✗ built in 214 ms (html, styles, scripts) 1 error · 9 warnings
RENDERER_FAILED src/app/pages/index.html:18
Renderer "talkList" failed on <!-- create-from-data-source="talks.json" renderer="talkList" … -->: Cannot read properties of undefined (reading 'title')
In numbers
Light to install, quick to build.
Measured on a real bilingual site: thirteen pages, a blog, Tailwind and custom directives.
Runtime dependencies
5
58 installed packages in all. Node built-ins first, one tool per job.
Save → refresh
<0.4s
A content change is rebuilt by a warm process and verified against a clean build.
Full build
1.3s
Minified, validated, ready to deploy; 0.9 s on Bun.