Appearance
Single-File HTML App
Self-contained HTML applications where all scripts, styles, and resources are either embedded or linked via CDN.
When to use
Use this approach when you need a self-contained HTML file that works without build tools or a dev server. Good for quick prototypes, demos, shareable standalone applications, and educational examples.
The pattern
Basic structure
A minimal single-file app includes a viewport meta tag, an inline <style> block for layout, and a <script> at the end of <body> for behavior:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
<title>My App</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
}
</style>
</head>
<body>
<h1>My App</h1>
<div id="app"></div>
<script>
document.getElementById("app").textContent = "Hello World";
</script>
</body>
</html>Example: With CDN dependencies
Add a <script> tag in <head> pointing at a versioned CDN URL to pull in a library. The library attaches to window and is available in any subsequent script:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Chart Demo</title>
<script
src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0"
></script>
</head>
<body>
<canvas id="chart"></canvas>
<script>
new Chart(document.getElementById("chart"), {
type: "bar",
data: {
labels: ["A", "B", "C"],
datasets: [{ data: [10, 20, 30] }],
},
});
</script>
</body>
</html>Example: With ES modules
Use <script type="module"> with an import statement pointing at esm.run to load an ES module build directly in the browser without a bundler:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>ES Module Demo</title>
</head>
<body>
<div id="app"></div>
<script type="module">
import { html, render } from "https://esm.run/lit-html";
const template = html`<h1>Hello from lit-html!</h1>`;
render(template, document.getElementById("app"));
</script>
</body>
</html>Trade-offs
Advantages:
- Zero setup, zero build tools
- Completely portable (email, share, deploy anywhere)
- Instant sharing and collaboration
Disadvantages:
- No code splitting or tree shaking
- No build/compile step, so you lose transpilation and build-time validation
- Harder to organize large applications