# Frontends & Static Sites

## Example generated code

src/index.ts:

```ts
import { readFile } from "node:fs/promises";
import { Hono } from "hono";

const contentTypes: Record<string, string> = {
	".html": "text/html; charset=utf-8",
	".css": "text/css; charset=utf-8",
	".js": "text/javascript; charset=utf-8",
};

const app = new Hono();

// Serve every file under public/. "/" maps to public/index.html. The build
// bundles this entrypoint next to public/, so paths resolve from the bundle.
app.get("/*", async (c) => {
	const path = c.req.path.endsWith("/")
		? `${c.req.path}index.html`
		: c.req.path;
	const type = contentTypes[path.slice(path.lastIndexOf("."))];
	if (!type || path.includes("..")) return c.notFound();
	try {
		const file = await readFile(new URL(`./public${path}`, import.meta.url));
		return c.body(file, 200, { "content-type": type });
	} catch {
		return c.notFound();
	}
});

export default app;
```

public/index.html:

```html
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		<title>Static site on Dynamic Apps</title>
		<link rel="stylesheet" href="./styles.css" />
	</head>
	<body>
		<main>
			<h1>Static sites scale to zero too.</h1>
			<p id="status">Loading JavaScript…</p>
		</main>
		<script type="module" src="./app.js"></script>
	</body>
</html>
```

package.json:

```json
{
	"name": "static-website-app",
	"version": "0.0.0",
	"private": true,
	"type": "module",
	"main": "src/index.ts",
	"dependencies": {
		"hono": "4.13.5"
	}
}
```

## Deploy and route

Deploy the directory and open `/apps/static-website/`:

src/server.ts:

```ts
// Deploy the site directory. Its package.json and src/index.ts serve public/.
await deployApp({
	appId: "static-website",
	source: new URL("../fixtures/app/", import.meta.url),
});
```

Directories that contain only static files are rejected. Every app needs a
`package.json` and an entrypoint that default-exports a `fetch` handler.
