Yawnv1.0
Getting Started

Introduction

Yawn is a TypeScript-first, HTML-based web framework. Write .yawn files, run one command, ship a real site. No bundler config, no JSX, no boilerplate.

Yawn is in active development. The API is stable for v1.0 but some packages are still maturing.

What makes Yawn different

Most frameworks ask you to learn a new paradigm before writing a single line. Yawn doesn't. If you know HTML, you already know 80% of it.

HTML-first
Write real HTML. No JSX, no virtual DOM ceremony, no mental model switch.
Zero config
Tailwind CDN is injected automatically. No webpack, no vite config, no postcss setup.
Instant reactivity
Declare a variable, use it in a template. Yawn wires the rest.
SSR out of the box
Every page server-renders to HTML first. Fast initial load, great SEO.
File-based routing
The file system is your router. Drop a file in src/pages/, get a route.
TypeScript native
Full TypeScript support throughout. No extra setup.

How it works

You write a .yawn file. The compiler reads <template>, <script>, and <style>, generates a server-rendered HTML page with a hydration script, and serves it. The browser renders HTML immediately, then Yawn's tiny runtime attaches reactivity.

hello.yawn
class="text-white/class="text-orange-400">30"><class="text-indigo-class="text-orange-400">400">templateclass="text-white/class="text-orange-400">30">>
  class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">div class="min-h-screen bg-[#0a0a0f] text-white flex items-center justify-center px-class="text-orange-400">4">
    class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">div class="text-center max-w-lg">
      class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">div class="inline-flex items-center gap-class="text-orange-400">2 bg-white/class="text-orange-400">5 border border-white/class="text-orange-400">10 rounded-full px-class="text-orange-400">4 py-class="text-orange-400">1.class="text-orange-400">5 text-xs text-white/class="text-orange-400">50 mb-class="text-orange-400">8">
        class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">span class="w-class="text-orange-400">1.class="text-orange-400">5 h-class="text-orange-400">1.class="text-orange-400">5 bg-green-class="text-orange-400">400 rounded-full">class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/spanclass="text-white/class="text-orange-400">30">>
        Live on Yawn v1.class="text-orange-400">0
      class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/divclass="text-white/class="text-orange-400">30">>
      class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">h1 class="text-5xl font-black tracking-tight mb-class="text-orange-400">4">Hello, class="text-yellow-300">{{ name }}class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/h1class="text-white/class="text-orange-400">30">>
      class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">p class="text-white/class="text-orange-400">40 mb-class="text-orange-400">8">You have clicked class="text-yellow-300">{{ count }} class="text-yellow-300">{{ count === class="text-orange-400">1 ? class="text-green-class="text-orange-400">400">'time' : class="text-green-class="text-orange-400">400">'times' }}class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/pclass="text-white/class="text-orange-400">30">>
      class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">div class="flex items-center gap-class="text-orange-400">3 justify-center">
        class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">button class="text-green-400">@click="count++" class="bg-white text-black px-class="text-orange-400">6 py-class="text-orange-400">2.class="text-orange-400">5 rounded-lg font-semibold hover:bg-white/class="text-orange-400">90 transition-colors">
          Click me
        class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/buttonclass="text-white/class="text-orange-400">30">>
        class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">button class="text-green-400">@click="count = class="text-orange-400">0" class="border border-white/class="text-orange-400">10 text-white/class="text-orange-400">50 px-class="text-orange-400">6 py-class="text-orange-400">2.class="text-orange-400">5 rounded-lg hover:text-white hover:border-white/class="text-orange-400">30 transition-colors">
          Reset
        class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/buttonclass="text-white/class="text-orange-400">30">>
      class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/divclass="text-white/class="text-orange-400">30">>
    class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/divclass="text-white/class="text-orange-400">30">>
  class="text-white/class="text-orange-400">30"><class="text-blue-class="text-orange-400">400">/divclass="text-white/class="text-orange-400">30">>
class="text-white/class="text-orange-400">30"><class="text-indigo-class="text-orange-400">400">/templateclass="text-white/class="text-orange-400">30">>

class="text-white/class="text-orange-400">30"><class="text-indigo-class="text-orange-400">400">scriptclass="text-white/class="text-orange-400">30">>
class="text-purple-class="text-orange-400">400">let name = "World";
class="text-purple-class="text-orange-400">400">let count = class="text-orange-400">0;
class="text-white/class="text-orange-400">30"><class="text-indigo-class="text-orange-400">400">/scriptclass="text-white/class="text-orange-400">30">>

Key principles

HTML-first
Developers write HTML, not JSX. The template is real HTML with reactive attributes.
Zero config
Tailwind CSS is auto-included via CDN. No bundler, no postcss, no config file.
Minimal script
The script block only holds variable declarations. Event handlers live inline in the template.
SSR + hydration
Pages are server-rendered to full HTML, then hydrated by a tiny runtime.
File-based routing
src/pages/about.yawn becomes /about automatically. No router config needed.

Quick start

terminal
npx create-yawn@latest my-site