Представьте: ваш медиаблог на Ghost тормозит при 5000 постах, страницы загружаются по 4 секунды, а Google считает LCP 4.2с. Типичная картина для тем, где Handlebars-шаблоны используют вложенные {{#get}} запросы без кэширования и не оптимизированы изображения. Мы решаем эту проблему переписыванием темы под Ghost 5 с кастомными настройками и правильным кэшированием.
В отличие от WordPress, Handlebars в Ghost не выполняет произвольный код, а только вызывает встроенные хелперы. Это плюс для безопасности, но минус для производительности, если не знать тонкостей. Наша команда с многолетним опытом разработки на Ghost (30+ проектов) создает темы, которые проходят gscan без предупреждений и набирают 90+ в Lighthouse. Расскажем, как это работает.
Проблемы, которые решаем
N+1 запросы через {{#get}}. Частая ошибка — получать данные для каждого поста отдельным запросом. Решение — использовать eager loading через параметр include в главном запросе, либо выносить данные в partials с мемоизацией.
Отсутствие адаптивных изображений. Без img_url с size и srcset тема грузит полные оригиналы: 3000px на мобильном. Это резко увеличивает LCP и CLS. Правильный подход — задать image_sizes в package.json и строить srcset для каждого изображения.
Пренебрежение кастомными настройками. Многие разработчики жёстко кодируют стили и функционал, которые редактор мог бы менять через Admin. Используем @custom в конфиге — это даёт контроль редактору без деплоя.
Как Handlebars влияет на производительность Ghost?
Handlebars позволяет создавать безопасные шаблоны без риска RCE, свойственного PHP-движкам. Ghost в версии 5.0+ стабильно поддерживает все хелперы для построения сложных интерфейсов: от пейджинга до Members. По сравнению с Nunjucks, Handlebars — родной язык, который даёт максимум контроля при минимуме возможностей для ошибки. Он в 2 раза быстрее, чем PHP-шаблонизаторы в WordPress, при равной нагрузке, благодаря отсутствию накладных расходов на выполнение кода.
Как мы это делаем: кейс оптимизации медиаблога
Клиент — медиа с 5000+ постов, тема на старом Bootstrap, LCP 4.2с, INP — 300ms. Задачи: сохранить дизайн, улучшить Core Web Vitals, добавить Members для премиум-контента.
Стек: Ghost 5.5, Handlebars, Node.js 18, Nginx, Cloudflare. Полностью переписали структуру шаблонов:
- Заменили вложенные
{{#get}}на один запрос сinclude=tags,authors. - Настроили
image_sizesс четырьмя вариантами и добавилиsizesатрибут. - Внедрили lazy loading для изображений ниже фолда.
- Использовали
@customдля выбора цветовой схемы и типа шапки.
Результат: LCP — 1.8с, CLS — 0.05, INP — 100ms. Сайт прошёл gscan без замечаний.
Почему стоит заказать кастомную тему Ghost?
Готовая тема не учитывает специфику контента и аудитории. Только кастомная разработка позволяет полностью контролировать вёрстку, настройки Members и производительность. Мы гарантируем gscan-валидацию и 30 дней поддержки после сдачи.
Процесс работы
- Аналитика: аудит текущей темы, замер метрик, выявление узких мест.
- Проектирование: создание макета структуры partials, схемы кастомных настроек, прототипирование Members-потоков.
- Реализация: написание всех hbs-шаблонов, стилизация, конфигурация
package.json, интеграция с Ghost API. - Тестирование: валидация gscan, проверка на всех устройствах, профилирование Lighthouse.
- Деплой: загрузка через Admin или CI/CD, настройка кэширования на Nginx и Cloudflare, мониторинг метрик.
Сроки ориентировочно
| Тип темы | Время |
|---|---|
| Минимальная рабочая тема | 2–3 дня |
| Полноценная (index, post, tag, author) | 5–8 дней |
| С Members и кастомными настройками | 8–12 дней |
| С Newsletter-шаблонами | +1–2 дня |
Стоимость рассчитывается индивидуально. Оценим проект за 1 день.
Типичные ошибки в темах Ghost
| Ошибка | Решение |
|---|---|
Отсутствие error.hbs |
Создать обязательный файл |
Использование {{#each}} без post_class |
Всегда применять {{post_class}} |
Игнорирование card_assets |
Включить в package.json |
| Жёсткая разметка вместо адаптивной | Использовать img_url с srcset |
Забытые @custom настройки |
Вынести все параметры в package.json |
Что входит в работу
- Исходный код темы с комментариями
- Документация по кастомным настройкам
- Настройка Members и Newsletter
- Валидация gscan с нулевыми предупреждениями
- Бесплатная поддержка в течение 30 дней после сдачи
Как реализовать Members-ограничения в кастомной теме?
Добавьте в post.hbs блок проверки доступа. Ghost предоставляет контекст {{#if access}} для платного контента и {{#unless @member}} для гостей. Пример:
{{#post}}
{{#if access}}
<div class="premium-content">{{content}}</div>
{{else}}
<div class="paywall">
<h3>Эта статья для подписчиков</h3>
{{#unless @member}}
<a href="#/portal/signup">Подписаться</a>
{{/unless}}
</div>
{{/if}}
{{/post}}Для отображения планов используйте {{#get "tiers"}} и выводите название и цену.
Примеры шаблонов
Основные хелперы на примере index.hbs
{{! index.hbs — список постов}}
{{#foreach posts}}
<article class="post-card {{post_class}}">
{{#if feature_image}}
<figure>
<img
srcset="{{img_url feature_image size="s"}} 300w, {{img_url feature_image size="m"}} 600w, {{img_url feature_image size="l"}} 1000w"
sizes="(max-width: 768px) 100vw, 50vw"
src="{{img_url feature_image size="m"}}"
alt="{{title}} — кастомная тема Ghost"
/>
</figure>
{{/if}}
<div class="post-card-content">
<header>
{{#primary_tag}}
<a href="{{url}}" class="post-tag">{{name}}</a>
{{/primary_tag}}
<h2><a href="{{url}}">{{title}}</a></h2>
</header>
{{#if excerpt}}
<p>{{excerpt words="30"}}</p>
{{/if}}
<footer>
{{#primary_author}}
<img src="{{img_url profile_image size="xs"}}" alt="{{name}}">
<a href="{{url}}">{{name}}</a>
{{/primary_author}}
<time datetime="{{date format="YYYY-MM-DD"}}">
{{date format="DD MMM YYYY"}}
</time>
{{#if @custom.show_reading_time}}
<span>{{reading_time}}</span>
{{/if}}
</footer>
</div>
</article>
{{/foreach}}
{{pagination}}
Динамические данные через {{#get}}
{{! Последние посты по тегу}}
{{#get "posts" limit="5" filter="tag:javascript" order="published_at desc"}}
{{#foreach posts}}
<a href="{{url}}">{{title}}</a>
{{/foreach}}
{{/get}} Обязательные файлы темы
my-theme/
├── package.json
├── index.hbs
├── post.hbs
├── page.hbs
├── error.hbs
├── tag.hbs (опционально)
├── author.hbs (опционально)
├── partials/
│ ├── header.hbs
│ ├── footer.hbs
│ └── post-card.hbs
└── assets/
├── css/screen.css
└── js/main.js {
"name": "my-theme",
"description": "Custom Ghost theme",
"version": "1.0.0",
"engines": {
"ghost": ">=5.0.0",
"ghost-api": "v5"
},
"license": "MIT",
"config": {
"posts_per_page": 12,
"image_sizes": {
"xs": {
"width": 300
},
"s": {
"width": 600
},
"m": {
"width": 1200
},
"l": {
"width": 2000
}
},
"card_assets": true,
"custom": {
"header_style": {
"type": "select",
"options": ["Center", "Left", "Right"],
"default": "Center"
},
"show_reading_time": {
"type": "boolean",
"default": true
}
}
}
}Свяжитесь с нами для оценки проекта. Закажите разработку кастомной темы Ghost — гарантируем качественный код, проходящий gscan без ошибок. Получите консультацию по вашему проекту — мы оценим сложность и сроки за 1 день.







