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

Use Markless without a server

Run a Markless component in a plain Vite app with five small files, two packages, and no server.

Last page said the same component renders anywhere. The smallest place is one browser tab.

You need five small files and two packages: @markless/core and vite. The build gives you plain static files.

Press Run, then click the button that shows up.

Where does my component end up?

Press Run to open the page. Then click Count 0 inside it.

The pageTry it
My Markless appno server
#appEmpty. Press Run.

The page's HTML right now

<body> <div id="app"></div> ... </body>
Your code: three files

index.html

<!doctype html><html lang="en"> <head> <meta charset="utf-8" /> <title>My Markless app</title> </head> <body> <div id="app"></div> (empty) <script type="module" src="/src/main.ts"></script> </body></html>

src/main.ts

import { render } from '@markless/core';import App from './App.tsrx'; const target = document.querySelector('#app');if (!target) throw new Error('Missing #app'); await render(App, { target }); (not run yet)

src/App.tsrx

import { state } from '@markless/core'; export default function App() @{ let count = state(0); <button onClick={() => count++}>Count {count}</button>}
What Markless did
Times App ran0not yet
Texts updated0
  1. noteNothing ran yet. The page is empty until you press Run.

Simplified. Run stands for opening the page: the browser loads index.html, which runs main.ts. The HTML view shows only the body. No server takes part.

Notice that App runs once, in the browser, and fills the empty #app.

Build it

Create package.json

{
	"name": "my-counter",
	"private": true,
	"type": "module",
	"scripts": {
		"dev": "vite",
		"build": "vite build",
		"preview": "vite preview"
	}
}

Then install the two packages:

npm install @markless/core vite

Add index.html

<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>My Markless app</title>
	</head>
	<body>
		<div id="app"></div>
		<script type="module" src="/src/main.ts"></script>
	</body>
</html>

Add vite.config.ts

The markless() plugin runs the compiler on your .tsrx files.

import { markless } from '@markless/core/vite';
import { defineConfig } from 'vite';

export default defineConfig({
	plugins: [markless()],
});

Add src/main.ts

render() runs App once and puts the result inside #app.

import { render } from '@markless/core';
import App from './App.tsrx';

const target = document.querySelector('#app');
if (!target) throw new Error('Missing #app');

await render(App, { target });

Add src/App.tsrx

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

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

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

Run it

npm run dev

Open http://localhost:5173 and click Count 0. Notice that only the button text changes.

To build for production, run npm run build. The dist/ folder holds index.html and a build/ folder of JavaScript files. Any static file host can serve dist/.

Next: What if you want many pages, each with its own URL? Quick start →

Was this page helpful?