# Frontend JS Architecture ## Цель - Держать `public/js/main.js` минимальным entrypoint. - Делить код по фичам, а не по страницам. - Снижать связность и дублирование. ## Структура - `public/js/main.js` — только импорты и вызовы `init*`. - `public/js/modules/theme/*` — тема и панель стилей. - `public/js/modules/header/*` — шапка, скролл, overflow-навигация. - `public/js/modules/experience/*` — masonry, expand, hover-эффекты. - `public/js/modules/mini-projects/*` — masonry и раскрытие секции мини-проектов. - `public/js/modules/cases/*` — медиалогика кейсов. - `public/js/modules/ui/*` — локальные UI-фичи (копирование, cookie, hero и т.д.). - `public/js/modules/shared/*` — переиспользуемые утилиты. ## Правила зависимостей - Разрешено: `feature -> shared`. - Нежелательно: `feature -> feature`. - Запрещено: циклические зависимости. - Если логика нужна в 2+ фичах, переносить ее в `shared`. ## Соглашения по именованию - Инициализаторы: `initFeatureName`. - Файлы с разделением ответственности: - `*-core.js` — состояние, вычисления, чистая логика. - `*-controls.js` — DOM и события. - Утилиты: короткие имена по области (`math.js`, `media.js`, `dom.js`). ## Контракт для init-функций - Функция должна быть безопасной на любой странице. - Если нужного DOM нет, делать ранний `return`. - Не бросать исключения при отсутствии опциональных API браузера. - По возможности избегать глобального состояния. ## Как добавить новую фичу 1. Создать модуль в нужной feature-папке, например `public/js/modules/ui/new-feature.js`. 2. Экспортировать `initNewFeature`. 3. В `public/js/main.js`: - добавить `import { initNewFeature } ...`; - вызвать `initNewFeature()` в блоке инициализации. 4. Если часть кода переиспользуется, вынести в `public/js/modules/shared/*`. ## Минимальный шаблон фичи ```js export function initNewFeature() { const root = document.querySelector("[data-new-feature]"); if (!root) return; // logic } ``` ## Чеклист перед PR - Проверить базовый smoke на страницах с этой фичей. - Проверить `prefers-reduced-motion`, если есть анимации. - Проверить resize/scroll сценарии, если есть геометрические вычисления. - Проверить доступность: `aria-*`, keyboard-only навигация, Escape/Focus. ## Source/Build/Public для HTML - `src/partials/*.html` — source of truth для общих блоков (header, fab, projects, contact, footer, cookie и т.д.). - `src/pages/**/*.html` — source of truth для страниц с include-маркерами `{{> partial-name }}`. - `public/assets/**` — картинки, видео, иконки сайта (редактируются вручную; сборка страниц их не копирует). - `public/**/*.html` — только build-артефакт; руками не редактируем. Эталон HTML-блоков для лонгрида кейса и порядок partials: **`docs/case-page-blocks.md`** (исходник-пример: `src/pages/cases/template-elements-demo.html`). ### Сборка страниц - Команда: `npm run build:pages`. - Скрипт: `scripts/build-pages.mjs`. - Скрипт подставляет partials и переменные пути: - `{{assetPrefix}}` (`""` для корня, `../` для `cases/*`), - `{{casesPrefix}}` (`cases/` для корня, `""` для `cases/*`). ### Правило перед выкладкой - Перед публикацией на хостинг всегда запускать `npm run build:pages` (или `npm run build`).