Настройка и кастомизация темы Eleventy
Eleventy не имеет официального маркетплейса тем — основной источник это стартовые шаблоны (starters) от сообщества и официальных партнёров. В отличие от Hugo или Jekyll, «темы» в Eleventy — это полноценные проекты с зависимостями, которые форкаются и кастомизируются, а не подключаются как пакет. Это даёт больше свободы и требует понимания структуры чужого кода.
Популярные стартеры
| Стартер | Особенности |
|---|---|
eleventy-base-blog (официальный) |
Минимальный блог, Nunjucks |
11ty-webc-starter |
WebC компоненты, современный стек |
eleventy-excellent |
Полный набор: RSS, sitemap, OG, dark mode |
eleventy-duo |
Портфолио + блог |
slinkity |
React/Vue компоненты + Vite |
Клонирование стартера:
# Через degit (без git-истории)
npx degit 11ty/eleventy-base-blog mysite
cd mysite
npm install
npm start
Структура типичного стартера
eleventy-base-blog/
├── eleventy.config.js # Конфиг — точка входа для кастомизации
├── src/
│ ├── _includes/
│ │ └── layouts/
│ │ ├── base.njk
│ │ └── post.njk
│ ├── _data/
│ │ └── metadata.json # Заменить первым делом
│ ├── blog/
│ ├── css/ # Стили — редактировать напрямую
│ └── index.njk
├── package.json
└── .eleventy.js # Иногда оба файла конфига существуют
Первичная настройка: metadata и конфиг
// src/_data/metadata.json
{
"title": "Название сайта",
"url": "https://example.com",
"language": "ru",
"description": "Описание сайта для SEO",
"author": {
"name": "Имя автора",
"email": "[email protected]",
"url": "https://example.com/about/"
}
}
// eleventy.config.js — добавление кастомной логики
module.exports = function(eleventyConfig) {
// Базовые настройки стартера (не трогать)
// ...
// Ваши дополнения:
eleventyConfig.addFilter("ruDate", function(dateObj) {
return new Intl.DateTimeFormat("ru-RU", {
day: "numeric",
month: "long",
year: "numeric"
}).format(new Date(dateObj));
});
eleventyConfig.addFilter("limit", function(arr, limit) {
return arr.slice(0, limit);
});
// Дополнительные passthrough
eleventyConfig.addPassthroughCopy("src/uploads");
};
Кастомизация шаблонов Nunjucks
Принцип тот же, что в Hugo: находим нужный шаблон, редактируем напрямую (стартер — это копия, не пакет).
Добавление навигации в base.njk:
{# src/_includes/layouts/base.njk #}
<!DOCTYPE html>
<html lang="{{ metadata.language }}">
<head>
...
</html>
<body>
<header class="site-header">
<div class="container">
<a href="/" class="logo">
<img src="/assets/images/logo.svg" alt="{{ metadata.title }}">
</a>
<nav class="main-nav" aria-label="Основная навигация">
{% for item in navigation %}
<a href="{{ item.url }}"
{% if page.url == item.url %}aria-current="page"{% endif %}
class="nav-link">
{{ item.label }}
</a>
{% endfor %}
</nav>
</div>
</header>
...
// src/_data/navigation.json
[
{ "label": "Главная", "url": "/" },
{ "label": "Услуги", "url": "/services/" },
{ "label": "Блог", "url": "/blog/" },
{ "label": "Контакты", "url": "/contact/" }
]
Кастомизация CSS
Стартеры используют разные подходы к стилям: vanilla CSS custom properties, SASS, Tailwind. Типичная кастомизация через CSS variables:
/* src/css/custom.css — добавить после imports стартера */
:root {
/* Переопределение переменных темы */
--color-primary: #2563eb;
--color-primary-dark: #1e40af;
--color-text: #1e293b;
--color-bg: #ffffff;
--color-bg-muted: #f8fafc;
--font-sans: "Inter", system-ui, sans-serif;
--font-mono: "JetBrains Mono", "Fira Code", monospace;
--radius: 8px;
--shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--container-max: 1280px;
}
/* Тёмная тема */
@media (prefers-color-scheme: dark) {
:root {
--color-text: #e2e8f0;
--color-bg: #0f172a;
--color-bg-muted: #1e293b;
}
}
Если стартер использует Tailwind, кастомизация через tailwind.config.js:
module.exports = {
content: ["./src/**/*.{njk,md,js,html}"],
theme: {
extend: {
colors: {
primary: { 500: '#2563eb', 600: '#1d4ed8' },
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
},
},
};
Добавление новых секций и компонентов
{# src/_includes/components/features.njk #}
{% set features = features or [] %}
<section class="features">
<div class="container">
{% if featuresTitle %}
<h2 class="section-title">{{ featuresTitle }}</h2>
{% endif %}
<div class="features-grid">
{% for feature in features %}
<div class="feature-card">
{% if feature.icon %}
<div class="feature-icon">{{ feature.icon | safe }}</div>
{% endif %}
<h3>{{ feature.name }}</h3>
<p>{{ feature.description }}</p>
</div>
{% endfor %}
</div>
</div>
</section>
Использование на странице:
---
layout: layouts/base.njk
title: О компании
featuresTitle: Наши преимущества
features:
- name: "Опыт"
icon: "<svg>...</svg>"
description: "10 лет разработки"
- name: "Команда"
icon: "<svg>...</svg>"
description: "25 специалистов"
---
Добавление RSS и Sitemap
Если стартер не включает:
npm install @11ty/eleventy-plugin-rss
// eleventy.config.js
const pluginRss = require("@11ty/eleventy-plugin-rss");
eleventyConfig.addPlugin(pluginRss);
{# src/feed.njk #}
---
permalink: /feed.xml
eleventyExcludeFromCollections: true
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>{{ metadata.title }}</title>
<link href="{{ metadata.url }}/feed.xml" rel="self"/>
<updated>{{ collections.blog | getNewestCollectionItemDate | dateToRfc3339 }}</updated>
{% for post in collections.blog | reverse | limit(10) %}
<entry>
<title>{{ post.data.title }}</title>
<link href="{{ metadata.url }}{{ post.url }}"/>
<updated>{{ post.date | dateToRfc3339 }}</updated>
<content type="html">{{ post.templateContent | htmlToAbsoluteUrls(metadata.url) }}</content>
</entry>
{% endfor %}
</feed>
Сроки
Первичная настройка стартера (metadata, навигация, цвета, шрифты) — 1–2 дня. Глубокая кастомизация шаблонов, добавление компонентов, кастомная страница тегов, RSS — 3–6 дней.







