Lume Static Site Generator for Deno

repository·main·Indexed Apr 15, 2026

https://github.com/lumeland/lume

Lume is a fast, simple, and flexible static site generator built for Deno. It allows developers to create static websites using multiple file formats (Markdown, YAML, JS, TS, JSX) and template engines (Vento, Nunjucks) without managing node_modules. Key features include a plugin architecture for asset transformation, a configurable rendering pipeline with renderOrder control, layout recursion, and support for draft pages via environment variables. It includes built-in plugins for code syntax highlighting with highlight.js and Decap CMS integration. Lume runs natively on Deno, leveraging its security model and offering a clean, secure build experience.

Tokens
25.7K
Snippets
82
Records
96
Agent score
81%

What's inside Lume

  1. Use the `vto` filter to render Vento strings

    main

    The vto filter allows you to render Vento template strings dynamically within your pages. This is useful for generating content from variables or data.

    Usage:

    {{ "{{ greeting }}" | vto { greeting: "Hello" } }}

    The filter accepts:

    • A string containing Vento template syntax.
    • An optional data object to pass to the template.

    The filter is automatically registered and available globally in all Vento templates.

    Sources: plugins/vento.ts

  2. Config: Site options

    main

    The SiteOptions interface defines the configuration for a Lume site. These options are passed when creating a Site instance or in the configuration file.

    Key options:

    • cwd: Current working directory.
    • src: Path to the site source.
    • dest: Path to the built destination.
    • emptyDest: Whether to empty the destination folder before building.
    • includes: Default includes path.
    • cssFile, jsFile: Default CSS and JS file names for components.
    • fontsFolder: Default folder for fonts.
    • location: Site location URL (used for generating URLs).
    • prettyUrls: Enable pretty URLs (e.g., /about-me/ instead of /about-me.html).
    • caseSensitiveUrls: Enable case-sensitive URL matching.
    • server: Server configuration (ServerOptions).
    • watcher: Watcher configuration (WatcherOptions).
    • components: Components configuration (ComponentsOptions).

    Sources: core/site.ts

  3. Installation

    main

    Import and register the plugin in your Lume configuration file:

    import lume from "lume/mod.ts";
    import codeHighlight from "lume/plugins/code_highlight.ts";
    
    const site = lume();
    
    site.use(codeHighlight());
  4. Configure esbuild options

    main

    Pass an options object to the esbuild() function to override default esbuild settings. These options map directly to the esbuild BuildOptions interface.

    Common Options

    import esbuild from "lume/plugins/esbuild.ts";
    
    const site = site({
      plugins: [
        esbuild({
          options: {
            // Bundle multiple files into one (default: true)
            bundle: true,
            
            // Output format: "iife", "cjs", "esm", "umd" (default: "esm")
            format: "esm",
            
            // Minify output (default: true)
            minify: true,
            
            // Keep function names (default: true)
            keepNames: true,
            
            // Platform: "browser", "node", "neutral" (default: "browser")
            platform: "browser",
            
            // Target browsers (default: modern browsers)
            target: ["es2020", "chrome80", "firefox70"],
            
            // Enable tree-shaking (default: true)
            treeShaking: true,
            
            // JSX mode: "automatic", "classic", "preserve" (default: "automatic")
            jsx: "automatic",
            
            // External modules (regex patterns)
            external: ["https://cdn.example.com/*", "node:fs"],
            
            // Path aliases
            alias: {
              "@components": "./src/components",
            },
          },
        }),
      ],
    });

    Source Maps Source maps are automatically generated if the source file has enableSourceMap set to true. They are saved as .map files alongside the bundled output.

    Sources: plugins/esbuild.ts

  5. Install and configure the SEO plugin

    main

    Use the seo plugin to validate and report on SEO best practices for your site's pages. The plugin checks title length, heading structure, meta descriptions, image alt text, and body content length.

    Installation No installation is required. The plugin is included with Lume.

    Configuration Import the plugin and pass an options object to customize validation rules and output behavior.

    import { SEO } from "https://deno.land/x/lume/plugins/seo.ts";
    
    const site = new Site();
    
    site.use(
      SEO({
        // Output options: false (silent), string (file path), or function
        output: false,
        
        // Filter pages to validate using a query string
        query: "type:post",
        
        // Override specific validation rules
        options: {
          title: {
            max: 60, // Maximum title length in graphemes
          },
          description: {
            min: 10, // Minimum description length in sentences
          },
          headingsOrder: true, // Enforce sequential heading levels
          duplicateTitles: true, // Flag pages with duplicate titles
          duplicateDescription: true, // Flag pages with duplicate descriptions
        },
      })
    );

    Default Validation Rules

    • Title: Max 80 graphemes, max 45 common words.
    • H1: Max 80 graphemes, max 45 common words.
    • Description: 1-2 sentences, max 55 common words.
    • Headings: Must be ordered sequentially.
    • Duplicate Titles/Descriptions: Flagged if found.
    • Image Alt: Min 2 characters, max 1500 characters.
    • Body: Min 1500 words, max 30000 words, max 42 common words.

    Output Behavior

    • Console: By default, errors are logged to the console during build.
    • File: Set output to a file path (e.g., "seo-report.json") to save a JSON report.
    • Custom Function: Set output to a function receiving a Map<string, ErrorMessage[]> to handle reports programmatically.
    • Debug Bar: Errors are automatically displayed in the Lume debug bar under the "SEO" collection with a magnifying glass icon.

    Sources: plugins/seo.ts

  6. Install and configure the Partytown plugin

    main

    The Partytown plugin moves heavy JavaScript to a web worker to improve page performance. It automatically copies the required Partytown library files and injects the necessary initialization script into every HTML page.

    To use it, import the plugin and pass it to your site configuration:

    import lume from "https://deno.land/x/lume@v2/lume.ts";
    import partytown from "https://deno.land/x/lume@v2/plugins/partytown.ts";
    
    const site = lume();
    
    site.use(partytown()); // Use default configuration
    // Or with custom options:
    // site.use(partytown({ options: { debug: true } }));
    
    export default site;
  7. Use built-in icon catalogs

    main

    Lume provides a set of pre-configured icon catalogs that can be used to fetch SVG icons from various popular icon libraries. These catalogs are defined in deps/icons.ts and include support for Bootstrap, Heroicons, Lucide, Material Symbols, Phosphor, Remix, Simple Icons, Tabler, and many others.

    To use an icon catalog, reference the catalog id in your configuration or code. The catalog defines the source URL pattern and available variants (styles, weights, or sizes).

    Available Catalog IDs:

    • bootstrap: Bootstrap Icons
    • heroicons: Heroicons (outline, solid, minimal, micro)
    • lucide: Lucide Icons
    • material-100 through material-700: Material Symbols (different weights)
    • material: Material Design Icons (filled, outlined, round, sharp, two-tone)
    • mingcute: Mingcute Icons
    • phosphor: Phosphor Icons (regular, bold, duotone, fill, light, thin)
    • remix: Remix Icons
    • simpleicons: Simple Icons
    • tabler: Tabler Icons (filled, outline)
    • myna: Myna UI Icons (regular, solid)
    • iconoir: Iconoir Icons (regular, solid)
    • sargam: Sargam Icons (duotone, fill, line)
    • boxicons: Boxicons (regular, solid, logos)
    • ant: Ant Design Icons (filled, outlined, twotone)
    • fluent: Fluent UI Icons (outlined, filled, twotone)
    • octicons: Octicons (24, 16, 12, 48, 96)
    • openmoji: OpenMoji (color, black)
    • feather: Feather Icons
    • fontawesome: Font Awesome (regular, solid, brands)
    • cssgg: CSS GG Icons
    • radix: Radix UI Icons
    • ionicons: Ionicons (outline, filled, sharp)

    Example Usage: When configuring a page or component to use icons, specify the catalog ID and the icon name. For catalogs with variants, you can also specify the variant ID.

    // Example configuration for a page using Heroicons
    const page = site.get("/my-page")
      .data({
        icon: {
          catalog: "heroicons",
          name: "home",
          variant: "solid", // optional: outline, solid, minimal, micro
        },
      });

    The system will resolve the icon URL based on the catalog definition. For example, heroicons with solid variant and home name resolves to: https://cdn.jsdelivr.net/npm/heroicons@2.2.0/24/solid/home.svg

    Customizing Icon Names: Some catalogs (like phosphor and remix) have custom name transformation functions. The phosphor catalog automatically appends the variant suffix (e.g., home-bold for bold variant) if the variant is not regular. The remix catalog capitalizes the first letter of the icon name.

    Sources: deps/icons.ts

  8. Install and configure the redirects plugin

    main

    The redirects plugin allows you to define URL redirections in your content files using front matter. It supports multiple output formats including HTML, JSON, Netlify, and Vercel.

    Installation: Import the plugin in your configuration file:

    import lume from "lume/mod.ts";
    import redirects from "lume/plugins/redirects.ts";
    
    const site = lume();
    
    site.use(redirects({
      output: "netlify", // or "html", "json", "vercel"
      defaultStatus: 301,
    }));
    
    export default site;

    Configuration Options:

    • output: The output format. Can be a string ("html", "json", "netlify", "vercel") or a custom function.
    • defaultStatus: The default HTTP status code for redirects (default: 301). Valid codes are 301, 302, 307, 308.

    Usage in Content Files: Add oldUrl and url to your page's front matter. The oldUrl can be a single string or an array of strings.

    ---
    title: New Page
    url: /new-page/
    oldUrl: /old-page/
    ---

    Or for multiple old URLs:

    ---
    title: New Page
    url: /new-page/
    oldUrl:
      - /old-page-1/
      - /old-page-2/
    ---

    Output Formats:

    • html: Creates HTML pages with meta refresh tags for each redirect.
    • json: Generates a _redirects.json file compatible with redirect middleware.
    • netlify: Appends redirect rules to a _redirects file.
    • vercel: Updates vercel.json with redirect configurations.

    Custom Output Strategy: You can provide a custom function for the output option:

    site.use(redirects({
      output: (redirects, site) => {
        // Custom logic to handle redirects
        console.log(redirects);
      },
    }));
    import lume from "lume/mod.ts";
    import redirects from "lume/plugins/redirects.ts";
    
    const site = lume();
    
    site.use(redirects({
      output: "netlify",
      defaultStatus: 301,
    }));
    
    export default site;

    Sources: plugins/redirects.ts

  9. Basic Usage

    main

    Import the plugin and call it with optional configuration:

    import { defineConfig } from "lume";
    import validateHtml from "lume/plugins/validate_html.ts";
    
    export default defineConfig({
      plugins: [
        validateHtml(), // Uses default rules
      ],
    });
  10. Install and configure the minify_html plugin

    main

    Use the minify_html plugin to automatically minify HTML, CSS, and JavaScript files during the build process. This reduces file sizes for better performance.

    Installation Import the plugin in your configuration file:

    import { minifyHTML } from "https://deno.land/x/lume/plugins/minify_html.ts";
    
    export default function (site: Site) {
      site.use(minifyHTML());
    }

    Configuration Pass an options object to customize which file types are minified and how the underlying minify-html library behaves:

    site.use(minifyHTML({
      // File extensions to minify (default: [".html"])
      extensions: [".html", ".css", ".js"],
      
      // Options passed to the minify-html library
      options: {
        // Example: keep HTML opening tags
        keep_html_and_head_opening_tags: true,
        // Example: remove comments
        keep_comments: false,
      }
    }));

    Supported Extensions The plugin only supports .html, .css, and .js extensions. Passing any other extension will throw an error.

    Default Behavior By default, the plugin minifies only .html files. It automatically enables CSS minification if .css is in the extensions list and JavaScript minification if .js is included.

    import { minifyHTML } from "https://deno.land/x/lume/plugins/minify_html.ts";
    
    export default function (site: Site) {
      site.use(minifyHTML({
        extensions: [".html", ".css", ".js"],
        options: {
          keep_comments: false,
          remove_bangs: true,
        }
      }));
    }

    Sources: plugins/minify_html.ts

  11. Configure Decap CMS backend and collections

    main

    To enable content editing, you must define the decap_cms configuration in your site's root data. This configuration tells Decap CMS how to connect to your repository and which content collections to manage.

    Required Structure Place the configuration in your root data file (e.g., _data.json):

    {
      "decap_cms": {
        "backend": {
          "name": "git-gateway",
          "branch": "main"
        },
        "site_url": "{{site_url}}",
        "display_url": "{{site_url}}",
        "media_folder": "static/images",
        "public_folder": "/images",
        "collections": [
          {
            "name": "posts",
            "label": "Blog Posts",
            "folder": "_posts",
            "create": true,
            "fields": [
              { "name": "title", "label": "Title", "widget": "string" },
              { "name": "date", "label": "Date", "widget": "datetime" },
              { "name": "body", "label": "Body", "widget": "markdown" }
            ]
          }
        ]
      }
    }

    Key Configuration Fields:

    • backend.name: The authentication method (e.g., git-gateway, github).
    • media_folder: The folder where uploaded images are stored.
    • public_folder: The URL path where media is served.
    • collections: An array of content types. Each collection defines:
      • name: Internal identifier.
      • label: Human-readable name.
      • folder: The directory where content files are stored.
      • fields: The schema for the content editor.

    Automatic Variables: The plugin automatically injects site_url and local_backend into the generated config. Do not override these manually unless necessary.

    Netlify Identity: If using Netlify Identity, set identity: "netlify" in the plugin options. The plugin will automatically add the identity widget script and redirect users with invite/recovery tokens to the admin page.

    Sources: plugins/decap_cms.ts