Build awesome configuration¶
Customize the static site generator that builds your Silex websites.
Overview¶
Silex uses build awesome (powered by Eleventy) to compile website source files (from GrapesJS) into static HTML, CSS, and assets. The build awesome build process is triggered when a user publishes, running the .eleventy.js config file and any data files.
You can customize:
- Directory structure (input, output, includes)
- Plugins and filters
- Data files (.json, .js)
- Template languages
- Build transforms and passes
Prerequisites¶
- Basic build awesome knowledge (see build awesome docs)
- Understanding of publication transformers
- Familiarity with Node.js and npm
CMS configuration (EleventyPluginOptions)¶
The Silex CMS plugin exposes a configuration object that controls build awesome behavior:
interface EleventyPluginOptions {
enabled: boolean // Enable/disable 11ty build
enable11ty: boolean // Actually run 11ty (vs just passing files through)
cacheBuster: boolean // Add timestamps to asset URLs
dataSources: DataSource[] // GraphQL APIs for CMS
dir: {
input: string // Where website files come from
html: string // Where HTML files go (relative to input)
assets: string // Assets directory
css: string // CSS directory
}
urls: {
css: string // Public URL prefix for CSS
assets: string // Public URL prefix for assets
}
}
Configuring in client config¶
Set CMS options in your client config file:
// client-config.js
export default async function (config) {
config.cmsConfig = {
enabled: true,
enable11ty: true,
cacheBuster: false,
dataSources: [
{
id: 'wordpress',
type: 'graphql',
url: 'https://my-wordpress.com/graphql',
},
],
dir: {
input: '',
html: '',
assets: 'assets',
css: 'css',
},
urls: {
css: '/css',
assets: '/assets',
},
}
}
Directory structure¶
When published, Silex creates this structure:
.
├── .eleventy.js — 11ty config
├── .eleventyignore — Files to exclude
├── _data/ — Global data files
│ ├── site.json — Site settings
│ └── (CMS data) — From GraphQL APIs
├── css/ — Stylesheets
│ ├── page-name.css
│ └── global.css
├── assets/ — Images, fonts, etc.
│ ├── logo.png
│ └── hero.jpg
├── _includes/ — Reusable templates
│ └── page-layout.liquid
├── index.html — Home page
├── about.html — Other pages
└── blog/
├── index.html — Collection page
└── post-1.html — Generated pages
Customizing directories¶
Change where input comes from and where output goes:
// In your .eleventy.js
module.exports = function(eleventyConfig) {
return {
dir: {
input: 'content', // Input directory (default: '.')
output: '_site', // Output directory (default: '_site')
includes: '_layouts', // Includes directory
layouts: '_layouts', // Layouts directory
data: '_data_custom', // Data files directory
},
}
}
In Silex client config, the dir.input option affects relative paths:
Customizing the build¶
Create a .eleventy.js file in your published site's root to extend Silex's default config:
// .eleventy.js
module.exports = function(eleventyConfig) {
// Add custom filters
eleventyConfig.addFilter('uppercase', (value) => {
return value.toUpperCase()
})
// Add a plugin
const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight')
eleventyConfig.addPlugin(syntaxHighlight)
// Add a custom collection
eleventyConfig.addCollection('posts', (collection) => {
return collection.getFilteredByGlob('posts/*.md').sort((a, b) => {
return b.date - a.date
})
})
// Passthrough copy (don't process these files)
eleventyConfig.addPassthroughCopy('fonts/')
// Return config options
return {
pathPrefix: '/',
htmlTemplateEngine: 'liquid',
}
}
Data files¶
Create .json or .js files in _data/ to make data available to all templates:
// _data/site.json
{
"title": "My Website",
"description": "A great website",
"socialImage": "/assets/og-image.jpg"
}
In any HTML template:
Dynamic data files¶
Use .js files to fetch data at build time:
// _data/posts.js
module.exports = async () => {
const response = await fetch('https://api.example.com/posts')
return response.json()
}
Then use in templates:
CMS data¶
When Silex data sources are enabled, their data is available in _data/:
// Silex fetches from WordPress and makes it available
// _data/wordpress.json (generated)
{
"posts": [
{ "id": 1, "title": "First Post", "content": "..." },
{ "id": 2, "title": "Second Post", "content": "..." }
]
}
Use in templates:
{% for post in wordpress.posts %}
<article>
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
</article>
{% endfor %}
Plugins¶
Add build awesome plugins to extend functionality:
// .eleventy.js
const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight')
const image = require('@11ty/eleventy-img')
module.exports = function(eleventyConfig) {
// Add a plugin
eleventyConfig.addPlugin(syntaxHighlight)
// Add image optimization
eleventyConfig.addNunjucksAsyncShortcode('image', async (src, alt) => {
const metadata = await image(src, {
widths: [300, 600, 1200],
formats: ['webp', 'jpeg'],
outputDir: '_site/img/',
})
const imageMarkup = Object.values(metadata)
.map(imageFormat => imageFormat[imageFormat.length - 1])
.map(image => `<source srcset="${image.srcset}" type="${image.sourceType}">`)
.join('')
return `<picture>${imageMarkup}</picture>`
})
return {
dir: {
input: '.',
output: '_site',
},
}
}
Popular plugins:
| Plugin | Purpose |
|---|---|
| @11ty/eleventy-plugin-syntaxhighlight | Code highlighting with Prism |
| @11ty/eleventy-img | Image optimization and responsive pictures |
| @11ty/eleventy-plugin-rss | RSS feed generation |
| @11ty/eleventy-navigation | Navigation menu management |
| @11ty/eleventy-plugin-bundle | Asset bundling and inline optimization |
Shortcodes¶
Shortcodes are custom template tags. Define them in .eleventy.js:
eleventyConfig.addShortcode('year', () => {
return new Date().getFullYear()
})
eleventyConfig.addPairedShortcode('callout', (content, type = 'info') => {
return `<div class="callout callout-${type}">${content}</div>`
})
Use in templates:
<footer>
<p>Copyright © {% year %}</p>
</footer>
{% callout "warning" %}
This is important!
{% endcallout %}
In Silex, editors can insert shortcodes via a shortcode block.
Filters¶
Create custom filters for transforming data:
eleventyConfig.addFilter('readableDate', (dateObj) => {
return new Date(dateObj).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
})
eleventyConfig.addFilter('limit', (array, limit) => {
return array.slice(0, limit)
})
Use in templates:
<time>{{ date | readableDate }}</time>
{% for post in posts | limit(5) %}
<h2>{{ post.title }}</h2>
{% endfor %}
Collections¶
Create collections to group and sort content:
eleventyConfig.addCollection('posts', (collection) => {
return collection
.getFilteredByGlob('posts/**/*.html')
.sort((a, b) => b.date - a.date)
})
eleventyConfig.addCollection('recent', (collection) => {
const now = new Date()
return collection
.getAll()
.filter(item => item.date < now)
.reverse()
.slice(0, 5)
})
Use in templates:
Transforms and passes¶
Process the entire HTML output during the build:
// Minify HTML in production
if (process.env.NODE_ENV === 'production') {
eleventyConfig.addTransform('minify', (content) => {
if (!content.includes('<!doctype html>')) return content
const minifyHtml = require('minify-html')
return minifyHtml.minify(Buffer.from(content), {
do_not_minify_doctype: true,
minify_css: true,
minify_js: true,
}).toString()
})
}
Cache busting¶
Enable cache busting to append timestamps to asset URLs:
This rewrites:
Great for avoiding browser caching issues on updates.
Example: Full .eleventy.js¶
// .eleventy.js
const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight')
const image = require('@11ty/eleventy-img')
const { EleventyHtmlBasePlugin } = require('@11ty/eleventy')
module.exports = function(eleventyConfig) {
// Plugins
eleventyConfig.addPlugin(syntaxHighlight)
eleventyConfig.addPlugin(EleventyHtmlBasePlugin)
// Filters
eleventyConfig.addFilter('date', (dateObj) => {
return new Date(dateObj).toISOString().split('T')[0]
})
// Collections
eleventyConfig.addCollection('sortedPosts', (collection) => {
return collection
.getFilteredByGlob('posts/**/*.html')
.sort((a, b) => b.date - a.date)
})
// Shortcodes
eleventyConfig.addShortcode('year', () => new Date().getFullYear())
// Transforms
eleventyConfig.addTransform('minify', (content, outputPath) => {
if (outputPath && outputPath.endsWith('.html')) {
const minify = require('html-minifier')
return minify.minify(content, { useShortDoctype: true })
}
return content
})
// Passthrough
eleventyConfig.addPassthroughCopy('fonts/')
eleventyConfig.addPassthroughCopy('vendor/')
return {
dir: {
input: '.',
output: '_site',
includes: '_includes',
data: '_data',
},
htmlTemplateEngine: 'liquid',
pathPrefix: '/',
}
}
Troubleshooting¶
Build is too slow¶
Build awesome can be slow if: - Fetching data from external APIs on each build - Processing many large images - Complex filters or transforms
Optimize:
- Cache data files between builds
- Use a CDN for images instead of local processing
- Simplify filters or move logic to the client
Data not available in templates¶
Check:
- File is in _data/ directory
- Filename matches the variable name (e.g., site.json → {{ site }})
- No syntax errors in .js files
- Build awesome log shows "Writing X files"
Shortcodes not working¶
Ensure:
- Defined in .eleventy.js before returning config
- Used with correct syntax (paired vs unpaired)
- File is in the published site root (not in node_modules)
See also¶
- Build awesome official docs — Complete reference
- GitLab CI pipeline
- Publication hooks
- Client configuration and plugins — Client config for CMS
- Build Awesome Plugins — vote for easier integration of 11ty/build awesome plugins