Building static sites with Lume
Practical Lume 3 setup — init, plugins, _components, and named permissions
Lume is a Deno-first static site generator for documentation, blogs, and content sites. The build output is plain static files that any static host can serve. This very site is built with Lume 3, and the examples below come from its real _config.ts and deno.json.
Create a project
deno run -A https://lume.land/init.ts
cd my-site
deno task lume -s # dev server with watch and reload
deno task lume # build into _site/
The official recommendation is project-local setup rather than a global CLI: the init script generates a deno.json containing a lume task and a matching named permission profile. Upgrade with deno task lume upgrade. If a tutorial uses deno.land/x/lume/init.ts or asks you to deno install a global lume command, it predates the current setup — the domain is now lume.land.
Core concepts
Configuration lives in _config.ts: create the site, register plugins, declare shared data.
import lume from "lume/mod.ts";
import jsx from "lume/plugins/jsx.ts";
import mdx from "lume/plugins/mdx.ts";
import sitemap from "lume/plugins/sitemap.ts";
const site = lume({ location: new URL("https://example.com") });
site.use(jsx());
site.use(mdx());
site.use(sitemap({ query: "indexable=true", items: { lastmod: "=lastModified" } }));
site.copy("static", ".");
site.data("layout", "doc.tsx");
export default site;
- Plugins: Markdown, Vento, search, and pagination work out of the box; JSX, MDX, sitemap, feed, and others are registered on demand with
site.use(). _includes/: the layouts and template partials directory. Pages pick a layout via thelayoutfrontmatter key, or you can set a site-wide default withsite.data("layout", ...)._components/: reusable components available in every template through the globalcompvariable, and engine-agnostic — a component written in JSX can be used from Vento. The Callout at the bottom of this page is one such component.preprocessvsprocess:site.preprocess([".mdx"], ...)runs before rendering and is good for injecting data — this site uses it to setlocaleandlastModifiedon every page.site.process([".html"], ...)runs after rendering with access topage.documentfor DOM work — this site uses it to wrap tables in scroll containers and addrel="noreferrer"to external links.
Narrowing permissions
Lume needs to read source files, write _site/, and fetch dependencies over the network, so many tutorials reach for -A. Deno 2 named permission profiles let you narrow and pin the permissions instead. This site's deno.json is a complete example:
{
"tasks": {
"lume": "deno run -P=lume lume/cli.ts"
},
"permissions": {
"lume": {
"read": true,
"write": true,
"import": ["cdn.jsdelivr.net:443", "jsr.io:443", "deno.land:443"],
"net": ["cdn.jsdelivr.net:443", "jsr.io:443", "deno.land:443", "esm.sh:443"],
"env": true,
"run": true,
"ffi": true,
"sys": true
}
}
}
deno run -P=lume applies only the profile named lume and nothing else. To tighten further: restrict net/import to the hosts your dependencies actually come from (as above), narrow write from true to ["_site"], and narrow env to the variables the build really reads (e.g. ["SITE_URL"]). Then run deno task lume — Deno reports exactly which permission is missing if you went too far.
Build and deploy
deno task lume emits _site/, a fully static artifact: Nginx, object storage, Cloudflare Pages, and GitHub Pages all host it directly. The new Deno Deploy has first-class static site support and detects Lume projects automatically with no extra configuration. Note that Deploy Classic does not support static hosting — the older "serve files with Deno.serve" recipes only apply to Classic.
Lume or Fresh
Consistent with the decision table: if every page is knowable at build time (docs, blogs, marketing pages), pick Lume; if you need request-time rendering, database access, or interactive islands, pick Fresh. Both can ship near-zero client JavaScript — the difference is when the HTML is generated.
Official references: Lume installation, Processors, Components, Plugin list, and Deno Deploy framework support.