Built for humans & coding agents

Static sites. Plain code.

HTML components. JSON or Markdown content. TypeScript logic. YASSB brings them together into a static site.

Get started
Dependencies
5
Runtimes
Node · Bun
Output
Static HTML, CSS & JavaScript
License
MIT

The mental model

Content, markup and logic. Each in its place.

Store content in JSON or Markdown, compose pages in HTML, and use TypeScript functions to turn data into markup. HTML comment directives connect the pieces, making it clear where content comes from and how each page is built.

1Data

Content in JSON or Markdown.

Content lives in JSON or Markdown files, apart from markup and code. Update the data file, and rebuild every page that uses it.

Datasrc/app/data-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" },
  { "title": "Shipping with YASSB", "date": "2026-09-18", "place": "Turin" }
]

2UI

HTML pages with reusable components.

Pages are plain HTML. Write a block once as a component and reuse it anywhere. A directive marks where data goes: it names the data file and the renderer that turns it into HTML.

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>

3Logic

Render data with TypeScript at build time.

A renderer is a typed function: it gets the data and options from the directive and returns HTML, with any loop or condition you need. Custom directives are TypeScript too. All of it runs at build time: visitors get static HTML.

Logicbuilder/renderers.ts

import { RendererProps } from 'yassb-web';

type Talk = { title: string; date: string; place: string };

export function talkList({ source, options }:
  RendererProps<Talk[], { limit?: number }>) {
  return source
    .slice(0, options?.limit)
    .map(t => t.place === 'Online'
      ? `<li>${t.title} · <a href="/live">watch live</a></li>`
      : `<li>${t.title} · ${t.place}</li>`)
    .join('');
}

Site-building features

Components, Markdown, translations and asset bundling.

Reuse page sections, generate pages from Markdown, build multiple language versions, and bundle styles and scripts in the same build.

<!-- component="header.html" -->↵
<!-- component="footer.html" -->↵

Components

Reuse HTML across pages

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" }
]
talkList()→
Agents
Speed

Data + renderers

Generate HTML from your data

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">

enWelcome itBenvenuti deWillkommen

Translations

Build each page in multiple languages

Mark text with a key; each page is built once per language, and missing keys are reported.

Sass Tailwind esbuild TypeScript

Assets

Compile styles and bundle scripts

Use Sass by default or configure Tailwind and other PostCSS plugins. Bundle TypeScript and JSX scripts with esbuild.

Agent-ready

Give your coding agent a map, documentation and checks.

Inspect the project structure, read documentation for the installed version, and validate changes from the command line. Structured output and source locations help agents find the files to edit and diagnose build errors.

$ npx yassb inspect
YASSB project my-site@1.4.0 (yassb-web 2.1.1)
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, with --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

Check the build after a change

Builds and validates: directives, data, translations, links, undeclared packages. Returns a non-zero exit code when validation fails.

{
  "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 complete guide ships with the package, matching the installed version and available directly in the terminal.

58

features · documentation coverage checked

Feature catalogue

Documentation coverage checked during development

Every feature is tagged in the code. If one is missing from the docs, YASSB's own build fails.

Developer experience

Edit, save, preview.

Preview changes as you work. YASSB watches content, styles, scripts and build configuration, updates the browser, and shows build errors directly in the page.

1Fast previews, verified against a clean build.
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.
2CSS updates without a page reload.
A stylesheet edit swaps the CSS without reloading; a script edit only rebundles the scripts.
3Build errors shown in the browser.
If your code throws, the server stays up and the browser shows what broke, with file and line.
4Write build logic in TypeScript.
Config, renderers and directives in TS or TSX, compiled by esbuild. No separate compilation step for your build configuration, renderers or directives.
localhost:3000
YASSB: rebuilding…
YASSB: 1 error(s) in the last buildclose

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

Time from saving a content change to seeing the updated page in the browser. Rebuild output is also verified against a clean build.

Full build

1.3s

Minified, validated, ready to deploy; 0.9 s on Bun.