Проекты05 / 05

Двадцатилетняя история промоутера переехала с темы на Drupal, которая всё ещё раздавала стили для IE6: три языка за двадцать дней коммитов, и в октябре 2026 архив по-прежнему пополняется на фронтенде, который в последний раз менялся в феврале 2024.

artforte.lv

Главная страница ArtForte с красным занавесом и монограммой AF
artforte.lv — первый экран.
Клиент
ART Forte, латвийская продюсерская компания
Роль
Разработка: сайт, контент-модель, CMS
Период
Сделано в январе 2023; фронтенд последний раз менялся в феврале 2024
Стек
Next.js, TypeScript, Strapi 4, PostgreSQL, S3, Vercel, Heroku
Онлайн
artforte.lv

ART Forte привозит в Латвию международную оперу, балет, театр и концерты, по собственным словам, с 2005 года. В архиве — первый концерт Анны Нетребко в Балтии и Хосе Каррерас в 2008 году.

В декабре 2022 эта история жила на сайте на Drupal, который всё ещё отдавал style.ie6.css, и на двух языках. Компании, работающей с международными продюсерами, нужно обратное.

Три задачи: рассказать посетителям, что идёт, и отправить их на нужную страницу билетов на их языке; показать двадцать лет постановок как архив, который можно листать; и отдать каждое слово на сайте, вплоть до подписей на кнопках, в руки клиента.

  1. 01

    Публичный сайт на трёх языках

    Латышский, английский и русский: одиннадцать маршрутов на каждом. Списки статические с окном регенерации в пять минут, детальные страницы рендерятся по запросу.

  2. 02

    Контент-модель, а не самописная админка

    Шесть типов контента в Strapi, 85 полей, из них 67 локализованы. Сама админка стандартная, намеренно: работа здесь в модели. Каждая подпись — поле в CMS, поэтому текст кнопки можно поменять на трёх языках без деплоя.

  3. 03

    Событие, которое само уходит в архив

    Предстоящие события и архив — одна таблица, разделённая по дате. На следующий день после показа событие переходит в архив, а место, дата, цена и кнопка Buy Ticket исчезают с его страницы. Никому ничего делать не нужно.

  4. 04

    Ссылки на билеты по языкам

    Запись на каждом языке ведёт на нужную страницу у билетного вендора. Ни чекаута, ни данных карт, ни остатков для синхронизации: вендор продолжает делать своё дело. Цена этого — воронку после клика не видно.

  5. 05

    Двадцать лет, которые можно листать

    88 записей на латышском, 86 на русском, 82 на английском, с 2006 по 2026 год. Перевод для каждой записи необязателен, поэтому постановка может существовать на одном языке и отсутствовать на другом, не оставляя дыры в сетке.

Как это устроено

  1. Редакторы

    • Strapiтри языка, 85 полей
    • S3афиши и фото
  2. Данные

    • PostgreSQL
    • Одна таблица Eventразделена по дате
  3. Сайт

    • Next.js на Vercel
    • Регенерациякаждые 5 минут
  4. Посетитель

    • Афиша и архив
    • Билетный вендордиплинк под каждый язык
Прежний сайт ArtForte, тема на Drupal, снимок декабря 2022
До: сайт на Drupal в декабре 2022, из Wayback Machine.
Сетка архива ArtForte с прошедшими постановками
Архив: двадцать лет в одной сетке по датам.

То, что обычно не попадает в портфолио. Всё это было на самом деле, и всё это есть в истории коммитов.

  1. Сбой 01

    Одна картинка, четыре шлюза, 30 коммитов за пять дней

    Симптом
    Картинки, загруженные в CMS, показывались не всегда. Сюда за пять дней ушло 22% всех коммитов проекта, с заголовками «Fix Image url», «1», «2», «3», «final», откат на следующее утро, «4», «Hardcode domain url».
    Причина
    Единого бага не было. Фото проходит четыре независимо настроенных шлюза, и каждый отказывал по-своему: собственная политика безопасности админки, права объекта на S3, форма URL (фронт дописывал хост к URL, которые уже были абсолютными) и allow-list картинок в Next. Девять часов один конфиг читал AWS_BUCKET, а другой AWS_BUCKET_NAME. Это прочтение по диффам; коммиты об этом молчат.
    Решение
    Шлюзы исправлены по очереди, потом появился ImageWithFallback: сломанная картинка показывает продуманную заглушку вместо битой иконки. Headless-стеки переносят отказы в стыки: каждая часть работала сама по себе, и ни один конфиг не отвечал за «фото появилось».
  2. Сбой 02

    Патч аналитики, отключивший React

    Симптом
    Коммит с заголовком «Fix ui», апрель 2023. Весь его дифф возвращает один элемент в _document.tsx.
    Причина
    Накануне вечером при добавлении Google Tag Manager вместе со сниппетом, который он заменял, был удалён <NextScript/>. Этот элемент несёт данные для гидратации, поэтому React никак не мог подхватить HTML сервера: бургер, переключатель языка, Load More и форма рассылки были бы мертвы. Симптом говорил об интерфейсе, а причина была в маркетинговых инструментах.
    Решение
    Одна строка, восстановлена через 19 часов 44 минуты. Сбой был бы некрасивым, но сайт бы не погас: страницы пререндерятся, так что контент и ссылки переживают отсутствие JavaScript. Ни один тест не мог бы этого поймать, потому что тестов не было.
  3. Сбой 03

    Архив, который год показывал 2008-й

    Симптом
    Блок архива на главной начинался с самых старых постановок, а не с последних. Wayback Machine это подтверждает: четыре постановки 2008 года в феврале 2023, те же четыре в июле, через день после крупного концерта.
    Причина
    sort[0]=date по умолчанию сортирует по возрастанию. Это написано за одиннадцать дней до того, как попали исторические записи, когда порядок ещё не был виден. А выжило потому, что выглядит правдоподобно: стена великих имён 2008 года читается как кураторский выбор, а не как баг.
    Решение
    date:desc, через 372 дня. Чтобы баг на сайте с большим объёмом данных заметили, данные должны стать видимыми, а смотреть на них должен тот, кто их знает.
  4. Сбой 04

    Перевод — это строка, а не столбец

    Симптом
    Переключатель языка не мог попасть на нужный перевод детальной страницы. В новостях и архиве после смены языка на экране оставались карточки предыдущего языка.
    Причина
    Две ловушки. Strapi даёт каждому переводу свой числовой id, так что одна и та же постановка — это 398, 399 и 400. А Next не перемонтирует страницу при смене локали, поэтому useState хранит список на старом языке, хотя пропсы уже изменились.
    Решение
    Переключатель читает локализации записи и подменяет id на id соседней. Списки сравнивают локаль прямо во время рендера и сбрасываются сами. Та же ловушка без перемонтирования снова встретилась на этом самом сайте, на первом экране и в чате.
  5. Сбой 05

    Последним коммитом стал процесс клиента в Instagram

    Симптом
    Карточки архива были сделаны горизонтальными. Загружаемые картинки незаметно сменились с 3861×2574 на 1080×1920, и имена файлов об этом говорили.
    Причина
    Команда начала делать один вертикальный постер для Instagram Stories и использовать его везде. Никто этого не решал; ассеты просто изменились под дизайном.
    Решение
    Новое соотношение сторон карточки в феврале 2024, последнее изменение кода фронтенда на сегодня. Последнее, что понадобилось коду, было не фичей. Ему нужно было вписаться в то, как сотрудники работают на самом деле.

  • коммитов за 20 дней разработки7–26 января 2023, за 17 разных дней
  • записей архива на LV, RU, ENживой подсчёт, 30 октября 2026; с 2006 по 2026
  • языка вместо 2на старом сайте были латышский и русский
  • полей CMS локализованошесть типов контента
  • дня архив показывал 2008-йснимки Wayback против коммита с исправлением
  • месяц между последним коммитом фронтенда и самой новой записьюс февраля 2024 по 1 октября 2026

Пульс проекта

Каждый коммит в репозиториях проекта на одной линии. Чем выше столбик, тем жарче было.

дек. 2022 г.апр. 2025 г.
  1. Каркас и план на Firebase, проживший месяц
  2. Старт разработки: 114 коммитов за 20 дней
  3. «Fix ui»: патч Tag Manager
  4. Архив научился сортировать
  5. Последний коммит фронтенда: пропорции постера
  6. CMS переезжает на другой хостинг без единого изменения фронтенда

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

Написать бриф

Быстро отвечаю в WhatsApp и Telegram

Или спросите о нём цифровой разум
Следующий кейсWinningBy AI