title: "wwwhat -- What if HTML was enough?" fetch.dog = "https://dog.ceo/api/breeds/image/random" set.wired.dog_url = "#dog.message#" description: Build full-stack web apps with HTML attributes. No JavaScript. No backend code. og.title: wwwhat -- What if HTML was enough? og.description: A Rust-powered web framework where HTML is the logic. File-based routing, server state, SQLite database, JWT auth -- all from .html files.

A Rust-powered web framework

What if HTML was enough?

Server-rendered web apps with HTML attributes.
No JavaScript. No backend code. Just ship.

File-based routing · Template variables · Components · SQLite + D1 · JWT auth · Forms · Uploads · Email · Deploy

The installable demo focuses on the progressive component demos. Full docs live at getwhatnow.com/docs.

Write less. Ship more.

A counter that persists server-side. Compare the approaches.

Traditional Stack

// api/counter.ts
import { db } from '../lib/db'
export async function POST(req) {
  const session = await getSession(req)
  await db.counter.increment(session.id)
  const count = await db.counter.get(session.id)
  return Response.json({ count })
}

// components/Counter.tsx
'use client'
import { useState } from 'react'
export function Counter() {
  const [count, setCount] = useState(0)
  const increment = async () => {
    const res = await fetch('/api/counter',
      { method: 'POST' })
    const { count } = await res.json()
    setCount(count)
  }
  return <button onClick={increment}>
    +1 ({count})
  </button>
}

wwwhat

<!-- site/counter.html -->

<p>Count: #session.counter|default:"0"#</p>

<button w-set="session.counter += 1">
  +1
</button>




That's the whole file.
No API. No state library.
No build step.

Try it live

Fetches a dog photo, increments your session counter, and updates a wired counter that pushes to every connected browser.

Random dog
#wired.dog_count|default:"0"#
Everyone (wired)
#session.dog_count|default:"0"#
You (session)

Open in another browser -- your count resets, the wired count stays in sync.

Everything included

What you'd normally install, configure, and debug separately -- all built in.

File-based routing

site/post/[id].html becomes /post/123

Template variables

#variable# syntax for data binding, filters, and defaults

JWT auth

Login, logout, role-based access from templates

SQLite + D1 database

Auto-migration, CRUD, queries -- local SQLite or Cloudflare D1

Components

HTML files become custom elements with props and slots

Form validation

Declarative rules, client + server enforcement

File uploads

Local storage or Cloudflare R2 with collection-based routing

Email sending

SMTP + Resend API with HTML templates

Bot protection

Cloudflare Turnstile integration for forms and actions

CSS framework

Utility-first styles included, dark mode, zero config

Client attributes

w-get, w-post, w-set -- interactivity without writing JavaScript

Static build + deploy

Pre-render to static HTML, deploy via Docker, SSH, or CDN

Explore the demos

Every feature is interactive. Click through to see it work.