Skip to content
These are temporary community docs. The official docs are in progress.Help improve them
Markless
Esc
↑↓navigate↵open⌘Jpreview
On this page

What is Markless?

The mental model. The compiler plans every update before your app runs, your component runs once, and the same component renders in many places.

The landing page showed one click that changed one number. So who decided which number to change?

The compiler did, before your app ever ran.

The compiler plans first

The compiler reads your .tsrx files at build time. It writes a plan: which state exists, which text shows it, and which code runs on which click.

Think of a stage crew with a cue sheet. That is an analogy. During the show, the crew follows the cues. Nobody rebuilds the set.

Your app follows the plan:

  • Your component runs once, to set up the page.
  • No click code runs until the first click. Then Markless loads the code for that one click.
  • When count changes, only the text that shows count changes.

Change where the code shows count, then click Add one.

What does the compiler write down, and what does a click touch?

Change where the code shows count. Read the new plan. Then click Add one.

Your code: Counter.tsrx

Edit the code. Where does it show count?

Where the code shows count
import { state } from '@markless/core'; export default function Counter() @{ let count = state(0); (state) <h1>My counter</h1> <p>Count: {count}</p> (shows count) <button onClick={() => count++}>Add one</button> (click code)}
1. Before your app runs, the compiler plans
  • state count starts at 0.
  • shows count One text shows count: the line under the title.
  • click code () => count++ runs on click. It stays unloaded until then.
2. The page
Counter

My counter

Count: 0

3. When you click
Times your component ran1Clicks never run it again
Texts changed per click1Only the texts in the plan
  1. ranYour component ran once, to set up the page.

Simplified. The plan lists what the compiler works out from your code, in plain words. The list under “When you click” shows what happens, not every step.

Notice that the plan changes with your code, and a click changes only the texts in the plan.

Here is the counter from the landing page:

import { state } from '@markless/core';

export default function Counter() @{
	let count = state(0);

	<button onClick={() => count++}>Count {count}</button>
}

Notice that count is a plain value. You read it and change it like any other variable.

Render it anywhere

The compiled component does not care where it runs. Pick the place your app needs. The plan stays the same.

Where How
One page in the browser render(App, { target }) from @markless/core. See Use Markless without a server.
A multi-page app @markless/router turns files in pages/ into URLs. See Quick start.
HTML from a server renderToString() from @markless/core.
Tests @markless/vitest-browser runs components in the Vitest browser mode.
Native apps Two experiments drive iOS and macOS buttons from the same counter.

If a server makes the HTML, your component runs there. It does not run again in the browser.

Coming from another framework?

Your code has no compiler markers: no .value, no $, no useX. That is the “mark” in Markless.

Nothing re-renders. The component body is setup, and the compiler wires each update. There is no effect system, so you never write a dependency list.

Markless borrows ideas from Solid, Ripple, Octane, Svelte, Marko, and Qwik. For the technical version, read Why Markless, technically.

Next: What is the smallest setup that runs this counter? Use Markless without a server →

Was this page helpful?