Get started Eleventy Blades base package
Base package bundles Eleventy Blades with other popular 11ty plugins, providing a ready-to-go reusable, zero-maintenance config:
npm install @anyblades/eleventy-blades-base
# Link base templates:
cd _includes/
ln -s ../node_modules/@anyblades/blades/_includes/blades
# Run Eleventy:
eleventy --config=node_modules/@anyblades/eleventy-blades-base/eleventy.config.js
Live examples:
If you don't want to type --config=... every time, symlink it once:
ln -s node_modules/@anyblades/eleventy-blades-base/eleventy.config.js
eleventy
Or save it in your package.json scripts:
"scripts": {
"build": "eleventy --config=node_modules/@anyblades/eleventy-blades-base/eleventy.config.js"
}
Alternatively, import it as a base config in your 11ty config:
import baseConfig from "@anyblades/eleventy-blades-base";
export default async function (eleventyConfig) {
await baseConfig(eleventyConfig);
}
You can toggle features/filters like this:
await baseConfig(eleventyConfig, {
plugins: {
"@anyblades/eleventy-blades": {
mdAutoRawTags: false,
filters: { attr_set: false },
},
},
});
Live examples:
B. Starter projects #
Eleventy Blades plugin and base package are included out-of-the-box with:
BA v46-in-1 Starter
- Modern, lightweight Eleventy v4 multi-site starter showcasing Eleventy Blades Kit and Tailwind CLI for: [1] Tailwind CSS + Typography [2] Blades CSS [3] Bootstrap CSS [4] Pico CSS [5] Simple CSS [6] Liquid Templates.
11ty v4Subtle
- The most subtle Eleventy v4 micro-starter for content-first sites. Powered by Eleventy Blades Kit
- Built-in bare-minimum examples
/anyblades/eleventy-blades/tree/main/examples
Appendix #
How it works
/anyblades/eleventy-blades/refs/heads/main/packages/eleventy-blades-base/eleventy.config.js :
/* Plugins (core > official > contrib) */
import { RenderPlugin } from "@11ty/eleventy";
import { feedPlugin } from "@11ty/eleventy-plugin-rss";
import eleventyNavigationPlugin from "@11ty/eleventy-navigation";
import eleventyBladesPlugin from "@anyblades/eleventy-blades";
import pluginTOC from "@uncenter/eleventy-plugin-toc";
import { siteData } from "@anyblades/eleventy-blades/features/siteData.js";
/* Libraries (A-Z) */
import markdownIt from "markdown-it";
import markdownItAnchor from "markdown-it-anchor";
import markdownItAttrs from "markdown-it-attrs";
import slugify from "@sindresorhus/slugify";
import YAML from "yaml";
/* System (A-Z) */
import fs from "node:fs";
import path from "node:path";
/**
* Eleventy Configuration
* @param {Object} eleventyConfig - The Eleventy configuration object
* @returns {Object} The Eleventy configuration object
*/
export default async function (eleventyConfig, pluginOptions = {}) {
/* Dirs */
const inputDir = eleventyConfig.directories.input;
const outputDir = eleventyConfig.directories.output;
const cwdIsDotEleventy = path.basename(process.cwd()) === ".11ty";
if (cwdIsDotEleventy) {
// Per https://www.11ty.dev/docs/config/#directory-for-includes
// Order matters, put this at the top of your configuration file.
// This is relative to your input directory!
eleventyConfig.setIncludesDirectory("./.11ty/_includes/");
}
/* Plugins */
eleventyConfig.addBundle("css", { bundleHtmlContentFromSelector: "style" }); // per https://www.11ty.dev/docs/plugins/bundle/#bundling-html-node-content
eleventyConfig.addTransform("inject-css-bundle", function (content) {
const isHtml = typeof this.page.outputPath === "string" && this.page.outputPath.endsWith(".html");
const css = isHtml && eleventyConfig.getFilter("getBundle").call(this, "css");
return css ? content.replace("</head>", `<style>${css}</style></head>`) : content;
});
eleventyConfig.addPlugin(RenderPlugin);
eleventyConfig.addPlugin(eleventyNavigationPlugin);
eleventyConfig.addPlugin(
eleventyBladesPlugin,
pluginOptions.plugins?.["@anyblades/eleventy-blades"] ?? { mdAutoRawTags: true },
);
eleventyConfig.addPlugin(pluginTOC, {
ignoredElements: [".header-anchor", "sub"],
ul: true,
wrapper: (toc) => `${toc}`,
});
// Feed plugin
eleventyConfig.addCollection("feed", (collectionApi) =>
collectionApi.getAll().filter((item) => item.data.date || item.data.revised),
);
eleventyConfig.addPlugin(feedPlugin, {
// per https://www.11ty.dev/docs/plugins/rss/#virtual-template
type: "atom", // or "rss", "json"
outputPath: "/feed.xml",
collection: {
name: "feed",
limit: 100, // 0 means no limit
},
templateData: {
eleventyComputed: {
metadata: (data) => {
return {
base: "https://example.com/", // sample/fallback value required by Feed plugin
...siteData(data),
};
},
},
},
});
/* Libraries */
let md = markdownIt({
html: true,
linkify: true,
})
.use(markdownItAnchor, {
slugify: slugify, // @TODO: TRICKS
permalink: markdownItAnchor.permalink.ariaHidden(),
})
.use(markdownItAttrs);
await import("markdown-it-deflist")
.then(({ default: markdownItDeflist }) => {
md.use(markdownItDeflist);
})
.catch(() => {
/* optional – skip if not installed */
});
eleventyConfig.setLibrary("md", md);
``````js
eleventyConfig.addFilter("markdownify", (content) => md.render(String(content ?? "")));
``````js
/* Data */
eleventyConfig.addDataExtension("yml,yaml", (contents) => YAML.parse(contents));
eleventyConfig.addGlobalData("layout", "default");
// Sitemap
eleventyConfig.addTemplate("sitemap.xml.njk", "", {
permalink: "/sitemap.xml",
layout: "blades/sitemap.xml.njk",
eleventyExcludeFromCollections: true,
});
/* Build */
eleventyConfig.addPassthroughCopy(
{
// From current working directory
_public: "./",
media: "./media/",
// Additionally from input dirs like `../` or `./site-1`
[`${inputDir}/_public/`]: "./",
[`${inputDir}/media/`]: "./media/",
},
{ expand: true }, // This follows/resolves symbolic links
);
/* Internal */
// Jekyll templates compatibility
eleventyConfig.addFilter("relative_url", (content) => content); // dummy
eleventyConfig.setLiquidOptions({
dynamicPartials: false, // allows unquoted Jekyll-style includes
root: [
eleventyConfig.directories.includes,
fs.realpathSync(path.resolve("./node_modules/@anyblades/blades/_includes")), // for symlinks to work after https://github.com/harttle/liquidjs/pull/870
],
});
// Dev tools
eleventyConfig.setChokidarConfig({ followSymlinks: true }); // follow symlinks in Chokidar used by 11ty to watch files
if (cwdIsDotEleventy) {
eleventyConfig.watchIgnores.add(`../.11ty/${outputDir}`); // !!! avoid circular watching
eleventyConfig.watchIgnores.add("../.11ty/node_modules/"); // avoid performance issues
}
}