{{ title }}
{% if description %}{{ description }}
{% endif %}--- name: eleventy description: Build content-focused websites with Eleventy (11ty). Use when creating templates (.njk, .liquid), working with data cascade, collections, or deploying static sites. allowed-tools: Read, Write, Edit, Bash, Glob, Grep --- # Eleventy (11ty) Skill Build fast, flexible static sites with Eleventy's zero-JS-by-default approach and powerful data cascade. ## Philosophy Alignment Eleventy perfectly matches progressive enhancement principles: | Principle | Eleventy Implementation | |-----------|------------------------| | HTML-first | Outputs pure static HTML | | Zero JS by default | No JavaScript unless you add it | | Template flexibility | Use any template language | | Data-driven | Powerful data cascade system | ## Project Structure ``` src/ ├── _includes/ # Layouts and partials │ ├── layouts/ │ │ └── base.njk │ └── partials/ │ └── header.njk ├── _data/ # Global data files │ ├── site.json # Site metadata │ └── navigation.js # Dynamic data ├── content/ # Content pages │ ├── index.njk # → / │ ├── about.njk # → /about/ │ └── blog/ │ ├── blog.json # Directory data │ └── post-1.md # → /blog/post-1/ ├── assets/ │ ├── css/ │ └── js/ └── eleventy.config.js # Configuration ``` ## Configuration ```javascript // eleventy.config.js export default function(eleventyConfig) { // Copy static assets eleventyConfig.addPassthroughCopy('src/assets'); // Watch for changes eleventyConfig.addWatchTarget('src/assets/css/'); // Add filters eleventyConfig.addFilter('dateFormat', (date, format) => { return new Intl.DateTimeFormat('en-US', { dateStyle: format || 'medium' }).format(date); }); // Add shortcodes eleventyConfig.addShortcode('year', () => `${new Date().getFullYear()}`); // Add collections eleventyConfig.addCollection('posts', (collectionApi) => { return collectionApi .getFilteredByGlob('src/content/blog/*.md') .filter(post => !post.data.draft) .sort((a, b) => b.date - a.date); }); return { dir: { input: 'src', output: '_site', includes: '_includes', data: '_data', }, markdownTemplateEngine: 'njk', htmlTemplateEngine: 'njk', }; } ``` ## Data Cascade Data flows from global to specific, with later values overriding earlier: ``` 1. Global Data (_data/*.json, _data/*.js) 2. Directory Data (blog/blog.json) 3. Template Front Matter 4. Computed Data ``` ### Global Data ```json // src/_data/site.json { "title": "My Website", "description": "A website built with Eleventy", "url": "https://example.com", "author": { "name": "Your Name", "email": "you@example.com" } } ``` ```javascript // src/_data/navigation.js export default [ { text: 'Home', url: '/' }, { text: 'About', url: '/about/' }, { text: 'Blog', url: '/blog/' }, ]; ``` ### Directory Data Apply data to all files in a directory: ```json // src/content/blog/blog.json { "layout": "layouts/post.njk", "tags": ["posts"], "permalink": "/blog/{{ page.fileSlug }}/" } ``` ### Front Matter ```yaml --- title: My Blog Post description: A description of this post date: 2024-01-15 tags: - javascript - tutorial draft: false --- ``` ## Template Languages ### Nunjucks (.njk) Primary recommended template language: ```nunjucks {# src/_includes/layouts/base.njk #}
No posts yet.
{% endif %} ``` ### Macros (Reusable Components) ```nunjucks {# src/_includes/macros/card.njk #} {% macro card(title, href, description) %}{{ description }}
{% endif %}{{ post.content | excerpt(150) }}
{% for post in collections.posts | limit(5) %} ... {% endfor %} ``` ## Shortcodes Reusable content snippets: ```javascript // eleventy.config.js // Simple shortcode eleventyConfig.addShortcode('year', () => `${new Date().getFullYear()}`); // Paired shortcode (with content) eleventyConfig.addPairedShortcode('callout', (content, type = 'info') => { return ``; }); // Async shortcode (for fetching data) eleventyConfig.addAsyncShortcode('image', async (src, alt) => { // Image optimization logic here return `Copyright {% year %}
{% callout "warning" %} This is a warning message. {% endcallout %} {% image "hero.jpg", "A descriptive alt text" %} ``` ## Permalinks Control output URLs: ```yaml --- # Static permalink permalink: /custom-url/ # Dynamic permalink permalink: /blog/{{ page.date | date: '%Y/%m' }}/{{ page.fileSlug }}/ # Disable output (data-only file) permalink: false # Multiple outputs (feeds) permalink: - /feed.xml - /feed.json --- ``` ## RSS Feed ```nunjucks {# src/feed.njk #} --- permalink: /feed.xml eleventyExcludeFromCollections: true ---