Eleventy (11ty)

repository·main·Indexed 12 days ago

https://github.com/11ty/eleventy

A lightweight, JavaScript-based static site generator that transforms diverse template formats—including HTML, Markdown, Liquid, Nunjucks, and JavaScript—into HTML. It features a flexible CLI for building, watching, and serving sites, as well as a programmatic Core API for custom integrations. Version 4.0.0-alpha.10 introduces updated watch and target methods and supports incremental builds to optimize performance.

Tokens
9.8K
Snippets
35
Records
51
Agent score
97%

What's inside Eleventy

  1. What is Eleventy?

    main

    Eleventy is a simple static site generator written in JavaScript. It transforms a directory of templates into HTML. It is designed as an alternative to Jekyll and supports a wide variety of template languages including:

    • HTML
    • Markdown
    • JavaScript
    • Liquid
    • Nunjucks

    It also supports various addons for technologies like WebC, Sass, Vue, Svelte, TypeScript, and JSX.

  2. Install Eleventy

    main

    You can install Eleventy using npm. The project supports both the new @awesome.me/buildawesome package name and the legacy @11ty/eleventy package name for backwards compatibility.

    To install for a development project, use the --save-dev flag.

    npm install @awesome.me/buildawesome --save-dev
    
    # Backwards compatible here too:
    npm install @11ty/eleventy --save-dev
  3. Understand Eleventy configuration file resolution

    main

    Eleventy searches for configuration files in a specific order to determine the project settings. If no configuration path is manually specified, it looks for:

    1. buildawesome.config.js (or other eligible JS paths via expandEligibleJavaScriptFilePaths)
    2. .eleventy.js
    3. eleventy.config.js (or other eligible JS paths via expandEligibleJavaScriptFilePaths)

    If a configuration file is manually specified via the API but cannot be found, Eleventy will throw a ConfigError.

  4. Output Destinations: fs vs json

    main

    The --to flag determines how Eleventy delivers the processed content:

    1. fs (Default): Writes the generated files to the file system at the location specified by --output. Note that using fs:templates will skip the passthrough copy step.
    2. json: Instead of writing files, Eleventy processes the content and outputs a JSON representation of the build to stdout.

    Note: The --to json mode is incompatible with --serve or --watch modes.

  5. How configuration resets work in watch mode

    main

    In watch mode, Eleventy monitors files to determine if a full configuration reset is required. A reset is triggered if:

    1. A local project configuration file (e.g., eleventy.config.js) is changed.
    2. A file matching the globs defined in userConfig.watchTargetsConfigReset is changed.
    3. A dependency of a configuration file is changed.

    When a reset is triggered, Eleventy emits the buildawesome.reset event, reloads the global configuration, and restarts the engine to ensure all new configuration settings are applied.

  6. Configure library amendments for a TemplateEngine

    main

    Eleventy allows you to modify a template engine's library instance after it has been loaded but before it is used. This is done via the libraryAmendments key in your configuration object.

    Amendments are functions that receive the engineLib as an argument. This is useful for adding custom filters, tags, or global variables to engines like Liquid or Nunjucks.

    Example configuration structure:

    // Inside your Eleventy configuration
    module.exports = function(eleventyConfig) {
      // The TemplateEngine will look for amendments under its specific name
      // e.g., if the engine name is 'liquid'
      eleventyConfig.addConfig({
        libraryAmendments: {
          liquid: [
            (engineLib) => {
              // Modify engineLib here
            }
          ]
        }
      });
    };
  7. How Eleventy merges configuration

    main

    Eleventy uses a multi-layered merging strategy to produce the final configuration object used during a build. The hierarchy (from lowest to highest priority) is:

    1. Default Config: The internal base configuration.
    2. Local Project Config: The object returned by your configuration file (e.g., .eleventy.js). This supports both a default export and a named config export.
    3. User Config API: Settings applied via the Eleventy configuration API (e.g., eleventyConfig.addPlugin(), eleventyConfig.setDirectories()).
    4. Overrides: High-priority overrides such as pathPrefix set via the CLI.

    Note on Configuration Formats: Eleventy supports two ways to define configuration in your local file:

    • Function Return: module.exports = function(eleventyConfig) { ... return { ... }; };
    • Named Export: export const config = { ... }; (if using ESM)

    If both are present, they are merged.

  8. Understand the TemplateEngine abstraction

    main

    The TemplateEngine class is an abstract base class used by Eleventy to interface with different templating libraries (like Liquid, Nunjucks, or Markdown). It provides a standardized way for Eleventy to interact with various engines, handling directory resolution, extension mapping, and library amendments.

    When implementing a custom engine, you must provide a compile() method. The engine uses the eleventyConfig to access directory settings and configuration details like libraryAmendments.

    Key behaviors:

    • Library Amendments: Eleventy allows you to run functions against an engine library via config.libraryAmendments[engineName]. These are executed when the engine library is set.
    • Compilation: The core task of an engine is to take a string and data and return a rendered string via compile().
    • Layouts: By default, engines are expected to work with Eleventy layouts (useLayouts() returns true).
  9. Watch JavaScript dependencies in Eleventy

    main

    Eleventy can watch JavaScript dependencies used within your templates and data files. This ensures that if a JS file imported by a template or global data file changes, the project rebuilds.

    To control this behavior, use:

    • eleventyConfig.setWatchJavaScriptDependencies(false) to disable watching JS dependencies (this can improve performance).
    • eleventyConfig.shouldSpiderJavaScriptDependencies() to check if the engine is currently configured to spider these dependencies.
  10. Implement a custom TemplateEngine

    main

    To create a new template engine for Eleventy, you should extend the TemplateEngine class. At a minimum, you must implement the async compile() method.

    Note that TemplateEngine is designed to be used internally by Eleventy's engine management system, typically initialized with a name and an eleventyConfig instance.

    // Conceptual implementation
    class MyCustomEngine extends TemplateEngine {
      async compile(str, data) {
        // Your logic to transform 'str' using 'data'
        return renderedString;
      }
    }
    /**
     * @abstract
     * @return {Promise}
     */
    async compile() {
    	throw new Error("compile() must be implemented by engine");
    }
  11. Install and use the RenderPlugin

    main

    The RenderPlugin allows you to render Eleventy template strings or files from within another template using shortcodes or filters. This is useful for nesting templates or rendering dynamic content blocks.

    Plugin Options

    When adding the plugin via $config.addPlugin(RenderPlugin, options), you can provide the following:

    • tagName (string): The name of the shortcode used to render a template string. Defaults to renderTemplate.
    • tagNameFile (string): The name of the shortcode used to render a template file. Defaults to renderFile.
    • filterName (string): The name of the async filter used to render template strings. Defaults to renderContent.
    • templateConfig (TemplateConfig): A configuration object.
    • accessGlobalData (boolean): If true, the rendered template will have access to the parent template's data cascade. Defaults to false.

    Usage Examples

    Rendering a String (Shortcode/Tag)

    If using Liquid or Nunjucks, you can use the tagName as a paired shortcode/tag:

    {% renderTemplate %}
    <p>This is dynamic content!</p>
    {% endrenderTemplate %}

    Rendering a File (Shortcode)

    Use the tagNameFile to render an existing file on disk:

    {% renderFile "path/to/template.njk", { key: "value" } %}
    // Example of adding the plugin in your .eleventy.js config
    module.exports = function(eleventyConfig) {
      eleventyConfig.addPlugin(RenderPlugin, {
        tagName: 'myCustomRender',
        accessGlobalData: true
      });
    };