testfly.me: полигон, на котором мы обкатываем решения, и издание о парапланерной технике
Сайт, который зарабатывает право на технологию: 105 тест-драйвов на двух языках отдаются статикой, а модули, выросшие здесь, уже работают у клиентов.

Полигон
testfly.me — наш собственный сайт, и это его главная ценность для работы. Здесь нет заказчика, которого нужно уговаривать на эксперимент, нет согласований и нет необходимости в «давайте сделаем как обычно». Поэтому мы смело пробуем новые решения тут, на настоящем сайте с настоящими посетителями, и только потом предлагаем их клиентам.
Правило простое: в клиентские проекты уходит то, что пережило здесь хотя бы год. Не пережило — значит, идея была красивой только на бумаге, но клиенты никогда об этом не узнают ;)
И в то же время testfly.me — это много больше, чем безопасная «песочница». Это полноценное двуязычное издание о парапланерной технике: подробные тест-драйвы крыльев, подвесок и приборов, которые пишутся с 1996 года и никем не оплачиваются.
Что было обкатано здесь
OutputTransformer. Модуль, который приводит в порядок готовый HTML: убирает лишние пробелы и переносы, расставляет типографику, делает замены. Первый коммит — в этом репозитории, 24 декабря 2025 года. За девять месяцев на живом сайте он пережил переписанную очистку, а в сентябре 2026-го мы выложили его в открытый доступ.
StaticPages. Статический кэш: ProcessWire собирает страницу один раз, дальше её отдаёт Apache обычным файлом. Проверить легко — главная отвечает с ETag и датой изменения 22 августа 2026 года, то есть PHP при обычном заходе не запускается вовсе.
Сборка фронтенда. В августе 2026 года мы заменили здесь старую связку gulp и rollup на свой пакет сборки — тот же, что теперь собирает atis.pro. Ломать сборку на собственном сайте не страшно; на клиентском — страшно.
Свои поля. Таблицы характеристик, подсчёт оценок — всё это отдельные типы полей и модулей, написанные под этот сайт и потом пригодившиеся в других.
Отчёт: оценки внутри текста


Оценку считает движок, а не автор
Общая оценка крыла — не цифра, которую кто-то поставил в конце. Тестировщик оценивает мелочи: отдельно ручки клевант, отдельно поведение на вираже, отдельно поведение на сложенном крыле. Из этих оценок складывается оценка подраздела, из подразделов — раздела, из разделов — всего аппарата.
Считает это наш модуль Marks, на сохранении страницы. Редактор нигде не вводит итог руками, и поменять его, не поменяв частные оценки, нельзя. Заодно это защита от самого себя: если общее впечатление тянет поставить крылу «девятку», а частные оценки дают 8,2 — в отчёте будет 8,2.
Короткие отчёты устроены проще: несколько оценок и одна средняя. Два шаблона, один модуль, одна и та же арифметика.
Характеристики — таблицами


Фильтр по брендам: 700 байт и ни одного запроса
В разделе с тремя десятками крыльев логотипы производителей стоят полосой над списком. Нажатие на логотип оставляет в списке только его крылья, повторное — возвращает остальные. Это и показано в ролике выше.
Никакого запроса при этом не происходит. Все карточки уже в HTML, и каждая несёт в атрибуте data небольшой JSON: бренд, сертификация, год, позиционирование. Фильтр сравнивает нужное поле и переключает карточкам класс — браузер перерисовывает список сам.
Весь файл фильтра — 699 байт после сборки. Он ничего не знает про бренды: поле берётся из атрибута ссылки, поэтому тем же кодом можно фильтровать по году или классу, не написав ни строчки.
Данные включены в html-код
<!-- each card carries what it can be filtered by -->
<div class="report item" data='{"brand":"ParAAvis","homologation":"EN B","year":2017}'>…</div>
<!-- the logo strip: the value is the link's own title -->
<a title="ParAAvis" data-filter><img src="/…/paraavis.png" alt="ParAAvis"></a>
// one call, any field of that JSON
dataFilter('.report.item', 'brand', 'ParAAvis') // or 'year', 2017 — same code Ничего, кроме разметки и одного вызова: сервер отдаёт готовый список, браузер решает, что показать.
Два языка, одно дерево страниц
Сайт живёт на двух языках: русские отчёты читают дома, английские — производители, которым интересно, что написали про их крыло. Это не два сайта и не копии: в ProcessWire второй язык — это соседние поля у той же страницы, поэтому оценки, характеристики и картинки общие, а переводится только текст.
Перевод черновиков делает встроенный в админку переводчик, дальше текст правится руками. Для технического текста про крылья это экономит вечер на отчёт, но не заменяет автора: термины парапланеризма машина переводит уверенно и неправильно.


