# Экспертный портал БИТ.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
```bash
# Если используем 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: Установить и активировать обязательные плагины**
```bash
# Премиум-плагины устанавливаются вручную (загрузка 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**
```bash
# Постоянные ссылки: /%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-репозиторий**
```bash
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`:
```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
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
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`:
```javascript
/**
* Боковая навигация — 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: Подготовить директории для ассетов**
```bash
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: Активировать дочернюю тему и проверить**
```bash
wp theme activate bitwms-child
```
Открыть `http://bitwms.local` — тема должна активироваться, стили брендбука (цвета, шрифты) должны применяться.
- [ ] **Step 7: Коммит**
```bash
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
'БИТ.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);
?>
```
- [ ] **Step 3: Добавить CSS боковой панели**
Добавить в конец `wp-content/themes/bitwms-child/style.css`:
```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` (перед закрывающим `?>` или в конец):
```php
// Вставка боковой панели после
add_action('generate_before_header', function () {
get_template_part('templates/sidebar-nav');
});
```
- [ ] **Step 5: Проверить боковую панель**
Открыть `http://bitwms.local`:
- На десктопе: боковая панель 70px слева с иконками, при наведении раскрывается до 250px с подписями
- На мобильном (< 768px): панель скрыта, виден гамбургер, по клику панель выезжает с оверлеем
- Основной контент сдвинут вправо на 70px
- [ ] **Step 6: Коммит**
```bash
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`:
```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):
```html
```
- [ ] **Step 2: Добавить CSS хедера**
Добавить в `style.css`:
```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: Коммит**
```bash
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
[
'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`:
```php
$bitwms_includes = [
'inc/enqueue.php',
'inc/cpt.php',
];
```
- [ ] **Step 3: Обновить permalink и проверить**
```bash
wp rewrite flush
```
В админке WP: проверить что в меню появились разделы "Кейсы", "Вебинары", "Курсы", "Мероприятия", "Материалы".
Создать рубрики для стандартных постов:
```bash
wp term create category "Статьи" --slug=articles
wp term create category "Новости" --slug=news
```
- [ ] **Step 4: Коммит**
```bash
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
'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`:
```php
$bitwms_includes = [
'inc/enqueue.php',
'inc/cpt.php',
'inc/acf-fields.php',
];
```
- [ ] **Step 3: Проверить поля в админке**
В админке WP: открыть создание нового Кейса, Вебинара, Курса, Мероприятия, Материала — проверить что все ACF-поля отображаются корректно с нужными типами и условной логикой (например, "Запись видео" появляется только при статусе "Прошёл").
- [ ] **Step 4: Коммит**
```bash
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
Всё о складской логистике и автоматизации склада
Экспертный портал от Первого Бита — кейсы, вебинары, курсы и материалы для руководителей складов
200+
проектов внедрения
15+
лет опыта в WMS
50+
экспертов в команде
```
- [ ] **Step 3: Добавить CSS героя**
Добавить в `style.css`:
```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: Коммит**
```bash
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
```
- [ ] **Step 2: Создать блок подписки**
Создать файл `wp-content/themes/bitwms-child/templates/section-subscribe.php`:
```php
```
- [ ] **Step 3: Создать блок клиентов**
Создать файл `wp-content/themes/bitwms-child/templates/section-clients.php`:
```php
'Клиент 1', 'logo' => ''],
['name' => 'Клиент 2', 'logo' => ''],
['name' => 'Клиент 3', 'logo' => ''],
['name' => 'Клиент 4', 'logo' => ''],
['name' => 'Клиент 5', 'logo' => ''],
['name' => 'Клиент 6', 'logo' => ''],
];
?>
```
- [ ] **Step 4: Добавить CSS для всех трёх блоков**
Добавить в `style.css`:
```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: Коммит**
```bash
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
'all', 'label' => 'Все'],
['slug' => 'post', 'label' => 'Статьи'],
['slug' => 'case', 'label' => 'Кейсы'],
['slug' => 'webinar', 'label' => 'Вебинары'],
['slug' => 'course', 'label' => 'Курсы'],
['slug' => 'event', 'label' => 'Мероприятия'],
['slug' => 'material', 'label' => 'Материалы'],
];
?>
['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;
?>
found_posts > 6) : ?>
Показать ещё
```
- [ ] **Step 2: Создать универсальную карточку контента**
Создать файл `wp-content/themes/bitwms-child/templates/content-card.php`:
```php
'Статья',
'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;
}
}
}
?>
```
- [ ] **Step 3: Создать AJAX-обработчик**
Создать файл `wp-content/themes/bitwms-child/inc/ajax-filter.php`:
```php
$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`:
```javascript
/**
* 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`:
```php
$bitwms_includes = [
'inc/enqueue.php',
'inc/cpt.php',
'inc/acf-fields.php',
'inc/ajax-filter.php',
];
```
Обновить `inc/enqueue.php` — добавить скрипт и локализацию:
```php
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`:
```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: Коммит**
```bash
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
БИТ.WMS
Комплексное решение для управления складом
БИТ.WMS — это полнофункциональная система управления складом от компании «Первый Бит». Автоматизирует все складские процессы: от приёмки до отгрузки, с полным контролем на каждом этапе.
Функции БИТ.WMS
'Приёмка', '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) : ?>
Почему Первый Бит
Быстро
Мы — профессионалы, знаем бизнес-задачи склада и процессы. Запускаем проекты за недели.
Просто
Знаем все о WMS-решениях и имеем собственный программный продукт БИТ.WMS.
Качественно
Первый Бит — это результат. 200+ успешных проектов, многолетний опыт.
Открыто
Прозрачная ценовая политика. Понятные сроки и этапы внедрения.
Кейсы внедрения
'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 : ?>
Кейсы скоро появятся.
Все кейсы
Возможно, вам будет интересно
1C:WMS Логистика
Управление складом на платформе 1С
Клеверенс
Мобильная автоматизация склада
1C:TMS
Управление транспортной логистикой
Кейсы
'←',
'next_text' => '→',
]); ?>
Другие кейсы
'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;
?>
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`:
```javascript
/**
* 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`:
```php
// Модальное окно gated-контента
add_action('wp_footer', function () {
?>
×
Скачать материал
Укажите ваши данные для получения доступа к материалу
Popup Maker > Add New:
**Попап "Exit-intent — Подписка":**
- Содержимое: "Не уходите! Подпишитесь на экспертные материалы по складской логистике" + форма email
- Триггер: Exit Intent
- Условия: все страницы
- Настройки: показывать 1 раз за сессию
**Попап "Таймер — Демо":**
- Содержимое: "Хотите увидеть БИТ.WMS в действии?" + CTA "Заказать демо"
- Триггер: Time Delay — 60 секунд
- Условия: только страница БИТ.WMS
- Настройки: показывать 1 раз за сессию
- [ ] **Step 2: Подключить JivoSite**
Добавить в `functions.php`:
```php
// JivoSite — виджет онлайн-консультанта
add_action('wp_footer', function () {
// Подставить реальный widget_id из кабинета JivoSite
?>
Проактивные приглашения), указать страницы: главная, /bit-wms/, /cases/.
- [ ] **Step 3: Подключить callback-виджет**
Добавить в `functions.php`:
```php
// Callback-виджет
add_action('wp_footer', function () {
// Подставить реальный код виджета из кабинета callback-hunter или аналога
?>
SEO > General:
- Указать название организации: "Первый Бит"
- Schema.org: тип организации — Company
- Social: указать ссылки на VK, Telegram
Для каждой страницы/записи: заполнить SEO-заголовок и мета-описание.
- [ ] **Step 6: Проверить все виджеты**
- JivoSite виджет отображается в правом нижнем углу
- Попап exit-intent срабатывает при уходе с сайта
- Попап таймера появляется через 60 сек на странице БИТ.WMS
- [ ] **Step 7: Коммит**
```bash
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: Проверить производительность**
```bash
# Установить плагин кеширования (опционально)
wp plugin install wp-super-cache --activate
```
Проверить в Google PageSpeed Insights или Lighthouse:
- Целевые показатели: LCP < 2.5s, CLS < 0.1
- Шрифты загружаются с `font-display: swap`
- Изображения оптимизированы
- [ ] **Step 5: Создать страницы юридических документов**
```bash
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: Финальный коммит**
```bash
git add themes/bitwms-child/
git commit -m "chore: final polish - responsive fixes, performance, legal pages"
```