RatMinimal web framework

About Rat

Small web apps should feel small.

Rat is a tiny language where one .rat file can hold a server, a page, styles, and behaviour, all served by one Go binary.

Read the docsWhy it exists

one .rat file · one Go binary · one dispatch shape

Why I made Rat

Rat started as a personal tool. I wanted to build small websites and apps without turning every idea into a stack decision first.

The shape came from borrowing small pieces of tools I liked: Ruby, Python, Pug, JSX, SCSS, Tailwind, C#, and a few others. Rat does not copy those languages whole. It keeps the parts that make web code feel direct and gives them one model.

The goal was modest: open one file, see the server state and the page, make a change, and still understand the code when I came back later.

What makes Rat unique

Rat gets most of its character from a few constraints.

Tail keeps Rat small: call other runtimes through the same shape, and leave the heavy work where it belongs.

Why Rat exists

Modern frameworks are good. The problem is that small apps often inherit big-app ceremony.

Before the first button works, you may already be choosing a language mode, a UI library, a router, a bundler, a server layer, an API shape, and a state model. None of those choices is wrong on its own. The pile is the problem.

Rat pushes the other way. It keeps the web-facing surface small, regular, and easy to explain.

A small page can become a stack decision tree before the page exists.

I do this too. I copy old projects, keep stale conventions, and wrap old decisions in new names. Give it six months and I can open my own code feeling like I need a guided tour. Rat is an attempt to avoid that drift.

Everything else

Rat

Complexity over time. Same axis on both sides.

Rat does not try to become every language. It gives you a small web-facing layer, then lets Python, JavaScript, SQL, or another runtime handle the parts they already do well.

The feeling Rat is after

Good tools leave more attention for the thing you are making.

Rat in practice

State, markup, and behaviour usually live in separate places, with glue between them. In Rat they can share one file and one connection model. Here is a whole counter: the code on the left, the running thing on the right. Same source.

counter.rat

> server
count: 0

> page
<button on_click[count << count + 1]> clicked [count] times

running, live

One mental model

Rat fights entropy by being a little stubborn. One way to declare state. One way to render it. One way to mutate it. One call shape for everything: name.method(args). The other end might be a built-in, a database, a service, a JSON API, a Python function, or browser JavaScript. The shape stays the same.

Three concerns, one dispatch model, and usually one obvious way to write what you mean.

One model does not make every app simple. It keeps the language from adding new spellings for old ideas. Code stays easier to read, easier to review, and less annoying to return to later.

Same call, either side

In most stacks, the server and browser feel like different worlds. Rat keeps pure computation consistent across both. Built-ins for strings, math, collections, regex, dates, JSON, encoding, and logging have Go and JavaScript versions, so the same call can behave the same during a server render and a browser update.

Effects stay where I/O belongs. Databases, HTTP, services, Tail, channels, and native APIs commit to a host and pass through dispatch when needed. The line is explicit instead of hidden in framework glue.

AI should read the language, not guess it

New languages do not have a giant training corpus. Rat leans into that. The language is small enough to describe directly, so a model can work from the rules instead of guessing from whatever stack it has seen most.

The whole dialect is designed to fit in one prompt. That is what llms.txt is for.

If you write Rat with an LLM, start with llms.txt. For code generation, give it llms-full.txt: the complete dialect guide and docs in one file.

That is also a useful constraint on Rat itself. If the language cannot be explained clearly, it is probably getting too complicated.

What Rat is for

Rat is not a replacement for mature production stacks. Use those when you need their ecosystem, scale, and years of battle-testing.

Rat is for small apps, personal tools, prototypes, teaching examples, and experiments where the whole program should fit in your head.

The bet is ordinary, but worth making: some software can stay small. Tools can have less ceremony. Building things can still feel like making.

I am Angelo Wolff, and I designed and built Rat. The source lives on GitHub, and you can find more of my work on my profile.