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
countchanges, only the text that showscountchanges.
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.
Edit the code. Where does it show 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)}- state
countstarts at 0. - shows count One text shows
count: the line under the title. - click code
() => count++runs on click. It stays unloaded until then.
My counter
Count: 0
- 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 →
