The compiler for user interfaces

Start here·3 min· Assumes: nothing

You have learned enough frameworks. (even if the number is zero) This one is mostly subtraction: TypeScript functions and one word you already know, state.

The idea underneath is small. When you create a variable, create it with state. Whatever reads it stays current, and the screen is one of the things reading it.

Hover a line if you don't believe it. Then click the heart:

mug-card.tsrx
1import { state } from '@markless/core'; 2 3export default function MugCard() @{4	let likes = state(0);5 6	<article>7		<div class="photo">8			<img src="/mug.png" />9			<h3>The Markless mug </h3>10			<p>Holds hot takes. </p>11		</div>12		<button onClick={() => likes++}>13			♥ {likes}14		</button>15	</article>16}
A hand-drawn coffee mug sticker

The Markless mug

Holds hot takes.

You just changed a variable. The number followed, because state told the page to follow likes. That is the whole trick.

Nothing hidden

Too simple, right? Surely something is re-running your code on every click. Good instinct, wrong framework. This heart keeps a log of every time your function runs:

your function runs#1 at 03:59:35

Your function ran once. Every click since is just likes++. Your AI can't hallucinate what doesn't exist. There's nothing hidden under the page: one run, then plain updates. And when code can't compile safely, the build fails and says why, which your AI can easily fix.

One language

A component is a TypeScript function in a .tsrx file. There is no template language. Add the router and a file under pages/ is a URL, with no routing config either. That is the whole learning curve, for you and for your agent.

Not married to the web

TSRX, the language underneath, also compiles to React, Solid and Vue. Nothing about a compiled interface insists on a browser either. And the speed people notice is a side effect: every update is written in advance. How it works shows the machinery.

Coming from another framework?

Three things you may be looking for are absent on purpose. There is no virtual DOM: templates compile to real DOM operations, and nothing re-renders. There is no hydration pass: a server-rendered page wakes up without re-running your components, which Markless calls resume. And there is no second syntax to hold in your head, because there is exactly one authoring language. That also means JSX and TSX are not supported, now or later.

Where to go next

Your first app is one command and four questions. Reading a .tsrx file is five minutes on the three unfamiliar bits. Already have a component? State covers updates.