Public
Like
diceRollerUI
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data β all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v9View latest version
This is a checklist + guide to avoid the mistakes we made while building simple UIs (like Dice Roller).
- Must be named:
main.tsx
- Must be of type:
http
- Must export a
default async function server()
that returns HTML - Must include a
client()
function that callscreateRoot(...).render(...)
- Must include hydration logic:
client()
must be re-exported:export { client };
- At the top, include:
/** @jsxImportSource https://esm.sh/react@18.2.0 */
- Import from URLs:
import { createRoot } from "https://esm.sh/react-dom@18.2.0/client"; import { useState } from "https://esm.sh/react@18.2.0";
The server()
function should return:
return new Response(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My App</title>
<script type="module">
import { client } from "${import.meta.url}";
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', client);
} else {
client();
}
</script>
</head>
<body>
<div id="root"></div>
</body>
</html>`, {
headers: { "content-type": "text/html; charset=utf-8" }
});
- Use Tailwind classes for layout, spacing, buttons, etc.
- Optionally import from CDN or inject inline CSS.
- Create a Val with
http
type filemain.tsx
- Set up JSX import and
server()
/client()
boilerplate - Build your UI in a
function App()
and render it insideclient()
- Return correct HTML in
server()
- Add a
moi.md
with title, url, image, and tags
Youβre ready to make any UI with just "make a X". π