Subchapter 3.2
references/core-assets.mdMarkdown3 KBView on GitHub
Nitro handles two asset kinds: public assets served directly to clients, and server assets bundled into the server for programmatic access.
Files in public/ are served automatically at the matching URL.
public/
image.png -> /image.png
robots.txt -> /robots.txtETag / Last-Modified and 304 Not Modified support.public/ is copied to .output/public/ and a metadata manifest is embedded for fast lookups + caching headers.import { defineConfig } from "nitro";
export default defineConfig({
publicAssets: [
{
baseURL: "build", // served under /build/
dir: "public/build", // source on disk
maxAge: 3600, // Cache-Control: public, max-age=3600, immutable
},
],
});Other entry options: fallthrough (continue to handlers when not found; defaults true for root, false otherwise) and ignore.
Generate gzip/brotli/zstd variants at build time, served based on Accept-Encoding:
export default defineConfig({
compressPublicAssets: true, // or { gzip: true, brotli: true, zstd: false }
});Only compressible MIME types ≥ 1 KB are compressed (.map files excluded).
Files in assets/ are bundled into the server and read via the storage layer at the assets:server mount point (only included in the bundle when accessed through useStorage).
assets/
data.json
templates/welcome.htmlimport { defineHandler } from "nitro";
import { useStorage } from "nitro/storage";
export default defineHandler(async () => {
const serverAssets = useStorage("assets:server");
const keys = await serverAssets.getKeys();
const data = await serverAssets.getItem("data.json");
const meta = await serverAssets.getMeta("data.json"); // { type, etag, mtime }
return { keys, data, meta };
});import { defineConfig } from "nitro";
export default defineConfig({
serverAssets: [
{ baseName: "templates", dir: "./templates" },
],
});Access via the assets:templates mount:
const html = await useStorage("assets:templates").getItem("email.html");Entry options: baseName, dir, pattern (default **/*), ignore.
public/ → served to clients with ETag/compression; assets/ → bundled, read via useStorage("assets:server").useStorage.publicAssets[].maxAge and compressPublicAssets to offload caching/compression without a CDN.