Как я перевёл два сайта компании с MODX на Nuxt

Зачем небольшим сайтам-витринам отказываться от CMS, как перенести контент без потерь и настроить выкладку на свой сервер одной командой git push.

Кейс~7 мин чтения
Главная страница сайта AS Better после переезда на Nuxt

У компании AS Better два направления и два сайта: мебель на заказ и ремонт торговых помещений. Оба я сделал на MODX в 2024 году, а в сентябре 2026-го перевёл на Nuxt. Рассказываю, почему отказался от CMS, что пришлось решить по дороге и что получилось в итоге.

Почему CMS оказалась лишней

Оба сайта по сути витрины: несколько страниц, галерея работ, форма заявки. Контент меняется несколько раз в год. При этом MODX требовал PHP, базу данных, обновления безопасности и резервные копии — целый слой обслуживания ради админки, которой почти не пользовались.

Статическая сборка на Nuxt снимает этот слой целиком: сайт собирается из репозитория, базы данных нет, обновлять нечего, кроме зависимостей проекта. Поводом вернуть CMS я для себя записал одно условие: если появится раздел, который нужно обновлять чаще раза в месяц силами не-разработчика. И даже тогда это будет headless-CMS поверх той же сборки, а не возврат к MODX.

Что перенести без потерь

  • Тексты, структуру разделов и оформление — посетитель не должен заметить переезда.
  • Файлы подтверждения прав в Яндекс Вебмастере и Google Search Console — иначе права на сайт в вебмастерах слетят.
  • Адреса страниц — чтобы не потерять позиции в поиске.

Контент без админки

Для мебельного сайта контент живёт в коде: типизированные массивы TypeScript. Пример работы — это объект с номером, названием, материалами и количеством фотографий. Добавить работу — значит дописать объект и положить фотографии в папку. Опечатку в поле ловит TypeScript ещё до сборки.

export const examples: ExampleWork[] = [
  {
    id: 1,
    count: 10,
    title: 'Кухня, МДФ эмаль с фрезеровкой',
    materials: ['Фасады — МДФ эмаль 22 мм', 'Корпус — Egger']
  }
]

У сайта по ремонту портфолио растёт быстрее — уже 21 объект в 9 городах. Там я взял Nuxt Content: каждый бренд — отдельный markdown-файл со списком объектов, а страница бренда с видео и постерами собирается из этих данных автоматически. Новый объект — одна запись в файле, без правки шаблонов.

Свои компоненты вместо библиотек

Карусель фотографий с листаемой лентой миниатюр и полноэкранным просмотром я написал сам — это пара небольших компонентов без внешних зависимостей. А четыре раздела мебельного сайта (материалы, фурнитура, мойки, техника) устроены одинаково, поэтому их обслуживает один универсальный компонент страницы-списка: сама страница сводится к массиву данных и одной строке шаблона.

Выкладка одной командой

Сайты живут на собственном сервере, без облачных платформ. Выкладка устроена так: git push в репозиторий на сервере запускает хук, который собирает проект, копирует готовую сборку в каталог сайта и перезапускает процесс Node.js. Перед сайтом стоит nginx.

  • Сборка идёт во временном каталоге и удаляется после выкладки — на сервере не копятся старые версии.
  • Фото и видео не хранятся в git: они лежат рядом со сборкой и отдаются nginx напрямую, а синхронизируются отдельной командой.
  • Есть тестовая копия сайта на поддомене для показа незаконченного. От индексации она закрыта трижды: robots.txt, заголовок X-Robots-Tag и пароль — дубли в поиске стоили бы позиций основному сайту.

SEO после переезда

sitemap.xml и robots.txt теперь генерируются автоматически, адрес сайта задаётся одной настройкой — переезд на другой домен сводится к смене переменной окружения. На тестовой копии счётчики аналитики отключены, чтобы тестовые визиты не портили статистику.

Итог

Из стека ушли PHP, база данных и админка. Контент по-прежнему легко обновлять, выкладка — одна команда, а заявки с обоих сайтов приходят в одно место. О том, как устроен общий обработчик заявок, — в отдельной статье.

Кейс в портфолиоAS BetterСмотреть кейс

Есть похожая задача?

Свяжитесь со мной — обсудим ваш проект.