---
title: What is Markless?
description: The mental model. The compiler plans every update before your app runs, your component runs once, and the same component renders in many places.
sidebar: { label: What is Markless }
---

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**.

<StartPlanFigure />

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:

```tsrx Counter.tsrx
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](/start/browser-only). |
| A multi-page app | `@markless/router` turns files in `pages/` into URLs. See [Quick start](/start/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](/how-it-works/design-choices).

:::warning[Work in progress]
Markless is at version 0.5.0. Its authors have not announced it yet. The native apps are experiments. They leave out styles and app packages.
:::

**Next:** What is the smallest setup that runs this counter? [Use Markless without a server →](/start/browser-only)
