
Research
/Security News
Malicious Chrome and Firefox Extensions Steal Crypto Traders’ Session and Wallet Data
Malicious Chrome and Firefox extensions target Axiom Trade and Padre users, stealing session tokens and wallet data.
eleventy-plugin-components-bundler
Advanced tools
Eleventy plugin for component-based architecture with tree-shaken CSS/JS bundling
Early Development Notice: This plugin is under active development. The API may change before reaching v1.0.0. Please report issues and feedback on GitHub.
An Eleventy plugin that automatically discovers and bundles CSS and JavaScript files from component-based architectures using esbuild
debug package for troubleshootingnpm install eleventy-plugin-components-bundler
Add eleventy-plugin-components-bundler to your Eleventy configuration:
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents);
// Uses default paths:
// basePath: 'src/_includes/components/_partials' (buttons, cards, etc.)
// sectionsPath: 'src/_includes/components/sections' (hero, banner, etc.)
// layoutsPath: 'src/_includes/layouts' (for template scanning)
// cssDest: 'assets/main.css' (bundled output)
// jsDest: 'assets/main.js' (bundled output)
return {
dir: {
input: 'src',
output: '_site'
}
};
}
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents, {
basePath: 'src/_includes/components/_partials',
sectionsPath: 'src/_includes/components/sections',
cssDest: 'assets/bundle.css',
jsDest: 'assets/bundle.js'
});
return {
dir: {
input: 'src',
output: '_site'
}
};
}
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents, {
// Bundle main app files along with components
mainCSSEntry: 'src/assets/main.css',
mainJSEntry: 'src/assets/main.js',
// Component paths
basePath: 'src/_includes/components/_partials',
sectionsPath: 'src/_includes/components/sections'
});
return {
dir: {
input: 'src',
output: '_site'
}
};
}
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents, {
basePath: 'src/_includes/components/_partials',
sectionsPath: 'src/_includes/components/sections',
postcss: {
enabled: true,
plugins: [autoprefixer(), cssnano({ preset: 'default' })],
options: {
// Additional PostCSS options if needed
}
}
});
return {
dir: {
input: 'src',
output: '_site'
}
};
}
This configuration:
src/_includes directory structureThe resulting bundled CSS will be properly ordered by dependencies, prefixed for browser compatibility, and minified for production use.
| Option | Description | Type | Default |
|---|---|---|---|
basePath | Path to base/atomic components directory | String | 'src/_includes/components/_partials' |
sectionsPath | Path to section/composite components directory | String | 'src/_includes/components/sections' |
layoutsPath | Path to layouts directory for scanning template includes | String | 'src/_includes/layouts' |
cssDest | Destination path for bundled CSS | String | 'assets/main.css' |
jsDest | Destination path for bundled JavaScript | String | 'assets/main.js' |
mainCSSEntry | Main CSS entry point (design tokens, base styles) | String | null |
mainJSEntry | Main JS entry point (app initialization code) | String | null |
minifyOutput | Enable esbuild minification for production builds | Boolean | false |
postcss | PostCSS configuration (enabled, plugins, options) | Object | { enabled: false, plugins: [], options: {} } |
validation | Section validation configuration | Object | { enabled: true, strict: false, reportAllErrors: true } |
The plugin expects components to be organized in a specific structure:
src/
└─ _includes/
├─ components/
│ ├─ _partials/ # Atomic/base components
│ │ ├─ button/
│ │ │ ├─ button.njk
│ │ │ ├─ button.css
│ │ │ ├─ button.js
│ │ │ └─ manifest.json (optional)
│ │ └─ image/
│ │ ├─ image.njk
│ │ └─ image.css
│ └─ sections/ # Composite components
│ ├─ banner/
│ │ ├─ banner.njk
│ │ ├─ banner.css
│ │ ├─ banner.js
│ │ └─ manifest.json
│ └─ media/
│ ├─ media.njk
│ ├─ media.css
│ └─ manifest.json
└─ layouts/
├─ base.njk
└─ page.njk
Each component can include an optional manifest.json file:
{
"name": "banner",
"type": "section",
"description": "banner section with background image",
"styles": ["banner.css", "banner-responsive.css"],
"scripts": ["banner.js"],
"requires": ["button", "image"]
}
If no manifest file is present, the plugin will auto-generate one based on the component name:
<component-name>.css and <component-name>.js filesThe plugin automatically detects components used in your templates through:
{% include "components/sections/banner/banner.njk" %}
{% include "components/_partials/button/button.njk" %}
{% from "components/_partials/button/button.njk" import button %}
---
title: My Page
sections:
- sectionType: banner
title: Welcome
- sectionType: media
image: /images/hero.jpg
---
The plugin scans your templates, layouts, and frontmatter to build a complete dependency graph, ensuring only the CSS and JavaScript needed for each page is bundled.
The plugin includes validation capabilities to catch common configuration errors in your frontmatter/YAML that would otherwise result in "silent failures" - where the site builds successfully but renders incorrectly.
isAnimated: "false" (string) always evaluates to true in templatesbuttonStyle: "blue" when CSS only supports primary, secondary, ghosttitleTag: "header" instead of valid HTML heading tagsAdd a validation object to your component's manifest.json:
{
"name": "hero",
"type": "section",
"styles": ["hero.css"],
"scripts": [],
"requires": ["button", "image"],
"validation": {
"required": ["sectionType"],
"properties": {
"sectionType": {
"type": "string",
"const": "hero"
},
"isReverse": {
"type": "boolean"
},
"containerFields.isAnimated": {
"type": "boolean"
},
"containerFields.background.imageScreen": {
"type": "string",
"enum": ["light", "dark", "none"]
},
"text.titleTag": {
"type": "string",
"enum": ["h1", "h2", "h3", "h4", "h5", "h6"]
},
"ctas": {
"type": "array",
"items": {
"properties": {
"isButton": {
"type": "boolean"
},
"buttonStyle": {
"type": "string",
"enum": ["primary", "secondary", "ghost", "none"]
}
}
}
}
}
}
}
Type Validation: Ensure fields are actual booleans, strings, numbers, or arrays - not string representations.
Enum Validation: Restrict values to predefined options (e.g., titleTag: ["h1", "h2", "h3"]).
Nested Properties: Use dot notation for nested validation (containerFields.isAnimated).
Array Items: Validate properties within array elements.
Helpful Error Messages: Get error messages with file context and helpful tips.
Section Validation Errors:
Section 0 (hero) in src/index.md:
- containerFields.isAnimated: expected boolean, got string "false"
- text.titleTag: "header" is invalid. Must be one of: h1, h2, h3, h4, h5, h6
- ctas[0].buttonStyle: "blue" is invalid. Must be one of: primary, secondary, ghost, none
Tip: String "false" evaluates to true in templates. Use boolean false instead.
Configure validation behavior in plugin options:
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents, {
validation: {
enabled: true, // Enable/disable validation
strict: false, // Fail build on errors vs warnings only
reportAllErrors: true // Report all errors vs stop on first
}
});
return {
dir: {
input: 'src',
output: '_site'
}
};
}
The plugin uses the debug package for detailed logging, which is the same debugging mechanism Eleventy uses internally. Debug output is silent by default and can be enabled using the DEBUG environment variable.
# Just this plugin
DEBUG=Eleventy:bundled-components npx @11ty/eleventy
# All Eleventy debugging (including this plugin)
DEBUG=Eleventy* npx @11ty/eleventy
# Everything (very verbose)
DEBUG=* npx @11ty/eleventy
For cross-platform compatibility, use the cross-env package:
{
"scripts": {
"build": "npx @11ty/eleventy",
"build:debug": "cross-env DEBUG=Eleventy:bundled-components npx @11ty/eleventy"
}
}
When debug mode is enabled, you'll see detailed information about:
Eleventy:bundled-components Running with options: { basePath: '...', sectionsPath: '...', ... }
Eleventy:bundled-components Partials path: /project/src/_includes/components/_partials
Eleventy:bundled-components Sections path: /project/src/_includes/components/sections
Eleventy:bundled-components Found all partials: [ 'button', 'image', 'icon' ]
Eleventy:bundled-components Found all sections: [ 'banner', 'hero', 'media' ]
Eleventy:bundled-components Components used in templates: [ 'banner', 'hero' ]
Eleventy:bundled-components Components needed (including dependencies): [ 'banner', 'hero', 'button', 'image' ]
Eleventy:bundled-components Found 4 components to bundle
Eleventy:bundled-components Starting bundling process...
Eleventy:bundled-components Wrote CSS to assets/main.css (4523 bytes)
Eleventy:bundled-components Wrote JS to assets/main.js (1892 bytes)
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';
import postcssCustomMedia from 'postcss-custom-media';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents, {
postcss: {
enabled: true,
plugins: [postcssCustomMedia(), autoprefixer(), cssnano({ preset: 'default' })]
}
});
return {
dir: {
input: 'src',
output: '_site'
}
};
}
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
import postcssNested from 'postcss-nested';
import autoprefixer from 'autoprefixer';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents, {
postcss: {
enabled: true,
plugins: [postcssNested(), autoprefixer()]
}
});
return {
dir: {
input: 'src',
output: '_site'
}
};
}
The plugin provides CSS processing with automatic @import resolution:
minifyOutput: true, all CSS (main + components) is minified togetherYour main CSS file can use @import statements with the following supported directory structure:
/* main.css */
@import './styles/_design-tokens.css';
@import './styles/_base.css';
@import './_utilities.css'; /* Files in same directory */
/* Your main application styles */
body {
font-family: var(--font-primary);
line-height: var(--line-height);
}
Expected Directory Structure:
src/assets/
├── main.css /* Main CSS entry point */
├── _utilities.css /* CSS files in same directory */
└── styles/ /* Subdirectory for @imports */
├── _design-tokens.css
├── _base.css
└── _components.css
The plugin automatically:
When minifyOutput: true is set:
// eleventy.config.js
import bundledComponents from 'eleventy-plugin-components-bundler';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(bundledComponents, {
mainCSSEntry: 'src/assets/main.css',
minifyOutput: process.env.NODE_ENV === 'production'
});
return {
dir: {
input: 'src',
output: '_site'
}
};
}
Result: All CSS (main entry + imported files + component styles) is fully minified into a single optimized file.
npm test # Run all tests with coverage
npm run test:unit # Run unit tests only
npm run coverage # Generate detailed coverage report
npm run lint # Lint and auto-fix code
npm run lint:check # Check linting without fixing
npm run format # Format code with Prettier
npm run format:check # Check formatting without fixing
npm run prerelease # Run lint, format, and tests (pre-release check)
This project uses ESLint and Prettier to maintain code quality:
prefer-const, no-var, strict equality, and complexity limitsRun npm run prerelease before committing to ensure your code passes all checks.
This plugin is tested using mocha with c8 for code coverage. Current coverage: 96%.
MIT
Portions of this project were developed with the assistance of AI tools including Claude and Claude Code. These tools were used to:
All AI-assisted code has been reviewed and tested to ensure it meets project standards. See the included CLAUDE.md file for more details.
FAQs
Eleventy plugin for component-based architecture with tree-shaken CSS/JS bundling
We found that eleventy-plugin-components-bundler demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Research
/Security News
Malicious Chrome and Firefox extensions target Axiom Trade and Padre users, stealing session tokens and wallet data.

Security News
GPT-6 Astra hits 100% on ExploitBench and finds zero-days autonomously, while independent tests reveal scope violations and monitoring gaps.

Product
Socket can now send alerts and supply chain attack notifications to Microsoft Teams, with filters that route the right updates to each channel.