Assets & styling
sitelo is built on Vite, so frontend JavaScript and CSS are compiled automatically. Put scripts and styles under src/ (for example src/js and src/css), link them from your HTML with root-relative URLs, and sitelo handles the rest — TypeScript, CSS imports, bundling, and minification.
Project layout
Pages and assets share src/. Folders like js/ and css/ are conventions, not requirements — sitelo cares about what your HTML references, not the folder names.
my-site/
src/
index.ht.js # page — returns HTML
css/
styles.css # linked from HTML → bundled
js/
main.js # linked from HTML → bundled
counter.ts # imported by main.js → bundled too
lib/
posts.js # only used in data() → never ships
public/
favicon.ico # copied as-isLink assets from HTML
Reference files with root-relative paths. A <script type="module"> or <link rel="stylesheet"> is what tells sitelo to include that file in the build:
export default () => `
<html lang="en">
<head>
<title>My site</title>
<link rel="stylesheet" href="/css/styles.css">
<script type="module" src="/js/main.js"></script>
</head>
<body>
<h1>Hello</h1>
<button id="count">0</button>
</body>
</html>
`import { html, head, title, link, script, body, h1, button } from 'javascript-to-html'
export default () =>
html({ lang: 'en' },
head(
title('My site'),
link({ rel: 'stylesheet', href: '/css/styles.css' }),
script({ type: 'module', src: '/js/main.js' }),
),
body(
h1('Hello'),
button({ id: 'count' }, '0'),
),
)export default function Home() {
return (
<html lang="en">
<head>
<title>My site</title>
<link rel="stylesheet" href="/css/styles.css" />
<script type="module" src="/js/main.js" />
</head>
<body>
<h1>Hello</h1>
<button id="count">0</button>
</body>
</html>
)
}import { createCounter } from './counter.ts'
const button = document.querySelector('#count')
const next = createCounter()
button.addEventListener('click', () => {
button.textContent = String(next())
})@import './tokens.css';
body {
font-family: system-ui, sans-serif;
margin: 0;
padding: 2rem;
}What Vite compiles
.js/.ts/.jsx/.tsx— bundled as ES modules, TypeScript stripped, imports inlined.css— processed and minified;@importand relativeurl()references are resolved- Anything imported from a referenced entry (like
counter.tsabove) is pulled into the same bundle - In
sitelo(dev), the same URLs go through Vite’s transform pipeline — no separate build step to try TypeScript or CSS
Need PostCSS, Sass, or other Vite plugins? Add them under vite in sitelo.config.js.
Zero JS by default
- Unreferenced code is not emitted. A helper only imported from
data()orgenerateStaticParamsstays out ofdist/— server-only secrets never ship by accident. - No
<script>on the page means no client JavaScript in the build. Static HTML and CSS are enough for most sites. public/is copied verbatim (favicons, robots.txt, static images you don’t want hashed).- Other referenced files (images, fonts, videos, …) are copied into
dist/.
Missing-asset validation
A <script src> or stylesheet href pointing at a file that exists in neither src/ nor public/ fails the build. Prefer a warning?
export default {
missingAssets: 'warn',
}