122 KiB
Экспертный портал БИТ.WMS — План реализации
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Создать экспертный контентный портал по складской логистике на WordPress с фокусом на лидогенерацию для компании "Первый Бит".
Architecture: WordPress 6.x + GeneratePress Premium (дочерняя тема) + GenerateBlocks Pro. Контент управляется через CPT + ACF Pro. Фиксированная боковая навигация (как place.lemma.ru), строгое соответствие брендбуку "Первый Бит" (розовый/чёрный/белый, Suisse Int'l). Лидогенерация: формы Contact Form 7, JivoSite, callback, попапы, gated-контент.
Tech Stack: WordPress 6.x, GeneratePress Premium, GenerateBlocks Pro, ACF Pro, Contact Form 7, Popup Maker, Yoast SEO, PHP 8.x, MySQL, CSS3, vanilla JS.
Спецификация: docs/superpowers/specs/2026-04-03-bit-wms-site-design.md
Файловая структура проекта
wp-content/
├── themes/
│ └── bitwms-child/ # Дочерняя тема GeneratePress
│ ├── style.css # Мета + кастомные стили брендбука
│ ├── functions.php # Подключение модулей
│ ├── inc/
│ │ ├── cpt.php # Регистрация кастомных типов записей
│ │ ├── acf-fields.php # ACF-группы полей (экспорт PHP)
│ │ ├── ajax-filter.php # AJAX-фильтрация ленты на главной
│ │ └── enqueue.php # Подключение шрифтов, скриптов
│ ├── templates/
│ │ ├── sidebar-nav.php # Фиксированная боковая панель
│ │ ├── hero.php # Герой главной страницы
│ │ ├── content-card.php # Карточка контента (универсальная)
│ │ ├── section-filter.php # Блок фильтрации по рубрикам
│ │ ├── section-promo-wms.php # Промо-блок БИТ.WMS
│ │ ├── section-subscribe.php # Блок подписки на рассылку
│ │ └── section-clients.php # Блок "Наши клиенты"
│ ├── template-parts/
│ │ ├── single-case.php # Детальная страница кейса
│ │ ├── single-webinar.php # Детальная страница вебинара
│ │ ├── single-course.php # Детальная страница курса
│ │ ├── single-event.php # Детальная страница мероприятия
│ │ └── single-material.php # Детальная страница материала
│ ├── page-templates/
│ │ ├── front-page.php # Шаблон главной страницы
│ │ ├── page-bit-wms.php # Шаблон страницы БИТ.WMS
│ │ ├── page-contacts.php # Шаблон страницы контактов
│ │ └── page-anketa.php # Шаблон анкеты для детального запроса
│ ├── archive/
│ │ └── archive-cpt.php # Единый шаблон архива для CPT
│ ├── js/
│ │ ├── sidebar-nav.js # Логика боковой панели (hover, мобильные)
│ │ ├── ajax-filter.js # AJAX-фильтрация + "Показать ещё"
│ │ └── gated-content.js # Модальное окно gated-контента
│ ├── fonts/
│ │ ├── SuisseIntl-Bold.woff2
│ │ └── SuisseIntl-Book.woff2
│ └── img/
│ ├── logo.svg # Логотип "первыйБит"
│ ├── logo-short.svg # Сокращённый логотип для боковой панели
│ └── icons/ # SVG-иконки для навигации
│ ├── warehouse.svg
│ ├── folder.svg
│ ├── document.svg
│ ├── camera.svg
│ ├── graduation.svg
│ ├── calendar.svg
│ ├── download.svg
│ ├── bell.svg
│ └── phone.svg
Task 1: Установка WordPress и базовая настройка
Контекст: Поднимаем локальную среду разработки, устанавливаем WordPress и необходимые плагины. Это фундамент для всей последующей работы.
Файлы:
-
Создать: конфигурация локальной среды (Local by Flywheel / Docker / MAMP)
-
Step 1: Установить WordPress локально
Используем Local by Flywheel (рекомендуется для простоты) или Docker. Создаём сайт:
- Имя сайта:
bitwms-local - PHP: 8.2
- Web Server: nginx
- MySQL: 8.0
# Если используем wp-cli с уже установленным WordPress:
wp core download --locale=ru_RU
wp config create --dbname=bitwms --dbuser=root --dbpass=root --locale=ru_RU
wp db create
wp core install --url="http://bitwms.local" --title="БИТ.WMS — Экспертный портал" --admin_user=admin --admin_password=admin --admin_email=admin@bitwms.local
- Step 2: Установить и активировать обязательные плагины
# Премиум-плагины устанавливаются вручную (загрузка zip через админку):
# - GeneratePress Premium (лицензия)
# - GenerateBlocks Pro (лицензия)
# - ACF Pro (лицензия)
# Бесплатные плагины через wp-cli:
wp plugin install generatepress --activate
wp plugin install contact-form-7 --activate
wp plugin install popup-maker --activate
wp plugin install wordpress-seo --activate
# Удалить дефолтные плагины:
wp plugin delete akismet hello
- Step 3: Базовые настройки WordPress
# Постоянные ссылки: /%postname%/
wp rewrite structure '/%postname%/'
# Часовой пояс, формат дат
wp option update timezone_string 'Asia/Yekaterinburg'
wp option update date_format 'd.m.Y'
wp option update time_format 'H:i'
# Отключить комментарии
wp option update default_comment_status 'closed'
wp option update default_ping_status 'closed'
# Удалить дефолтный контент
wp post delete 1 --force
wp post delete 2 --force
wp post delete 3 --force
# Настройки чтения: статическая главная страница
wp post create --post_type=page --post_title='Главная' --post_status=publish
wp post create --post_type=page --post_title='Блог' --post_status=publish
wp option update show_on_front 'page'
wp option update page_on_front $(wp post list --post_type=page --name=главная --field=ID)
wp option update page_for_posts $(wp post list --post_type=page --name=блог --field=ID)
- Step 4: Активировать GeneratePress Premium модули
В админке WordPress: Appearance > GeneratePress > активировать модули:
-
Typography
-
Colors
-
Spacing
-
Blog
-
Elements
-
WooCommerce (не нужен, оставить выкл.)
-
Menu Plus
-
Sections (не нужен при использовании GenerateBlocks)
-
Disable Elements
-
Copyright
-
Background Images
-
Step 5: Проверить что всё работает
Открыть http://bitwms.local — должен отобразиться чистый сайт GeneratePress с русской локалью, статической главной страницей.
- Step 6: Инициализировать git-репозиторий
cd /path/to/wordpress/wp-content
git init
cat > .gitignore << 'EOF'
# WordPress core — не трекаем
../../*.php
../../wp-admin/
../../wp-includes/
# Плагины — премиум устанавливаются отдельно
plugins/
# Загрузки
uploads/
# Системное
.DS_Store
Thumbs.db
*.log
# Трекаем только дочернюю тему
!themes/bitwms-child/
EOF
git add .
git commit -m "init: WordPress project structure"
Task 2: Дочерняя тема — создание и подключение шрифтов
Контекст: Создаём дочернюю тему GeneratePress с брендбуком "Первый Бит". Шрифт Suisse Int'l — коммерческий, файлы woff2 должны быть предоставлены (или временно используем Arial как fallback).
Файлы:
-
Создать:
wp-content/themes/bitwms-child/style.css -
Создать:
wp-content/themes/bitwms-child/functions.php -
Создать:
wp-content/themes/bitwms-child/inc/enqueue.php -
Step 1: Создать дочернюю тему
Создать файл wp-content/themes/bitwms-child/style.css:
/*
Theme Name: БИТ.WMS Portal
Theme URI: https://wms.ru
Description: Дочерняя тема GeneratePress для экспертного портала БИТ.WMS
Author: Первый Бит
Author URI: https://1bit.ru
Template: generatepress
Version: 1.0.0
Text Domain: bitwms
*/
/* ==========================================================================
Брендбук "Первый Бит" — CSS Custom Properties
========================================================================== */
:root {
/* Цвета */
--color-primary: #E50071; /* Розовый/маджента — Pantone 213 */
--color-black: #000000; /* Заголовки, текст */
--color-white: #FFFFFF; /* Основной фон */
--color-gray-light: #EBEBEB; /* Дополнительный */
--color-gray-text: #666666; /* Мета-текст */
/* Типографика */
--font-heading: 'Suisse Intl', Arial, sans-serif;
--font-body: 'Suisse Intl', Arial, sans-serif;
/* Лейаут */
--sidebar-width-collapsed: 70px;
--sidebar-width-expanded: 250px;
--content-max-width: 1200px;
--header-height: 60px;
}
/* ==========================================================================
@font-face — Suisse Int'l (файлы в fonts/)
Если шрифты недоступны, fallback на Arial (по брендбуку)
========================================================================== */
@font-face {
font-family: 'Suisse Intl';
src: url('./fonts/SuisseIntl-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Suisse Intl';
src: url('./fonts/SuisseIntl-Book.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
/* ==========================================================================
Глобальные стили
========================================================================== */
body {
font-family: var(--font-body);
font-weight: 400;
color: var(--color-black);
background-color: var(--color-white);
margin: 0;
padding: 0;
}
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-heading);
font-weight: 700;
color: var(--color-black);
line-height: 1.2;
}
h1 { font-size: 3rem; }
h2 { font-size: 2.25rem; }
h3 { font-size: 1.5rem; }
h4 { font-size: 1.25rem; }
a {
color: var(--color-primary);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* ==========================================================================
Кнопки
========================================================================== */
.btn {
display: inline-block;
padding: 12px 32px;
font-family: var(--font-heading);
font-weight: 700;
font-size: 1rem;
line-height: 1.5;
text-decoration: none;
border-radius: 0;
cursor: pointer;
transition: background-color 0.2s, color 0.2s;
border: 2px solid transparent;
}
.btn-primary {
background-color: var(--color-primary);
color: var(--color-white);
border-color: var(--color-primary);
}
.btn-primary:hover {
background-color: #C60060;
border-color: #C60060;
text-decoration: none;
color: var(--color-white);
}
.btn-outline {
background-color: transparent;
color: var(--color-black);
border-color: var(--color-black);
}
.btn-outline:hover {
background-color: var(--color-black);
color: var(--color-white);
text-decoration: none;
}
/* ==========================================================================
Утилиты
========================================================================== */
.container {
max-width: var(--content-max-width);
margin: 0 auto;
padding: 0 24px;
}
.badge {
display: inline-block;
padding: 4px 12px;
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
background-color: var(--color-gray-light);
color: var(--color-black);
}
- Step 2: Создать functions.php дочерней темы
Создать файл wp-content/themes/bitwms-child/functions.php:
<?php
/**
* БИТ.WMS Portal — дочерняя тема GeneratePress
*
* @package bitwms
*/
defined('ABSPATH') || exit;
// Подключение стилей родительской темы
add_action('wp_enqueue_scripts', function () {
wp_enqueue_style(
'generatepress-parent',
get_template_directory_uri() . '/style.css'
);
wp_enqueue_style(
'bitwms-child',
get_stylesheet_uri(),
['generatepress-parent'],
wp_get_theme()->get('Version')
);
});
// Подключение модулей
$bitwms_includes = [
'inc/enqueue.php',
];
foreach ($bitwms_includes as $file) {
$filepath = get_stylesheet_directory() . '/' . $file;
if (file_exists($filepath)) {
require_once $filepath;
}
}
- Step 3: Создать inc/enqueue.php
Создать файл wp-content/themes/bitwms-child/inc/enqueue.php:
<?php
/**
* Подключение скриптов и стилей
*
* @package bitwms
*/
defined('ABSPATH') || exit;
add_action('wp_enqueue_scripts', function () {
$theme_version = wp_get_theme()->get('Version');
$theme_uri = get_stylesheet_directory_uri();
// Боковая навигация
wp_enqueue_script(
'bitwms-sidebar-nav',
$theme_uri . '/js/sidebar-nav.js',
[],
$theme_version,
true
);
}, 20);
- Step 4: Создать placeholder для JS боковой навигации
Создать файл wp-content/themes/bitwms-child/js/sidebar-nav.js:
/**
* Боковая навигация — hover-раскрытие и мобильный гамбургер
*/
document.addEventListener('DOMContentLoaded', function () {
const sidebar = document.querySelector('.sidebar-nav');
const hamburger = document.querySelector('.hamburger-toggle');
const body = document.body;
if (!sidebar) return;
// Мобильное меню — toggle
if (hamburger) {
hamburger.addEventListener('click', function () {
sidebar.classList.toggle('sidebar-nav--open');
body.classList.toggle('sidebar-overlay');
});
}
// Закрытие по клику на оверлей
body.addEventListener('click', function (e) {
if (e.target === body && body.classList.contains('sidebar-overlay')) {
sidebar.classList.remove('sidebar-nav--open');
body.classList.remove('sidebar-overlay');
}
});
});
- Step 5: Подготовить директории для ассетов
cd wp-content/themes/bitwms-child
mkdir -p fonts img/icons js templates template-parts page-templates archive inc
Поместить шрифты Suisse Int'l (woff2) в fonts/. Если шрифты пока недоступны — тема будет использовать Arial как fallback (по брендбуку).
- Step 6: Активировать дочернюю тему и проверить
wp theme activate bitwms-child
Открыть http://bitwms.local — тема должна активироваться, стили брендбука (цвета, шрифты) должны применяться.
- Step 7: Коммит
git add themes/bitwms-child/
git commit -m "feat: create child theme with brandbook styles and fonts"
Task 3: Фиксированная боковая панель навигации
Контекст: Ключевой элемент лейаута — фиксированная боковая панель слева (как place.lemma.ru). В свёрнутом виде 70px с иконками, при наведении раскрывается до 250px с подписями. На мобильных — скрывается, появляется гамбургер.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/templates/sidebar-nav.php -
Модифицировать:
wp-content/themes/bitwms-child/style.css(добавить стили панели) -
Модифицировать:
wp-content/themes/bitwms-child/functions.php(подключить шаблон) -
Step 1: Создать SVG-иконки навигации
Создать директорию wp-content/themes/bitwms-child/img/icons/ и поместить туда SVG-файлы. Используем простые моноцветные иконки (чёрный, без теней и градиентов по брендбуку).
Минимальный набор SVG (можно взять из Lucide Icons или Heroicons и упростить до монохромных):
-
warehouse.svg— БИТ.WMS -
folder.svg— Кейсы -
document.svg— Статьи -
camera.svg— Вебинары -
graduation.svg— Курсы -
calendar.svg— Мероприятия -
download.svg— Материалы -
bell.svg— Новости -
phone.svg— Контакты -
telegram.svg— Telegram -
vk.svg— VK -
Step 2: Создать шаблон боковой панели
Создать файл wp-content/themes/bitwms-child/templates/sidebar-nav.php:
<?php
/**
* Фиксированная боковая панель навигации
*
* @package bitwms
*/
defined('ABSPATH') || exit;
$theme_uri = get_stylesheet_directory_uri();
$nav_items = [
[
'label' => 'БИТ.WMS',
'icon' => 'warehouse.svg',
'url' => '/bit-wms/',
],
[
'label' => 'Кейсы',
'icon' => 'folder.svg',
'url' => '/cases/',
],
[
'label' => 'Статьи',
'icon' => 'document.svg',
'url' => '/articles/',
],
[
'label' => 'Вебинары',
'icon' => 'camera.svg',
'url' => '/webinars/',
],
[
'label' => 'Курсы',
'icon' => 'graduation.svg',
'url' => '/courses/',
],
[
'label' => 'Мероприятия',
'icon' => 'calendar.svg',
'url' => '/events/',
],
[
'label' => 'Материалы',
'icon' => 'download.svg',
'url' => '/materials/',
],
[
'label' => 'Новости',
'icon' => 'bell.svg',
'url' => '/news/',
],
[
'label' => 'Контакты',
'icon' => 'phone.svg',
'url' => '/contacts/',
],
];
$current_path = wp_parse_url(get_permalink(), PHP_URL_PATH);
?>
<aside class="sidebar-nav" role="navigation" aria-label="Основная навигация">
<div class="sidebar-nav__logo">
<a href="<?php echo esc_url(home_url('/')); ?>">
<img src="<?php echo esc_url($theme_uri . '/img/logo-short.svg'); ?>"
alt="первыйБит"
class="sidebar-nav__logo-img" />
</a>
</div>
<nav class="sidebar-nav__menu">
<ul class="sidebar-nav__list">
<?php foreach ($nav_items as $item) :
$is_active = (strpos($current_path, $item['url']) === 0);
?>
<li class="sidebar-nav__item <?php echo $is_active ? 'sidebar-nav__item--active' : ''; ?>">
<a href="<?php echo esc_url(home_url($item['url'])); ?>"
class="sidebar-nav__link">
<span class="sidebar-nav__icon">
<img src="<?php echo esc_url($theme_uri . '/img/icons/' . $item['icon']); ?>"
alt="" aria-hidden="true" width="24" height="24" />
</span>
<span class="sidebar-nav__label"><?php echo esc_html($item['label']); ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
</nav>
<div class="sidebar-nav__social">
<a href="#" class="sidebar-nav__social-link" aria-label="Telegram">
<img src="<?php echo esc_url($theme_uri . '/img/icons/telegram.svg'); ?>"
alt="" width="20" height="20" />
</a>
<a href="#" class="sidebar-nav__social-link" aria-label="VK">
<img src="<?php echo esc_url($theme_uri . '/img/icons/vk.svg'); ?>"
alt="" width="20" height="20" />
</a>
</div>
</aside>
<!-- Мобильный гамбургер (виден только на <768px) -->
<button class="hamburger-toggle" aria-label="Открыть меню" aria-expanded="false">
<span class="hamburger-toggle__bar"></span>
<span class="hamburger-toggle__bar"></span>
<span class="hamburger-toggle__bar"></span>
</button>
- Step 3: Добавить CSS боковой панели
Добавить в конец wp-content/themes/bitwms-child/style.css:
/* ==========================================================================
Боковая панель навигации
========================================================================== */
.sidebar-nav {
position: fixed;
top: 0;
left: 0;
width: var(--sidebar-width-collapsed);
height: 100vh;
background-color: var(--color-white);
border-right: 1px solid var(--color-gray-light);
z-index: 1000;
display: flex;
flex-direction: column;
transition: width 0.25s ease;
overflow: hidden;
}
.sidebar-nav:hover {
width: var(--sidebar-width-expanded);
}
.sidebar-nav__logo {
padding: 16px;
display: flex;
align-items: center;
justify-content: center;
min-height: 60px;
border-bottom: 1px solid var(--color-gray-light);
}
.sidebar-nav__logo-img {
width: 36px;
height: auto;
}
.sidebar-nav__menu {
flex: 1;
overflow-y: auto;
padding: 16px 0;
}
.sidebar-nav__list {
list-style: none;
margin: 0;
padding: 0;
}
.sidebar-nav__item {
margin: 0;
}
.sidebar-nav__link {
display: flex;
align-items: center;
gap: 16px;
padding: 12px 23px;
color: var(--color-black);
text-decoration: none;
font-size: 0.875rem;
font-weight: 400;
white-space: nowrap;
transition: background-color 0.15s;
}
.sidebar-nav__link:hover {
background-color: var(--color-gray-light);
text-decoration: none;
color: var(--color-black);
}
.sidebar-nav__item--active .sidebar-nav__link {
color: var(--color-primary);
font-weight: 700;
}
.sidebar-nav__item--active .sidebar-nav__link img {
filter: brightness(0) saturate(100%) invert(12%) sepia(97%) saturate(5765%) hue-rotate(327deg) brightness(87%) contrast(107%);
}
.sidebar-nav__icon {
flex-shrink: 0;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.sidebar-nav__label {
opacity: 0;
transition: opacity 0.2s ease 0.05s;
}
.sidebar-nav:hover .sidebar-nav__label {
opacity: 1;
}
.sidebar-nav__social {
padding: 16px;
display: flex;
gap: 12px;
justify-content: center;
border-top: 1px solid var(--color-gray-light);
}
.sidebar-nav__social-link {
opacity: 0.6;
transition: opacity 0.15s;
}
.sidebar-nav__social-link:hover {
opacity: 1;
}
/* Сдвиг основного контента */
.site-content,
.site-header,
.site-footer {
margin-left: var(--sidebar-width-collapsed);
}
/* Гамбургер — скрыт на десктопе */
.hamburger-toggle {
display: none;
position: fixed;
top: 16px;
left: 16px;
z-index: 1001;
background: var(--color-white);
border: 1px solid var(--color-gray-light);
padding: 8px;
cursor: pointer;
flex-direction: column;
gap: 4px;
}
.hamburger-toggle__bar {
display: block;
width: 24px;
height: 2px;
background-color: var(--color-black);
transition: transform 0.2s;
}
/* ==========================================================================
Мобильные стили (< 768px)
========================================================================== */
@media (max-width: 767px) {
.sidebar-nav {
transform: translateX(-100%);
width: var(--sidebar-width-expanded);
}
.sidebar-nav--open {
transform: translateX(0);
}
.sidebar-nav--open .sidebar-nav__label {
opacity: 1;
}
.hamburger-toggle {
display: flex;
}
.site-content,
.site-header,
.site-footer {
margin-left: 0;
}
body.sidebar-overlay::after {
content: '';
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
z-index: 999;
}
}
- Step 4: Подключить боковую панель в тему
Добавить в wp-content/themes/bitwms-child/functions.php (перед закрывающим ?> или в конец):
// Вставка боковой панели после <body>
add_action('generate_before_header', function () {
get_template_part('templates/sidebar-nav');
});
- Step 5: Проверить боковую панель
Открыть http://bitwms.local:
-
На десктопе: боковая панель 70px слева с иконками, при наведении раскрывается до 250px с подписями
-
На мобильном (< 768px): панель скрыта, виден гамбургер, по клику панель выезжает с оверлеем
-
Основной контент сдвинут вправо на 70px
-
Step 6: Коммит
git add themes/bitwms-child/
git commit -m "feat: add fixed sidebar navigation with hover expand and mobile hamburger"
Task 4: Верхний хедер
Контекст: Тонкий хедер над основным контентом (правее боковой панели): логотип + слоган слева, телефон + CTA "Заказать демо" + поиск справа. Высота ~60px.
Файлы:
-
Модифицировать:
wp-content/themes/bitwms-child/style.css -
Модифицировать:
wp-content/themes/bitwms-child/functions.php -
Step 1: Настроить хедер через GeneratePress hooks
Добавить в wp-content/themes/bitwms-child/functions.php:
// Кастомный хедер
add_action('generate_before_header', function () {
// Боковая панель уже подключена выше
}, 5);
// Переопределяем содержимое хедера
add_filter('generate_header_items_order', function () {
return ['header-widget', 'site-branding', 'navigation'];
});
Через Customizer GeneratePress (Appearance > Customize > Layout > Header): выбрать лейаут хедера "inline with navigation" или настроить через Elements.
Альтернативно, создать кастомный хедер через GP Elements (Appearance > Elements > Header):
<div class="top-header">
<div class="top-header__left">
<a href="/" class="top-header__logo">
<img src="/wp-content/themes/bitwms-child/img/logo.svg" alt="первыйБит" height="30" />
</a>
<span class="top-header__tagline">Экспертный портал по складской логистике</span>
</div>
<div class="top-header__right">
<a href="tel:+73432000000" class="top-header__phone">+7 (343) 200-00-00</a>
<a href="#demo-form" class="btn btn-primary btn-sm" data-popup="demo">Заказать демо</a>
<button class="top-header__search" aria-label="Поиск">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>
</svg>
</button>
</div>
</div>
- Step 2: Добавить CSS хедера
Добавить в style.css:
/* ==========================================================================
Верхний хедер
========================================================================== */
.top-header {
display: flex;
align-items: center;
justify-content: space-between;
height: var(--header-height);
padding: 0 32px;
background-color: var(--color-white);
border-bottom: 1px solid var(--color-gray-light);
}
.top-header__left {
display: flex;
align-items: center;
gap: 16px;
}
.top-header__logo img {
height: 30px;
width: auto;
}
.top-header__tagline {
font-size: 0.875rem;
color: var(--color-gray-text);
}
.top-header__right {
display: flex;
align-items: center;
gap: 24px;
}
.top-header__phone {
font-weight: 700;
color: var(--color-black);
text-decoration: none;
font-size: 0.875rem;
}
.top-header__phone:hover {
color: var(--color-primary);
text-decoration: none;
}
.btn-sm {
padding: 8px 20px;
font-size: 0.875rem;
}
.top-header__search {
background: none;
border: none;
cursor: pointer;
color: var(--color-black);
padding: 4px;
}
.top-header__search:hover {
color: var(--color-primary);
}
@media (max-width: 767px) {
.top-header {
padding: 0 16px 0 56px; /* Отступ под гамбургер */
}
.top-header__tagline {
display: none;
}
.top-header__phone {
display: none;
}
}
- Step 3: Проверить хедер
Открыть http://bitwms.local:
-
Хедер 60px, прижат к верху, правее боковой панели
-
Логотип + слоган слева, телефон + "Заказать демо" + лупа справа
-
На мобильном: слоган и телефон скрыты
-
Step 4: Коммит
git add themes/bitwms-child/
git commit -m "feat: add top header with logo, phone and demo CTA"
Task 5: Регистрация кастомных типов записей (CPT)
Контекст: Регистрируем 5 кастомных типов записей: case, webinar, course, event, material. Статьи и Новости — стандартный post с рубриками.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/inc/cpt.php -
Модифицировать:
wp-content/themes/bitwms-child/functions.php(подключить файл) -
Step 1: Создать файл регистрации CPT
Создать файл wp-content/themes/bitwms-child/inc/cpt.php:
<?php
/**
* Регистрация кастомных типов записей
*
* @package bitwms
*/
defined('ABSPATH') || exit;
add_action('init', 'bitwms_register_post_types');
function bitwms_register_post_types(): void {
// Кейсы
register_post_type('case', [
'labels' => [
'name' => 'Кейсы',
'singular_name' => 'Кейс',
'add_new' => 'Добавить кейс',
'add_new_item' => 'Добавить новый кейс',
'edit_item' => 'Редактировать кейс',
'view_item' => 'Просмотреть кейс',
'all_items' => 'Все кейсы',
'search_items' => 'Найти кейс',
'not_found' => 'Кейсы не найдены',
'not_found_in_trash' => 'В корзине кейсов нет',
],
'public' => true,
'has_archive' => true,
'rewrite' => ['slug' => 'cases'],
'menu_icon' => 'dashicons-portfolio',
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
'show_in_rest' => true,
]);
// Вебинары
register_post_type('webinar', [
'labels' => [
'name' => 'Вебинары',
'singular_name' => 'Вебинар',
'add_new' => 'Добавить вебинар',
'add_new_item' => 'Добавить новый вебинар',
'edit_item' => 'Редактировать вебинар',
'view_item' => 'Просмотреть вебинар',
'all_items' => 'Все вебинары',
'search_items' => 'Найти вебинар',
'not_found' => 'Вебинары не найдены',
'not_found_in_trash' => 'В корзине вебинаров нет',
],
'public' => true,
'has_archive' => true,
'rewrite' => ['slug' => 'webinars'],
'menu_icon' => 'dashicons-video-alt3',
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
'show_in_rest' => true,
]);
// Курсы
register_post_type('course', [
'labels' => [
'name' => 'Курсы',
'singular_name' => 'Курс',
'add_new' => 'Добавить курс',
'add_new_item' => 'Добавить новый курс',
'edit_item' => 'Редактировать курс',
'view_item' => 'Просмотреть курс',
'all_items' => 'Все курсы',
'search_items' => 'Найти курс',
'not_found' => 'Курсы не найдены',
'not_found_in_trash' => 'В корзине курсов нет',
],
'public' => true,
'has_archive' => true,
'rewrite' => ['slug' => 'courses'],
'menu_icon' => 'dashicons-welcome-learn-more',
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
'show_in_rest' => true,
]);
// Мероприятия
register_post_type('event', [
'labels' => [
'name' => 'Мероприятия',
'singular_name' => 'Мероприятие',
'add_new' => 'Добавить мероприятие',
'add_new_item' => 'Добавить новое мероприятие',
'edit_item' => 'Редактировать мероприятие',
'view_item' => 'Просмотреть мероприятие',
'all_items' => 'Все мероприятия',
'search_items' => 'Найти мероприятие',
'not_found' => 'Мероприятия не найдены',
'not_found_in_trash' => 'В корзине мероприятий нет',
],
'public' => true,
'has_archive' => true,
'rewrite' => ['slug' => 'events'],
'menu_icon' => 'dashicons-calendar-alt',
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
'show_in_rest' => true,
]);
// Материалы
register_post_type('material', [
'labels' => [
'name' => 'Материалы',
'singular_name' => 'Материал',
'add_new' => 'Добавить материал',
'add_new_item' => 'Добавить новый материал',
'edit_item' => 'Редактировать материал',
'view_item' => 'Просмотреть материал',
'all_items' => 'Все материалы',
'search_items' => 'Найти материал',
'not_found' => 'Материалы не найдены',
'not_found_in_trash' => 'В корзине материалов нет',
],
'public' => true,
'has_archive' => true,
'rewrite' => ['slug' => 'materials'],
'menu_icon' => 'dashicons-download',
'supports' => ['title', 'thumbnail', 'excerpt'],
'show_in_rest' => true,
]);
// Таксономии: Отрасли (для кейсов)
register_taxonomy('industry', ['case'], [
'labels' => [
'name' => 'Отрасли',
'singular_name' => 'Отрасль',
'add_new_item' => 'Добавить отрасль',
],
'public' => true,
'hierarchical' => true,
'rewrite' => ['slug' => 'industry'],
'show_in_rest' => true,
]);
// Таксономии: Тип материала
register_taxonomy('material_type', ['material'], [
'labels' => [
'name' => 'Тип материала',
'singular_name' => 'Тип материала',
'add_new_item' => 'Добавить тип',
],
'public' => true,
'hierarchical' => true,
'rewrite' => ['slug' => 'material-type'],
'show_in_rest' => true,
]);
// Рубрики для Статей и Новостей (стандартный post)
// "Статьи" и "Новости" — рубрики, создаются в админке
}
- Step 2: Подключить CPT в functions.php
Добавить 'inc/cpt.php' в массив $bitwms_includes в functions.php:
$bitwms_includes = [
'inc/enqueue.php',
'inc/cpt.php',
];
- Step 3: Обновить permalink и проверить
wp rewrite flush
В админке WP: проверить что в меню появились разделы "Кейсы", "Вебинары", "Курсы", "Мероприятия", "Материалы".
Создать рубрики для стандартных постов:
wp term create category "Статьи" --slug=articles
wp term create category "Новости" --slug=news
- Step 4: Коммит
git add themes/bitwms-child/inc/cpt.php themes/bitwms-child/functions.php
git commit -m "feat: register custom post types (case, webinar, course, event, material)"
Task 6: ACF-поля для кастомных типов записей
Контекст: Настраиваем кастомные поля через ACF Pro для каждого CPT. Поля экспортируем в PHP для версионного контроля.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/inc/acf-fields.php -
Модифицировать:
wp-content/themes/bitwms-child/functions.php -
Step 1: Создать ACF-группы полей в PHP
Создать файл wp-content/themes/bitwms-child/inc/acf-fields.php:
<?php
/**
* ACF-группы полей для кастомных типов записей
*
* @package bitwms
*/
defined('ABSPATH') || exit;
if (!function_exists('acf_add_local_field_group')) {
return;
}
add_action('acf/init', 'bitwms_register_acf_fields');
function bitwms_register_acf_fields(): void {
// ===== Кейсы =====
acf_add_local_field_group([
'key' => 'group_case_fields',
'title' => 'Поля кейса',
'fields' => [
[
'key' => 'field_case_client',
'label' => 'Клиент',
'name' => 'case_client',
'type' => 'text',
'required' => 1,
],
[
'key' => 'field_case_industry',
'label' => 'Отрасль',
'name' => 'case_industry',
'type' => 'text',
],
[
'key' => 'field_case_task',
'label' => 'Задача',
'name' => 'case_task',
'type' => 'wysiwyg',
'toolbar' => 'basic',
],
[
'key' => 'field_case_solution',
'label' => 'Решение',
'name' => 'case_solution',
'type' => 'wysiwyg',
'toolbar' => 'basic',
],
[
'key' => 'field_case_result',
'label' => 'Результат',
'name' => 'case_result',
'type' => 'wysiwyg',
'toolbar' => 'basic',
],
[
'key' => 'field_case_quote',
'label' => 'Цитата клиента',
'name' => 'case_quote',
'type' => 'textarea',
'rows' => 3,
],
[
'key' => 'field_case_gallery',
'label' => 'Галерея',
'name' => 'case_gallery',
'type' => 'gallery',
'return_format' => 'array',
],
],
'location' => [
[['param' => 'post_type', 'operator' => '==', 'value' => 'case']],
],
]);
// ===== Вебинары =====
acf_add_local_field_group([
'key' => 'group_webinar_fields',
'title' => 'Поля вебинара',
'fields' => [
[
'key' => 'field_webinar_date',
'label' => 'Дата проведения',
'name' => 'webinar_date',
'type' => 'date_time_picker',
'display_format' => 'd.m.Y H:i',
'return_format' => 'Y-m-d H:i:s',
'required' => 1,
],
[
'key' => 'field_webinar_speaker',
'label' => 'Спикер',
'name' => 'webinar_speaker',
'type' => 'text',
],
[
'key' => 'field_webinar_status',
'label' => 'Статус',
'name' => 'webinar_status',
'type' => 'select',
'choices' => [
'upcoming' => 'Анонс',
'past' => 'Прошёл',
],
'default_value' => 'upcoming',
],
[
'key' => 'field_webinar_video',
'label' => 'Запись видео (URL)',
'name' => 'webinar_video',
'type' => 'url',
'conditional_logic' => [
[['field' => 'field_webinar_status', 'operator' => '==', 'value' => 'past']],
],
],
[
'key' => 'field_webinar_presentation',
'label' => 'Презентация (файл)',
'name' => 'webinar_presentation',
'type' => 'file',
'return_format' => 'url',
'conditional_logic' => [
[['field' => 'field_webinar_status', 'operator' => '==', 'value' => 'past']],
],
],
],
'location' => [
[['param' => 'post_type', 'operator' => '==', 'value' => 'webinar']],
],
]);
// ===== Курсы =====
acf_add_local_field_group([
'key' => 'group_course_fields',
'title' => 'Поля курса',
'fields' => [
[
'key' => 'field_course_program',
'label' => 'Программа курса',
'name' => 'course_program',
'type' => 'wysiwyg',
'toolbar' => 'full',
],
[
'key' => 'field_course_duration',
'label' => 'Длительность',
'name' => 'course_duration',
'type' => 'text',
'placeholder' => 'Например: 2 дня (16 часов)',
],
[
'key' => 'field_course_format',
'label' => 'Формат',
'name' => 'course_format',
'type' => 'select',
'choices' => [
'online' => 'Онлайн',
'offline' => 'Очно',
'mixed' => 'Смешанный',
],
],
[
'key' => 'field_course_price',
'label' => 'Стоимость',
'name' => 'course_price',
'type' => 'text',
'placeholder' => 'Например: 25 000 руб.',
],
],
'location' => [
[['param' => 'post_type', 'operator' => '==', 'value' => 'course']],
],
]);
// ===== Мероприятия =====
acf_add_local_field_group([
'key' => 'group_event_fields',
'title' => 'Поля мероприятия',
'fields' => [
[
'key' => 'field_event_date',
'label' => 'Дата проведения',
'name' => 'event_date',
'type' => 'date_time_picker',
'display_format' => 'd.m.Y H:i',
'return_format' => 'Y-m-d H:i:s',
'required' => 1,
],
[
'key' => 'field_event_location',
'label' => 'Место проведения',
'name' => 'event_location',
'type' => 'text',
],
[
'key' => 'field_event_format',
'label' => 'Формат',
'name' => 'event_format',
'type' => 'select',
'choices' => [
'online' => 'Онлайн',
'offline' => 'Очно',
'mixed' => 'Смешанный',
],
],
[
'key' => 'field_event_program',
'label' => 'Программа',
'name' => 'event_program',
'type' => 'wysiwyg',
'toolbar' => 'basic',
],
[
'key' => 'field_event_registration_url',
'label' => 'Ссылка на регистрацию',
'name' => 'event_registration_url',
'type' => 'url',
],
],
'location' => [
[['param' => 'post_type', 'operator' => '==', 'value' => 'event']],
],
]);
// ===== Материалы =====
acf_add_local_field_group([
'key' => 'group_material_fields',
'title' => 'Поля материала',
'fields' => [
[
'key' => 'field_material_file',
'label' => 'Файл',
'name' => 'material_file',
'type' => 'file',
'return_format' => 'array',
],
[
'key' => 'field_material_type',
'label' => 'Тип файла',
'name' => 'material_file_type',
'type' => 'select',
'choices' => [
'pdf' => 'PDF',
'video' => 'Видео',
'checklist' => 'Чек-лист',
'excel' => 'Excel',
'other' => 'Другое',
],
],
[
'key' => 'field_material_gated',
'label' => 'Gated-контент (скачивание за email)',
'name' => 'material_gated',
'type' => 'true_false',
'default_value' => 0,
'ui' => 1,
],
],
'location' => [
[['param' => 'post_type', 'operator' => '==', 'value' => 'material']],
],
]);
}
- Step 2: Подключить ACF-поля в functions.php
Добавить 'inc/acf-fields.php' в массив $bitwms_includes:
$bitwms_includes = [
'inc/enqueue.php',
'inc/cpt.php',
'inc/acf-fields.php',
];
- Step 3: Проверить поля в админке
В админке WP: открыть создание нового Кейса, Вебинара, Курса, Мероприятия, Материала — проверить что все ACF-поля отображаются корректно с нужными типами и условной логикой (например, "Запись видео" появляется только при статусе "Прошёл").
- Step 4: Коммит
git add themes/bitwms-child/inc/acf-fields.php themes/bitwms-child/functions.php
git commit -m "feat: add ACF field groups for all custom post types"
Task 7: Главная страница — шаблон и герой
Контекст: Шаблон главной страницы: герой + фильтр по рубрикам + лента контента + промо WMS + подписка + клиенты. Начинаем с героя.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/page-templates/front-page.php -
Создать:
wp-content/themes/bitwms-child/templates/hero.php -
Модифицировать:
wp-content/themes/bitwms-child/style.css -
Step 1: Создать шаблон главной страницы
Создать файл wp-content/themes/bitwms-child/page-templates/front-page.php:
<?php
/**
* Template Name: Главная страница
*
* @package bitwms
*/
defined('ABSPATH') || exit;
get_header();
?>
<main class="front-page">
<?php get_template_part('templates/hero'); ?>
<?php get_template_part('templates/section-filter'); ?>
<?php // Лента контента будет добавлена в Task 9 ?>
<?php get_template_part('templates/section-promo-wms'); ?>
<?php get_template_part('templates/section-subscribe'); ?>
<?php get_template_part('templates/section-clients'); ?>
</main>
<?php
get_footer();
- Step 2: Создать шаблон героя
Создать файл wp-content/themes/bitwms-child/templates/hero.php:
<?php
/**
* Герой главной страницы
*
* @package bitwms
*/
defined('ABSPATH') || exit;
?>
<section class="hero">
<div class="container">
<div class="hero__content">
<h1 class="hero__title">Всё о складской логистике и автоматизации склада</h1>
<p class="hero__subtitle">Экспертный портал от Первого Бита — кейсы, вебинары, курсы и материалы для руководителей складов</p>
<div class="hero__actions">
<a href="<?php echo esc_url(home_url('/bit-wms/#demo-form')); ?>" class="btn btn-primary">Заказать демо БИТ.WMS</a>
<a href="<?php echo esc_url(home_url('/cases/')); ?>" class="btn btn-outline">Смотреть кейсы</a>
</div>
</div>
<div class="hero__stats">
<div class="hero__stat">
<span class="hero__stat-number">200+</span>
<span class="hero__stat-label">проектов внедрения</span>
</div>
<div class="hero__stat">
<span class="hero__stat-number">15+</span>
<span class="hero__stat-label">лет опыта в WMS</span>
</div>
<div class="hero__stat">
<span class="hero__stat-number">50+</span>
<span class="hero__stat-label">экспертов в команде</span>
</div>
</div>
</div>
</section>
- Step 3: Добавить CSS героя
Добавить в style.css:
/* ==========================================================================
Герой главной страницы
========================================================================== */
.hero {
padding: 80px 0 60px;
}
.hero__title {
font-size: 3.5rem;
line-height: 1.1;
margin: 0 0 24px;
max-width: 700px;
}
.hero__subtitle {
font-size: 1.25rem;
line-height: 1.6;
color: var(--color-gray-text);
margin: 0 0 40px;
max-width: 600px;
}
.hero__actions {
display: flex;
gap: 16px;
margin-bottom: 60px;
}
.hero__stats {
display: flex;
gap: 48px;
}
.hero__stat {
display: flex;
flex-direction: column;
gap: 4px;
}
.hero__stat-number {
font-family: var(--font-heading);
font-weight: 700;
font-size: 2.5rem;
line-height: 1;
color: var(--color-primary);
}
.hero__stat-label {
font-size: 0.875rem;
color: var(--color-gray-text);
}
@media (max-width: 767px) {
.hero {
padding: 40px 0 32px;
}
.hero__title {
font-size: 2rem;
}
.hero__subtitle {
font-size: 1rem;
}
.hero__actions {
flex-direction: column;
margin-bottom: 40px;
}
.hero__stats {
flex-direction: column;
gap: 24px;
}
}
- Step 4: Назначить шаблон странице "Главная" в админке
В админке WP: Страницы > Главная > в блоке "Атрибуты страницы" выбрать шаблон "Главная страница".
Альтернативно — переименовать файл в front-page.php (без Template Name) и положить в корень дочерней темы, тогда WordPress подхватит его автоматически для статической главной.
- Step 5: Проверить главную
Открыть http://bitwms.local:
-
Герой с H1, подзаголовком, двумя кнопками, тремя KPI-цифрами
-
Типографика Suisse Int'l / Arial, цвета по брендбуку
-
Адаптивность на мобильном
-
Step 6: Коммит
git add themes/bitwms-child/
git commit -m "feat: add front page template with hero section"
Task 8: Главная — промо-блок WMS, подписка, клиенты
Контекст: Оставшиеся блоки главной страницы: промо БИТ.WMS, подписка на рассылку, логотипы клиентов.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/templates/section-promo-wms.php -
Создать:
wp-content/themes/bitwms-child/templates/section-subscribe.php -
Создать:
wp-content/themes/bitwms-child/templates/section-clients.php -
Модифицировать:
wp-content/themes/bitwms-child/style.css -
Step 1: Создать промо-блок БИТ.WMS
Создать файл wp-content/themes/bitwms-child/templates/section-promo-wms.php:
<?php
/**
* Промо-блок БИТ.WMS на главной
*
* @package bitwms
*/
defined('ABSPATH') || exit;
?>
<section class="promo-wms">
<div class="container">
<h2 class="promo-wms__title">БИТ.WMS — комплексное решение для вашего склада</h2>
<div class="promo-wms__grid">
<div class="promo-wms__item">
<span class="promo-wms__icon">⚡</span>
<h3>Быстрое внедрение</h3>
<p>Знаем бизнес-задачи склада, запускаем проект за недели, а не месяцы</p>
</div>
<div class="promo-wms__item">
<span class="promo-wms__icon">⚙</span>
<h3>Собственная разработка</h3>
<p>БИТ.WMS — продукт Первого Бита, гибко адаптируется под ваши процессы</p>
</div>
<div class="promo-wms__item">
<span class="promo-wms__icon">✓</span>
<h3>Проверено временем</h3>
<p>200+ проектов внедрения, 15+ лет экспертизы в складской логистике</p>
</div>
<div class="promo-wms__item">
<span class="promo-wms__icon">☆</span>
<h3>Прозрачные условия</h3>
<p>Открытая ценовая политика, понятные сроки и этапы</p>
</div>
</div>
<div class="promo-wms__actions">
<a href="<?php echo esc_url(home_url('/bit-wms/')); ?>" class="btn btn-primary">Подробнее о продукте</a>
<a href="<?php echo esc_url(home_url('/bit-wms/#demo-form')); ?>" class="btn btn-outline">Заказать демо</a>
</div>
</div>
</section>
- Step 2: Создать блок подписки
Создать файл wp-content/themes/bitwms-child/templates/section-subscribe.php:
<?php
/**
* Блок подписки на рассылку
*
* @package bitwms
*/
defined('ABSPATH') || exit;
?>
<section class="subscribe-section">
<div class="container">
<h2 class="subscribe-section__title">Получайте экспертные материалы по складской логистике на почту</h2>
<form class="subscribe-section__form" action="#" method="post">
<input type="email"
name="email"
class="subscribe-section__input"
placeholder="Ваш email"
required
aria-label="Email для подписки" />
<button type="submit" class="btn btn-primary">Подписаться</button>
</form>
<p class="subscribe-section__note">Нажимая кнопку, вы соглашаетесь с <a href="/privacy-policy/">политикой конфиденциальности</a></p>
</div>
</section>
- Step 3: Создать блок клиентов
Создать файл wp-content/themes/bitwms-child/templates/section-clients.php:
<?php
/**
* Блок "Наши клиенты"
*
* @package bitwms
*/
defined('ABSPATH') || exit;
// Логотипы клиентов можно управлять через ACF Options Page или хардкод
// Для MVP — placeholder-структура
$clients = [
['name' => 'Клиент 1', 'logo' => ''],
['name' => 'Клиент 2', 'logo' => ''],
['name' => 'Клиент 3', 'logo' => ''],
['name' => 'Клиент 4', 'logo' => ''],
['name' => 'Клиент 5', 'logo' => ''],
['name' => 'Клиент 6', 'logo' => ''],
];
?>
<section class="clients-section">
<div class="container">
<h2 class="clients-section__title">Нам доверяют</h2>
<div class="clients-section__grid">
<?php foreach ($clients as $client) : ?>
<div class="clients-section__item">
<?php if ($client['logo']) : ?>
<img src="<?php echo esc_url($client['logo']); ?>"
alt="<?php echo esc_attr($client['name']); ?>" />
<?php else : ?>
<span class="clients-section__placeholder"><?php echo esc_html($client['name']); ?></span>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
</section>
- Step 4: Добавить CSS для всех трёх блоков
Добавить в style.css:
/* ==========================================================================
Промо-блок БИТ.WMS
========================================================================== */
.promo-wms {
padding: 80px 0;
background-color: var(--color-gray-light);
}
.promo-wms__title {
margin: 0 0 48px;
}
.promo-wms__grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 32px;
margin-bottom: 48px;
}
.promo-wms__item h3 {
margin: 0 0 8px;
font-size: 1.25rem;
}
.promo-wms__item p {
margin: 0;
color: var(--color-gray-text);
line-height: 1.6;
}
.promo-wms__icon {
font-size: 2rem;
display: block;
margin-bottom: 12px;
}
.promo-wms__actions {
display: flex;
gap: 16px;
}
/* ==========================================================================
Подписка на рассылку
========================================================================== */
.subscribe-section {
padding: 80px 0;
}
.subscribe-section__title {
margin: 0 0 32px;
max-width: 600px;
}
.subscribe-section__form {
display: flex;
gap: 12px;
max-width: 500px;
margin-bottom: 12px;
}
.subscribe-section__input {
flex: 1;
padding: 12px 16px;
font-size: 1rem;
font-family: var(--font-body);
border: 2px solid var(--color-gray-light);
border-radius: 0;
background: var(--color-white);
}
.subscribe-section__input:focus {
outline: none;
border-color: var(--color-primary);
}
.subscribe-section__note {
font-size: 0.75rem;
color: var(--color-gray-text);
}
/* ==========================================================================
Наши клиенты
========================================================================== */
.clients-section {
padding: 60px 0 80px;
border-top: 1px solid var(--color-gray-light);
}
.clients-section__title {
margin: 0 0 32px;
}
.clients-section__grid {
display: flex;
flex-wrap: wrap;
gap: 32px;
align-items: center;
}
.clients-section__item img {
max-height: 40px;
width: auto;
filter: grayscale(100%);
opacity: 0.6;
transition: filter 0.2s, opacity 0.2s;
}
.clients-section__item img:hover {
filter: grayscale(0%);
opacity: 1;
}
.clients-section__placeholder {
display: inline-block;
padding: 12px 24px;
background: var(--color-gray-light);
font-size: 0.875rem;
color: var(--color-gray-text);
}
@media (max-width: 767px) {
.promo-wms__grid {
grid-template-columns: 1fr;
}
.promo-wms__actions {
flex-direction: column;
}
.subscribe-section__form {
flex-direction: column;
}
}
- Step 5: Проверить все блоки на главной
Открыть http://bitwms.local:
-
Промо-блок WMS с 4 преимуществами на сером фоне
-
Блок подписки с полем email
-
Блок клиентов с placeholder-ами
-
Step 6: Коммит
git add themes/bitwms-child/
git commit -m "feat: add promo WMS, subscribe, and clients sections to front page"
Task 9: Лента контента с AJAX-фильтрацией на главной
Контекст: Горизонтальная полоса тегов-фильтров + карточная сетка контента + "Показать ещё". Фильтрация через AJAX без перезагрузки.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/templates/section-filter.php -
Создать:
wp-content/themes/bitwms-child/templates/content-card.php -
Создать:
wp-content/themes/bitwms-child/inc/ajax-filter.php -
Создать:
wp-content/themes/bitwms-child/js/ajax-filter.js -
Модифицировать:
wp-content/themes/bitwms-child/functions.php -
Модифицировать:
wp-content/themes/bitwms-child/style.css -
Модифицировать:
wp-content/themes/bitwms-child/inc/enqueue.php -
Step 1: Создать шаблон фильтра
Создать файл wp-content/themes/bitwms-child/templates/section-filter.php:
<?php
/**
* Блок фильтрации по типам контента
*
* @package bitwms
*/
defined('ABSPATH') || exit;
$filters = [
['slug' => 'all', 'label' => 'Все'],
['slug' => 'post', 'label' => 'Статьи'],
['slug' => 'case', 'label' => 'Кейсы'],
['slug' => 'webinar', 'label' => 'Вебинары'],
['slug' => 'course', 'label' => 'Курсы'],
['slug' => 'event', 'label' => 'Мероприятия'],
['slug' => 'material', 'label' => 'Материалы'],
];
?>
<section class="content-feed">
<div class="container">
<div class="filter-bar" role="tablist">
<?php foreach ($filters as $filter) : ?>
<button class="filter-bar__btn <?php echo $filter['slug'] === 'all' ? 'filter-bar__btn--active' : ''; ?>"
data-filter="<?php echo esc_attr($filter['slug']); ?>"
role="tab"
aria-selected="<?php echo $filter['slug'] === 'all' ? 'true' : 'false'; ?>">
<?php echo esc_html($filter['label']); ?>
</button>
<?php endforeach; ?>
</div>
<div class="content-grid" id="content-grid">
<?php
// Начальная загрузка — последние 6 записей из всех CPT
$initial_query = new WP_Query([
'post_type' => ['post', 'case', 'webinar', 'course', 'event', 'material'],
'posts_per_page' => 6,
'orderby' => 'date',
'order' => 'DESC',
]);
if ($initial_query->have_posts()) :
while ($initial_query->have_posts()) :
$initial_query->the_post();
get_template_part('templates/content-card');
endwhile;
wp_reset_postdata();
endif;
?>
</div>
<?php if ($initial_query->found_posts > 6) : ?>
<div class="content-feed__more">
<button class="btn btn-outline" id="load-more-btn" data-page="1">Показать ещё</button>
</div>
<?php endif; ?>
</div>
</section>
- Step 2: Создать универсальную карточку контента
Создать файл wp-content/themes/bitwms-child/templates/content-card.php:
<?php
/**
* Универсальная карточка контента
*
* @package bitwms
*/
defined('ABSPATH') || exit;
$post_type = get_post_type();
$type_labels = [
'post' => 'Статья',
'case' => 'Кейс',
'webinar' => 'Вебинар',
'course' => 'Курс',
'event' => 'Мероприятие',
'material' => 'Материал',
];
$type_label = $type_labels[$post_type] ?? 'Запись';
// Для постов с рубрикой "Новости" — переопределяем метку
if ($post_type === 'post') {
$categories = get_the_category();
foreach ($categories as $cat) {
if ($cat->slug === 'news') {
$type_label = 'Новость';
break;
}
}
}
?>
<article class="content-card">
<a href="<?php the_permalink(); ?>" class="content-card__link">
<?php if (has_post_thumbnail()) : ?>
<div class="content-card__image">
<?php the_post_thumbnail('medium_large'); ?>
</div>
<?php else : ?>
<div class="content-card__image content-card__image--placeholder"></div>
<?php endif; ?>
<div class="content-card__body">
<span class="badge"><?php echo esc_html($type_label); ?></span>
<h3 class="content-card__title"><?php the_title(); ?></h3>
<?php if (has_excerpt()) : ?>
<p class="content-card__excerpt"><?php echo esc_html(wp_trim_words(get_the_excerpt(), 15)); ?></p>
<?php endif; ?>
<div class="content-card__meta">
<time datetime="<?php echo esc_attr(get_the_date('Y-m-d')); ?>">
<?php echo esc_html(get_the_date('d.m.Y')); ?>
</time>
</div>
</div>
</a>
</article>
- Step 3: Создать AJAX-обработчик
Создать файл wp-content/themes/bitwms-child/inc/ajax-filter.php:
<?php
/**
* AJAX-фильтрация ленты контента на главной
*
* @package bitwms
*/
defined('ABSPATH') || exit;
add_action('wp_ajax_bitwms_filter', 'bitwms_ajax_filter');
add_action('wp_ajax_nopriv_bitwms_filter', 'bitwms_ajax_filter');
function bitwms_ajax_filter(): void {
$post_type = sanitize_text_field($_POST['post_type'] ?? 'all');
$page = absint($_POST['page'] ?? 1);
$per_page = 6;
$args = [
'posts_per_page' => $per_page,
'paged' => $page,
'orderby' => 'date',
'order' => 'DESC',
];
if ($post_type === 'all') {
$args['post_type'] = ['post', 'case', 'webinar', 'course', 'event', 'material'];
} else {
$args['post_type'] = $post_type;
}
$query = new WP_Query($args);
ob_start();
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
get_template_part('templates/content-card');
}
wp_reset_postdata();
}
$html = ob_get_clean();
wp_send_json_success([
'html' => $html,
'has_more' => $page < $query->max_num_pages,
]);
}
- Step 4: Создать JS для AJAX-фильтрации
Создать файл wp-content/themes/bitwms-child/js/ajax-filter.js:
/**
* AJAX-фильтрация ленты контента + "Показать ещё"
*/
document.addEventListener('DOMContentLoaded', function () {
const filterBar = document.querySelector('.filter-bar');
const contentGrid = document.getElementById('content-grid');
const loadMoreBtn = document.getElementById('load-more-btn');
if (!filterBar || !contentGrid) return;
let currentFilter = 'all';
let currentPage = 1;
// Фильтрация по типу
filterBar.addEventListener('click', function (e) {
const btn = e.target.closest('.filter-bar__btn');
if (!btn) return;
// Обновляем активную кнопку
filterBar.querySelectorAll('.filter-bar__btn').forEach(function (b) {
b.classList.remove('filter-bar__btn--active');
b.setAttribute('aria-selected', 'false');
});
btn.classList.add('filter-bar__btn--active');
btn.setAttribute('aria-selected', 'true');
currentFilter = btn.dataset.filter;
currentPage = 1;
loadContent(false);
});
// "Показать ещё"
if (loadMoreBtn) {
loadMoreBtn.addEventListener('click', function () {
currentPage++;
loadContent(true);
});
}
function loadContent(append) {
var formData = new FormData();
formData.append('action', 'bitwms_filter');
formData.append('post_type', currentFilter);
formData.append('page', currentPage);
fetch(bitwmsAjax.url, {
method: 'POST',
body: formData,
})
.then(function (response) { return response.json(); })
.then(function (data) {
if (data.success) {
if (append) {
contentGrid.insertAdjacentHTML('beforeend', data.data.html);
} else {
contentGrid.innerHTML = data.data.html;
}
if (loadMoreBtn) {
loadMoreBtn.style.display = data.data.has_more ? '' : 'none';
}
}
});
}
});
- Step 5: Подключить AJAX-обработчик и скрипт
Добавить 'inc/ajax-filter.php' в $bitwms_includes в functions.php:
$bitwms_includes = [
'inc/enqueue.php',
'inc/cpt.php',
'inc/acf-fields.php',
'inc/ajax-filter.php',
];
Обновить inc/enqueue.php — добавить скрипт и локализацию:
<?php
/**
* Подключение скриптов и стилей
*
* @package bitwms
*/
defined('ABSPATH') || exit;
add_action('wp_enqueue_scripts', function () {
$theme_version = wp_get_theme()->get('Version');
$theme_uri = get_stylesheet_directory_uri();
// Боковая навигация
wp_enqueue_script(
'bitwms-sidebar-nav',
$theme_uri . '/js/sidebar-nav.js',
[],
$theme_version,
true
);
// AJAX-фильтрация (только на главной)
if (is_front_page()) {
wp_enqueue_script(
'bitwms-ajax-filter',
$theme_uri . '/js/ajax-filter.js',
[],
$theme_version,
true
);
wp_localize_script('bitwms-ajax-filter', 'bitwmsAjax', [
'url' => admin_url('admin-ajax.php'),
]);
}
}, 20);
- Step 6: Добавить CSS для фильтра и сетки карточек
Добавить в style.css:
/* ==========================================================================
Фильтр-бар
========================================================================== */
.filter-bar {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 32px;
padding-bottom: 24px;
border-bottom: 1px solid var(--color-gray-light);
}
.filter-bar__btn {
padding: 8px 20px;
font-family: var(--font-body);
font-size: 0.875rem;
font-weight: 400;
background: none;
border: 1px solid var(--color-gray-light);
cursor: pointer;
transition: background-color 0.15s, color 0.15s, border-color 0.15s;
color: var(--color-black);
}
.filter-bar__btn:hover {
border-color: var(--color-black);
}
.filter-bar__btn--active {
background-color: var(--color-black);
color: var(--color-white);
border-color: var(--color-black);
font-weight: 700;
}
/* ==========================================================================
Сетка карточек контента
========================================================================== */
.content-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
margin-bottom: 32px;
}
.content-card__link {
display: block;
text-decoration: none;
color: inherit;
transition: opacity 0.15s;
}
.content-card__link:hover {
text-decoration: none;
color: inherit;
}
.content-card__link:hover .content-card__title {
color: var(--color-primary);
}
.content-card__image {
aspect-ratio: 16 / 10;
overflow: hidden;
margin-bottom: 16px;
background-color: var(--color-gray-light);
}
.content-card__image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.content-card__body .badge {
margin-bottom: 8px;
}
.content-card__title {
font-size: 1.125rem;
margin: 0 0 8px;
line-height: 1.3;
transition: color 0.15s;
}
.content-card__excerpt {
font-size: 0.875rem;
color: var(--color-gray-text);
margin: 0 0 12px;
line-height: 1.5;
}
.content-card__meta {
font-size: 0.75rem;
color: var(--color-gray-text);
}
.content-feed__more {
text-align: center;
margin-bottom: 60px;
}
@media (max-width: 1024px) {
.content-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 767px) {
.content-grid {
grid-template-columns: 1fr;
}
}
- Step 7: Проверить фильтрацию
Создать несколько тестовых записей разных типов в админке. Открыть главную:
-
Фильтр-бар с кнопками типов контента
-
Клик по типу фильтрует карточки без перезагрузки
-
"Показать ещё" подгружает следующую порцию
-
Карточки в сетке 3 колонки (2 на планшете, 1 на мобильном)
-
Step 8: Коммит
git add themes/bitwms-child/
git commit -m "feat: add content feed with AJAX filtering and load more on front page"
Task 10: Страница продукта БИТ.WMS
Контекст: Продуктовая страница: герой, функции, "Почему Первый Бит", кейсы, другие решения, форма демо, анкета.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/page-templates/page-bit-wms.php -
Модифицировать:
wp-content/themes/bitwms-child/style.css -
Step 1: Создать шаблон страницы БИТ.WMS
Создать файл wp-content/themes/bitwms-child/page-templates/page-bit-wms.php:
<?php
/**
* Template Name: БИТ.WMS
*
* @package bitwms
*/
defined('ABSPATH') || exit;
get_header();
?>
<main class="page-bitwms">
<!-- Герой -->
<section class="bitwms-hero">
<div class="container">
<h1>БИТ.WMS</h1>
<p class="bitwms-hero__subtitle">Комплексное решение для управления складом</p>
<p class="bitwms-hero__desc">БИТ.WMS — это полнофункциональная система управления складом от компании «Первый Бит». Автоматизирует все складские процессы: от приёмки до отгрузки, с полным контролем на каждом этапе.</p>
<div class="bitwms-hero__actions">
<a href="#demo-form" class="btn btn-primary">Заказать демо</a>
<a href="#" class="btn btn-outline" data-popup="download-presentation">Скачать презентацию</a>
</div>
</div>
</section>
<!-- Функции -->
<section class="bitwms-features">
<div class="container">
<h2>Функции БИТ.WMS</h2>
<div class="features-grid">
<?php
$features = [
['title' => 'Приёмка', 'desc' => 'Контроль поступающего товара, сверка с заказами, маркировка', 'result' => 'Сокращение времени приёмки на 40%'],
['title' => 'Размещение', 'desc' => 'Автоматический подбор ячеек хранения по заданным правилам', 'result' => 'Оптимизация использования площади склада'],
['title' => 'Хранение', 'desc' => 'Адресное хранение, контроль сроков годности, серийных номеров', 'result' => 'Снижение потерь от просрочки'],
['title' => 'Отбор', 'desc' => 'Волновой и кластерный отбор, оптимизация маршрутов сборки', 'result' => 'Увеличение скорости сборки заказов на 30%'],
['title' => 'Отгрузка', 'desc' => 'Контроль отгрузки, формирование документов, сверка с заказом', 'result' => 'Снижение ошибок отгрузки до 0,1%'],
['title' => 'Инвентаризация', 'desc' => 'Плановая и выборочная инвентаризация с ТСД', 'result' => 'Инвентаризация за часы вместо дней'],
];
foreach ($features as $f) : ?>
<div class="feature-card">
<h3 class="feature-card__title"><?php echo esc_html($f['title']); ?></h3>
<p class="feature-card__desc"><?php echo esc_html($f['desc']); ?></p>
<p class="feature-card__result"><strong>Результат:</strong> <?php echo esc_html($f['result']); ?></p>
</div>
<?php endforeach; ?>
</div>
</div>
</section>
<!-- Почему Первый Бит -->
<section class="bitwms-why">
<div class="container">
<h2>Почему Первый Бит</h2>
<div class="why-grid">
<div class="why-item">
<h3 class="why-item__title">Быстро</h3>
<p>Мы — профессионалы, знаем бизнес-задачи склада и процессы. Запускаем проекты за недели.</p>
</div>
<div class="why-item">
<h3 class="why-item__title">Просто</h3>
<p>Знаем все о WMS-решениях и имеем собственный программный продукт БИТ.WMS.</p>
</div>
<div class="why-item">
<h3 class="why-item__title">Качественно</h3>
<p>Первый Бит — это результат. 200+ успешных проектов, многолетний опыт.</p>
</div>
<div class="why-item">
<h3 class="why-item__title">Открыто</h3>
<p>Прозрачная ценовая политика. Понятные сроки и этапы внедрения.</p>
</div>
</div>
</div>
</section>
<!-- Кейсы -->
<section class="bitwms-cases">
<div class="container">
<h2>Кейсы внедрения</h2>
<div class="content-grid">
<?php
$cases_query = new WP_Query([
'post_type' => 'case',
'posts_per_page' => 3,
'orderby' => 'date',
'order' => 'DESC',
]);
if ($cases_query->have_posts()) :
while ($cases_query->have_posts()) :
$cases_query->the_post();
get_template_part('templates/content-card');
endwhile;
wp_reset_postdata();
else : ?>
<p>Кейсы скоро появятся.</p>
<?php endif; ?>
</div>
<p><a href="<?php echo esc_url(home_url('/cases/')); ?>" class="btn btn-outline">Все кейсы</a></p>
</div>
</section>
<!-- Другие решения -->
<section class="bitwms-other">
<div class="container">
<h2>Возможно, вам будет интересно</h2>
<div class="other-grid">
<div class="other-card">
<h3>1C:WMS Логистика</h3>
<p>Управление складом на платформе 1С</p>
</div>
<div class="other-card">
<h3>Клеверенс</h3>
<p>Мобильная автоматизация склада</p>
</div>
<div class="other-card">
<h3>1C:TMS</h3>
<p>Управление транспортной логистикой</p>
</div>
</div>
</div>
</section>
<!-- Форма "Заказать демо" -->
<section class="bitwms-demo" id="demo-form">
<div class="container">
<h2>Заказать демо БИТ.WMS</h2>
<p>Оставьте заявку, и наш эксперт свяжется с вами для демонстрации системы</p>
<?php
// Contact Form 7 shortcode — ID формы подставить после создания
// echo do_shortcode('[contact-form-7 id="XXX" title="Заказать демо"]');
?>
<form class="demo-form" action="#" method="post">
<div class="demo-form__grid">
<input type="text" name="name" placeholder="Имя *" required />
<input type="text" name="company" placeholder="Компания" />
<input type="tel" name="phone" placeholder="Телефон *" required />
<input type="email" name="email" placeholder="Email *" required />
</div>
<textarea name="comment" placeholder="Комментарий" rows="3"></textarea>
<label class="demo-form__consent">
<input type="checkbox" required />
Согласен на <a href="/privacy-policy/" target="_blank">обработку персональных данных</a>
</label>
<button type="submit" class="btn btn-primary">Отправить заявку</button>
</form>
<p class="demo-form__anketa">
Нужен детальный расчёт? <a href="<?php echo esc_url(home_url('/bit-wms/anketa/')); ?>">Заполните анкету</a>
</p>
</div>
</section>
</main>
<?php
get_footer();
- Step 2: Добавить CSS для страницы БИТ.WMS
Добавить в style.css:
/* ==========================================================================
Страница БИТ.WMS
========================================================================== */
.bitwms-hero {
padding: 80px 0 60px;
}
.bitwms-hero h1 {
font-size: 4rem;
margin: 0 0 16px;
}
.bitwms-hero__subtitle {
font-size: 1.5rem;
color: var(--color-gray-text);
margin: 0 0 24px;
}
.bitwms-hero__desc {
font-size: 1.125rem;
line-height: 1.6;
max-width: 700px;
margin: 0 0 32px;
}
.bitwms-hero__actions {
display: flex;
gap: 16px;
}
/* Функции */
.bitwms-features {
padding: 80px 0;
background-color: var(--color-gray-light);
}
.features-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
margin-top: 32px;
}
.feature-card {
background: var(--color-white);
padding: 32px;
}
.feature-card__title {
margin: 0 0 12px;
}
.feature-card__desc {
color: var(--color-gray-text);
line-height: 1.6;
margin: 0 0 16px;
}
.feature-card__result {
font-size: 0.875rem;
color: var(--color-primary);
margin: 0;
}
/* Почему Первый Бит */
.bitwms-why {
padding: 80px 0;
}
.why-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 32px;
margin-top: 32px;
}
.why-item__title {
font-size: 1.5rem;
margin: 0 0 12px;
}
.why-item p {
color: var(--color-gray-text);
line-height: 1.6;
margin: 0;
}
/* Кейсы */
.bitwms-cases {
padding: 60px 0;
border-top: 1px solid var(--color-gray-light);
}
/* Другие решения */
.bitwms-other {
padding: 60px 0;
background-color: var(--color-gray-light);
}
.other-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
margin-top: 32px;
}
.other-card {
background: var(--color-white);
padding: 32px;
}
.other-card h3 {
margin: 0 0 8px;
}
.other-card p {
color: var(--color-gray-text);
margin: 0;
}
/* Форма демо */
.bitwms-demo {
padding: 80px 0;
}
.demo-form {
max-width: 600px;
margin-top: 24px;
}
.demo-form__grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
margin-bottom: 12px;
}
.demo-form input[type="text"],
.demo-form input[type="tel"],
.demo-form input[type="email"],
.demo-form textarea {
width: 100%;
padding: 12px 16px;
font-family: var(--font-body);
font-size: 1rem;
border: 2px solid var(--color-gray-light);
border-radius: 0;
background: var(--color-white);
box-sizing: border-box;
}
.demo-form input:focus,
.demo-form textarea:focus {
outline: none;
border-color: var(--color-primary);
}
.demo-form textarea {
margin-bottom: 16px;
}
.demo-form__consent {
display: flex;
align-items: flex-start;
gap: 8px;
font-size: 0.875rem;
margin-bottom: 24px;
color: var(--color-gray-text);
}
.demo-form__anketa {
margin-top: 24px;
font-size: 0.875rem;
color: var(--color-gray-text);
}
@media (max-width: 767px) {
.bitwms-hero h1 {
font-size: 2.5rem;
}
.bitwms-hero__actions {
flex-direction: column;
}
.features-grid,
.other-grid {
grid-template-columns: 1fr;
}
.why-grid {
grid-template-columns: repeat(2, 1fr);
}
.demo-form__grid {
grid-template-columns: 1fr;
}
}
- Step 3: Создать страницу в WP и назначить шаблон
В админке WP: создать страницу "БИТ.WMS" со slug bit-wms, назначить шаблон "БИТ.WMS".
- Step 4: Проверить страницу
Открыть http://bitwms.local/bit-wms/:
-
Все секции отображаются
-
Форма демо работает визуально
-
Адаптивность на мобильном
-
Step 5: Коммит
git add themes/bitwms-child/
git commit -m "feat: add BIT.WMS product page template with features, benefits, and demo form"
Task 11: Архивные шаблоны и детальные страницы CPT
Контекст: Единый шаблон архива для всех CPT + детальные шаблоны для кейсов, вебинаров, курсов, мероприятий.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/archive/archive-cpt.php -
Создать:
wp-content/themes/bitwms-child/template-parts/single-case.php -
Создать:
wp-content/themes/bitwms-child/template-parts/single-webinar.php -
Создать:
wp-content/themes/bitwms-child/template-parts/single-course.php -
Создать:
wp-content/themes/bitwms-child/template-parts/single-event.php -
Модифицировать:
wp-content/themes/bitwms-child/style.css -
Step 1: Создать архивные шаблоны
WordPress ищет шаблоны по иерархии: archive-{post_type}.php. Создаём по одному для каждого CPT (все используют единый layout).
Создать файл wp-content/themes/bitwms-child/archive-case.php:
<?php
/**
* Архив Кейсов
*
* @package bitwms
*/
defined('ABSPATH') || exit;
get_header();
?>
<main class="archive-page">
<div class="container">
<h1 class="archive-page__title">Кейсы</h1>
<div class="content-grid">
<?php
if (have_posts()) :
while (have_posts()) :
the_post();
get_template_part('templates/content-card');
endwhile;
else : ?>
<p>Кейсы скоро появятся.</p>
<?php endif; ?>
</div>
<?php the_posts_pagination([
'prev_text' => '←',
'next_text' => '→',
]); ?>
</div>
</main>
<?php
get_footer();
Создать аналогичные файлы для остальных CPT — archive-webinar.php, archive-course.php, archive-event.php, archive-material.php — меняя только заголовок H1 ("Вебинары", "Курсы", "Мероприятия", "Материалы") и текст "не найдено".
- Step 2: Создать детальный шаблон кейса
Создать файл wp-content/themes/bitwms-child/single-case.php:
<?php
/**
* Детальная страница кейса
*
* @package bitwms
*/
defined('ABSPATH') || exit;
get_header();
the_post();
$client = get_field('case_client');
$industry = get_field('case_industry');
$task = get_field('case_task');
$solution = get_field('case_solution');
$result = get_field('case_result');
$quote = get_field('case_quote');
$gallery = get_field('case_gallery');
?>
<main class="single-case">
<div class="container">
<article>
<h1><?php the_title(); ?></h1>
<div class="single-case__meta">
<?php if ($client) : ?>
<div class="single-case__meta-item">
<strong>Клиент:</strong> <?php echo esc_html($client); ?>
</div>
<?php endif; ?>
<?php if ($industry) : ?>
<div class="single-case__meta-item">
<strong>Отрасль:</strong> <?php echo esc_html($industry); ?>
</div>
<?php endif; ?>
</div>
<?php if ($task) : ?>
<section class="single-case__section">
<h2>Задача</h2>
<?php echo wp_kses_post($task); ?>
</section>
<?php endif; ?>
<?php if ($solution) : ?>
<section class="single-case__section">
<h2>Решение</h2>
<?php echo wp_kses_post($solution); ?>
</section>
<?php endif; ?>
<?php if ($result) : ?>
<section class="single-case__section">
<h2>Результат</h2>
<?php echo wp_kses_post($result); ?>
</section>
<?php endif; ?>
<?php if ($gallery) : ?>
<section class="single-case__gallery">
<h2>Галерея</h2>
<div class="gallery-grid">
<?php foreach ($gallery as $img) : ?>
<a href="<?php echo esc_url($img['url']); ?>" target="_blank">
<img src="<?php echo esc_url($img['sizes']['medium_large']); ?>"
alt="<?php echo esc_attr($img['alt']); ?>" />
</a>
<?php endforeach; ?>
</div>
</section>
<?php endif; ?>
<?php if ($quote) : ?>
<blockquote class="single-case__quote">
<p><?php echo esc_html($quote); ?></p>
</blockquote>
<?php endif; ?>
<div class="single-case__cta">
<p>Хотите такой же результат?</p>
<a href="<?php echo esc_url(home_url('/bit-wms/#demo-form')); ?>" class="btn btn-primary">Закажите консультацию</a>
</div>
</article>
<!-- Похожие кейсы -->
<section class="related-posts">
<h2>Другие кейсы</h2>
<div class="content-grid">
<?php
$related = new WP_Query([
'post_type' => 'case',
'posts_per_page' => 3,
'post__not_in' => [get_the_ID()],
'orderby' => 'rand',
]);
if ($related->have_posts()) :
while ($related->have_posts()) :
$related->the_post();
get_template_part('templates/content-card');
endwhile;
wp_reset_postdata();
endif;
?>
</div>
</section>
</div>
</main>
<?php
get_footer();
- Step 3: Создать детальные шаблоны вебинара, курса, мероприятия
Создать single-webinar.php, single-course.php, single-event.php по аналогичной структуре, используя соответствующие ACF-поля из Task 6. Каждый шаблон содержит:
-
Заголовок H1
-
ACF-поля в нужном порядке
-
CTA-блок внизу (регистрация / запись)
-
Блок "Похожие" (3 карточки того же типа)
-
Step 4: Добавить CSS для детальных страниц
Добавить в style.css:
/* ==========================================================================
Архивные страницы
========================================================================== */
.archive-page {
padding: 60px 0;
}
.archive-page__title {
margin: 0 0 32px;
}
/* ==========================================================================
Детальные страницы
========================================================================== */
.single-case,
.single-webinar,
.single-course,
.single-event {
padding: 60px 0;
}
.single-case__meta {
display: flex;
gap: 24px;
margin-bottom: 40px;
padding-bottom: 24px;
border-bottom: 1px solid var(--color-gray-light);
}
.single-case__meta-item {
font-size: 0.875rem;
color: var(--color-gray-text);
}
.single-case__section {
margin-bottom: 40px;
}
.single-case__section h2 {
font-size: 1.5rem;
margin: 0 0 16px;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
margin-top: 16px;
}
.gallery-grid img {
width: 100%;
height: auto;
}
.single-case__quote {
border-left: 4px solid var(--color-primary);
padding: 24px 32px;
margin: 40px 0;
background-color: var(--color-gray-light);
font-style: italic;
font-size: 1.125rem;
line-height: 1.6;
}
.single-case__cta {
padding: 40px 0;
border-top: 1px solid var(--color-gray-light);
}
.single-case__cta p {
font-size: 1.25rem;
font-weight: 700;
margin: 0 0 16px;
}
.related-posts {
padding: 60px 0 0;
border-top: 1px solid var(--color-gray-light);
}
.related-posts h2 {
margin: 0 0 24px;
}
/* Пагинация */
.nav-links {
display: flex;
gap: 8px;
justify-content: center;
margin-top: 32px;
}
.nav-links .page-numbers {
padding: 8px 16px;
border: 1px solid var(--color-gray-light);
color: var(--color-black);
text-decoration: none;
}
.nav-links .page-numbers.current {
background: var(--color-black);
color: var(--color-white);
border-color: var(--color-black);
}
@media (max-width: 767px) {
.single-case__meta {
flex-direction: column;
gap: 8px;
}
.gallery-grid {
grid-template-columns: repeat(2, 1fr);
}
}
- Step 5: Проверить архивы и детальные страницы
Создать тестовые записи каждого типа. Проверить:
-
/cases/— архив кейсов с карточками -
/cases/test-case/— детальная страница с ACF-полями -
Аналогично для вебинаров, курсов, мероприятий, материалов
-
Step 6: Коммит
git add themes/bitwms-child/
git commit -m "feat: add archive and single templates for all custom post types"
Task 12: Страница контактов и футер
Контекст: Страница контактов с формой обратной связи. Кастомный футер с колонками.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/page-templates/page-contacts.php -
Модифицировать:
wp-content/themes/bitwms-child/functions.php(футер) -
Модифицировать:
wp-content/themes/bitwms-child/style.css -
Step 1: Создать шаблон страницы контактов
Создать файл wp-content/themes/bitwms-child/page-templates/page-contacts.php:
<?php
/**
* Template Name: Контакты
*
* @package bitwms
*/
defined('ABSPATH') || exit;
get_header();
?>
<main class="page-contacts">
<div class="container">
<h1>Контакты</h1>
<div class="contacts-grid">
<div class="contacts-info">
<h2>Екатеринбург Проектный центр</h2>
<p><strong>Телефон:</strong> <a href="tel:+73432000000">+7 (343) 200-00-00</a></p>
<p><strong>Email:</strong> <a href="mailto:wms@1bit.ru">wms@1bit.ru</a></p>
<p><strong>Адрес:</strong> г. Екатеринбург</p>
</div>
<div class="contacts-form">
<h2>Напишите нам</h2>
<?php // echo do_shortcode('[contact-form-7 id="XXX" title="Обратная связь"]'); ?>
<form action="#" method="post">
<input type="text" name="name" placeholder="Имя *" required />
<input type="email" name="email" placeholder="Email *" required />
<textarea name="message" placeholder="Сообщение" rows="5"></textarea>
<label class="demo-form__consent">
<input type="checkbox" required />
Согласен на <a href="/privacy-policy/" target="_blank">обработку персональных данных</a>
</label>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
</div>
</div>
</div>
</main>
<?php
get_footer();
- Step 2: Настроить кастомный футер
Добавить в functions.php:
// Кастомный футер
add_action('generate_before_footer_content', function () {
?>
<div class="custom-footer">
<div class="container">
<div class="custom-footer__grid">
<div class="custom-footer__col">
<img src="<?php echo esc_url(get_stylesheet_directory_uri() . '/img/logo.svg'); ?>"
alt="первыйБит" height="24" />
<p>Екатеринбург Проектный центр</p>
<p><a href="tel:+73432000000">+7 (343) 200-00-00</a></p>
<p><a href="mailto:wms@1bit.ru">wms@1bit.ru</a></p>
</div>
<div class="custom-footer__col">
<h4>Разделы</h4>
<ul>
<li><a href="/cases/">Кейсы</a></li>
<li><a href="/articles/">Статьи</a></li>
<li><a href="/webinars/">Вебинары</a></li>
<li><a href="/courses/">Курсы</a></li>
<li><a href="/events/">Мероприятия</a></li>
<li><a href="/materials/">Материалы</a></li>
</ul>
</div>
<div class="custom-footer__col">
<h4>Продукты</h4>
<ul>
<li><a href="/bit-wms/">БИТ.WMS</a></li>
<li>1C:WMS</li>
<li>Клеверенс</li>
<li>1C:TMS</li>
</ul>
</div>
<div class="custom-footer__col">
<h4>Подписка</h4>
<form class="footer-subscribe" action="#" method="post">
<input type="email" placeholder="Ваш email" required />
<button type="submit" class="btn btn-primary btn-sm">OK</button>
</form>
</div>
</div>
<div class="custom-footer__bottom">
<p>© <?php echo date('Y'); ?> Первый Бит. Все права защищены.</p>
<div class="custom-footer__legal">
<a href="/privacy-policy/">Политика конфиденциальности</a>
<a href="/consent/">Согласие на обработку данных</a>
</div>
</div>
</div>
</div>
<?php
}, 5);
- Step 3: Добавить CSS футера и контактов
Добавить в style.css:
/* ==========================================================================
Страница контактов
========================================================================== */
.page-contacts {
padding: 60px 0;
}
.contacts-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 48px;
margin-top: 32px;
}
.contacts-info p {
line-height: 1.8;
}
.contacts-form input,
.contacts-form textarea {
width: 100%;
padding: 12px 16px;
font-family: var(--font-body);
font-size: 1rem;
border: 2px solid var(--color-gray-light);
border-radius: 0;
margin-bottom: 12px;
box-sizing: border-box;
}
.contacts-form input:focus,
.contacts-form textarea:focus {
outline: none;
border-color: var(--color-primary);
}
/* ==========================================================================
Футер
========================================================================== */
.custom-footer {
border-top: 1px solid var(--color-gray-light);
padding: 48px 0 24px;
}
.custom-footer__grid {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1.5fr;
gap: 32px;
margin-bottom: 32px;
}
.custom-footer__col h4 {
font-size: 0.875rem;
margin: 0 0 16px;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.custom-footer__col ul {
list-style: none;
margin: 0;
padding: 0;
}
.custom-footer__col li {
margin-bottom: 8px;
font-size: 0.875rem;
}
.custom-footer__col a {
color: var(--color-gray-text);
}
.custom-footer__col a:hover {
color: var(--color-primary);
}
.custom-footer__col p {
font-size: 0.875rem;
color: var(--color-gray-text);
line-height: 1.6;
}
.footer-subscribe {
display: flex;
gap: 8px;
}
.footer-subscribe input {
flex: 1;
padding: 8px 12px;
font-size: 0.875rem;
border: 2px solid var(--color-gray-light);
border-radius: 0;
}
.custom-footer__bottom {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 24px;
border-top: 1px solid var(--color-gray-light);
font-size: 0.75rem;
color: var(--color-gray-text);
}
.custom-footer__legal {
display: flex;
gap: 24px;
}
.custom-footer__legal a {
color: var(--color-gray-text);
font-size: 0.75rem;
}
@media (max-width: 767px) {
.contacts-grid {
grid-template-columns: 1fr;
}
.custom-footer__grid {
grid-template-columns: 1fr;
}
.custom-footer__bottom {
flex-direction: column;
gap: 12px;
text-align: center;
}
}
-
Step 4: Создать страницу "Контакты" в WP, назначить шаблон
-
Step 5: Проверить контакты и футер
-
Step 6: Коммит
git add themes/bitwms-child/
git commit -m "feat: add contacts page template and custom footer"
Task 13: Формы Contact Form 7 и gated-контент
Контекст: Настраиваем реальные формы CF7 для всех точек лидогенерации. Gated-контент для материалов.
Файлы:
-
Создать:
wp-content/themes/bitwms-child/js/gated-content.js -
Модифицировать:
wp-content/themes/bitwms-child/inc/enqueue.php -
Step 1: Создать формы Contact Form 7 в админке
В админке WP > Contact > Add New. Создать 5 форм:
Форма "Заказать демо":
[text* your-name placeholder "Имя"]
[text your-company placeholder "Компания"]
[tel* your-phone placeholder "Телефон"]
[email* your-email placeholder "Email"]
[textarea your-comment placeholder "Комментарий"]
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
[submit "Отправить заявку"]
Форма "Получить консультацию":
[text* your-name placeholder "Имя"]
[tel* your-phone placeholder "Телефон"]
[email* your-email placeholder "Email"]
[textarea your-question placeholder "Ваш вопрос"]
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
[submit "Отправить"]
Форма "Зарегистрироваться":
[text* your-name placeholder "Имя"]
[email* your-email placeholder "Email"]
[tel your-phone placeholder "Телефон"]
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
[submit "Зарегистрироваться"]
Форма "Скачать материал" (gated):
[text* your-name placeholder "Имя"]
[email* your-email placeholder "Email"]
[hidden material-id]
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
[submit "Скачать"]
Форма "Обратная связь":
[text* your-name placeholder "Имя"]
[email* your-email placeholder "Email"]
[textarea* your-message placeholder "Сообщение"]
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
[submit "Отправить"]
Для каждой формы настроить email-уведомление на адрес wms@1bit.ru.
- Step 2: Заменить placeholder-формы на шорткоды CF7
Обновить шаблоны page-bit-wms.php, page-contacts.php — заменить HTML-формы на echo do_shortcode('[contact-form-7 id="ID" title="Название"]'); с реальными ID форм.
- Step 3: Создать JS для gated-контента
Создать файл wp-content/themes/bitwms-child/js/gated-content.js:
/**
* Gated-контент — модальное окно для скачивания материалов за email
*/
document.addEventListener('DOMContentLoaded', function () {
var modal = document.getElementById('gated-modal');
if (!modal) return;
var overlay = modal.querySelector('.gated-modal__overlay');
var closeBtn = modal.querySelector('.gated-modal__close');
// Открытие модального окна по data-gated
document.addEventListener('click', function (e) {
var trigger = e.target.closest('[data-gated]');
if (!trigger) return;
e.preventDefault();
var materialId = trigger.dataset.gated;
var downloadUrl = trigger.dataset.downloadUrl;
// Установить hidden-поле с ID материала
var hiddenField = modal.querySelector('input[name="material-id"]');
if (hiddenField) {
hiddenField.value = materialId;
}
// Сохранить URL для скачивания
modal.dataset.downloadUrl = downloadUrl || '';
modal.classList.add('gated-modal--open');
document.body.style.overflow = 'hidden';
});
// Закрытие
function closeModal() {
modal.classList.remove('gated-modal--open');
document.body.style.overflow = '';
}
if (closeBtn) closeBtn.addEventListener('click', closeModal);
if (overlay) overlay.addEventListener('click', closeModal);
// После успешной отправки CF7 — скачать файл
document.addEventListener('wpcf7mailsent', function (e) {
if (modal.classList.contains('gated-modal--open') && modal.dataset.downloadUrl) {
window.open(modal.dataset.downloadUrl, '_blank');
closeModal();
}
});
});
- Step 4: Добавить HTML модального окна в footer
Добавить в functions.php:
// Модальное окно gated-контента
add_action('wp_footer', function () {
?>
<div id="gated-modal" class="gated-modal">
<div class="gated-modal__overlay"></div>
<div class="gated-modal__content">
<button class="gated-modal__close" aria-label="Закрыть">×</button>
<h3>Скачать материал</h3>
<p>Укажите ваши данные для получения доступа к материалу</p>
<?php // echo do_shortcode('[contact-form-7 id="ID" title="Скачать материал"]'); ?>
</div>
</div>
<?php
});
- Step 5: Добавить CSS модального окна
Добавить в style.css:
/* ==========================================================================
Модальное окно (gated-контент)
========================================================================== */
.gated-modal {
display: none;
position: fixed;
inset: 0;
z-index: 2000;
align-items: center;
justify-content: center;
}
.gated-modal--open {
display: flex;
}
.gated-modal__overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.5);
}
.gated-modal__content {
position: relative;
background: var(--color-white);
padding: 48px;
max-width: 480px;
width: 90%;
z-index: 1;
}
.gated-modal__close {
position: absolute;
top: 16px;
right: 16px;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--color-gray-text);
}
- Step 6: Подключить скрипт в enqueue.php
Добавить в inc/enqueue.php:
// Gated-контент
wp_enqueue_script(
'bitwms-gated-content',
$theme_uri . '/js/gated-content.js',
[],
$theme_version,
true
);
-
Step 7: Проверить формы и gated-контент
-
Step 8: Коммит
git add themes/bitwms-child/
git commit -m "feat: add Contact Form 7 forms and gated content modal"
Task 14: Попапы, JivoSite, callback, аналитика
Контекст: Финальный слой лидогенерации: попапы (exit-intent, таймер), виджеты JivoSite и callback, аналитика.
Файлы:
-
Модифицировать:
wp-content/themes/bitwms-child/functions.php -
Step 1: Настроить Popup Maker
В админке WP > Popup Maker > Add New:
Попап "Exit-intent — Подписка":
- Содержимое: "Не уходите! Подпишитесь на экспертные материалы по складской логистике" + форма email
- Триггер: Exit Intent
- Условия: все страницы
- Настройки: показывать 1 раз за сессию
Попап "Таймер — Демо":
-
Содержимое: "Хотите увидеть БИТ.WMS в действии?" + CTA "Заказать демо"
-
Триггер: Time Delay — 60 секунд
-
Условия: только страница БИТ.WMS
-
Настройки: показывать 1 раз за сессию
-
Step 2: Подключить JivoSite
Добавить в functions.php:
// JivoSite — виджет онлайн-консультанта
add_action('wp_footer', function () {
// Подставить реальный widget_id из кабинета JivoSite
?>
<!-- JivoSite -->
<script src="//code.jivo.ru/widget/XXXXXXXX" async></script>
<?php
}, 99);
Настройка автоприглашения через 30 сек — в панели управления JivoSite (Настройки > Проактивные приглашения), указать страницы: главная, /bit-wms/, /cases/.
- Step 3: Подключить callback-виджет
Добавить в functions.php:
// Callback-виджет
add_action('wp_footer', function () {
// Подставить реальный код виджета из кабинета callback-hunter или аналога
?>
<!-- Callback Widget -->
<!-- <script src="https://cdn.callbackhunter.com/XXXXX.js" async></script> -->
<?php
}, 99);
- Step 4: Подключить Яндекс.Метрику и GA4
Добавить в functions.php:
// Аналитика — Яндекс.Метрика + GA4
add_action('wp_head', function () {
?>
<!-- Yandex.Metrika counter -->
<!-- Подставить реальный ID счётчика -->
<!--
<script type="text/javascript">
(function(m,e,t,r,i,k,a){...})(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(XXXXXXXX, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
-->
<!-- Google Analytics 4 -->
<!-- Подставить реальный ID GA4 -->
<!--
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
-->
<?php
}, 1);
Цели в Яндекс.Метрике настраиваются через интерфейс метрики после получения ID счётчика.
- Step 5: Настроить Yoast SEO
В админке WP > SEO > General:
- Указать название организации: "Первый Бит"
- Schema.org: тип организации — Company
- Social: указать ссылки на VK, Telegram
Для каждой страницы/записи: заполнить SEO-заголовок и мета-описание.
-
Step 6: Проверить все виджеты
-
JivoSite виджет отображается в правом нижнем углу
-
Попап exit-intent срабатывает при уходе с сайта
-
Попап таймера появляется через 60 сек на странице БИТ.WMS
-
Step 7: Коммит
git add themes/bitwms-child/
git commit -m "feat: add popups, JivoSite, callback widget, and analytics tracking"
Task 15: Финальная проверка и полировка
Контекст: Проверяем весь сайт целиком: все страницы, формы, адаптивность, производительность.
- Step 1: Проверить все страницы
Пройти по каждой странице и убедиться:
-
Главная: герой, фильтр, лента, промо WMS, подписка, клиенты
-
БИТ.WMS: герой, функции, "почему", кейсы, другие решения, демо-форма
-
Архивы: кейсы, статьи, вебинары, курсы, мероприятия, материалы
-
Детальные: каждый тип записи с ACF-полями
-
Контакты: информация + форма
-
Футер: на всех страницах
-
Step 2: Проверить адаптивность
Протестировать все страницы на разрешениях:
- Desktop: 1920px, 1440px, 1280px
- Tablet: 1024px, 768px
- Mobile: 375px, 320px
Убедиться:
-
Боковая панель скрывается < 768px, гамбургер работает
-
Сетки переходят в 1 колонку
-
Формы занимают полную ширину
-
Текст читабелен
-
Step 3: Проверить формы
Отправить тестовые данные через каждую форму:
- Заказать демо
- Получить консультацию
- Зарегистрироваться на вебинар
- Скачать материал (gated)
- Обратная связь
Убедиться что email-уведомления приходят.
- Step 4: Проверить производительность
# Установить плагин кеширования (опционально)
wp plugin install wp-super-cache --activate
Проверить в Google PageSpeed Insights или Lighthouse:
-
Целевые показатели: LCP < 2.5s, CLS < 0.1
-
Шрифты загружаются с
font-display: swap -
Изображения оптимизированы
-
Step 5: Создать страницы юридических документов
wp post create --post_type=page --post_title='Политика конфиденциальности' --post_name='privacy-policy' --post_status=publish
wp post create --post_type=page --post_title='Согласие на обработку персональных данных' --post_name='consent' --post_status=publish
Заполнить юридический текст (предоставляется заказчиком).
- Step 6: Финальный коммит
git add themes/bitwms-child/
git commit -m "chore: final polish - responsive fixes, performance, legal pages"