Это демонстрационная работа для портфолио, а не действующий магазин. Ниже честный список: что здесь работает по-настоящему и что придумано. Такой список — часть работы, а не оговорка: клиент должен понимать, за что он смотрит на демо.
Поиск
Индекс целиком в браузере: 320 позиций, около десяти килобайт после brotli. Конвейер запроса — нормализация, доменный словарь на 156 строк, стемминг Snowball, затем MiniSearch с порогом fuzzy по длине токена.
Транслитерация и починка раскладки применяются только как запасной вариант — если основной дал меньше трёх результатов. Иначе короткие токены превращаются в мусор и тянут в выдачу чужие категории.
Отдельная история — словарь. Snowball схлопывает падежи, но не схлопывает существительное и относительное прилагательное: «плитка» → «плитк», а «плиточный» → «плиточн». Расстояние три, fuzzy не спасает и не должен. Лемматизатор решил бы задачу, но тянет словарь на мегабайты — в браузер такое не грузят.
Фасеты
Счётчики дизъюнктивные: для группы они считаются со всеми фильтрами, кроме фильтров самой группы. Поэтому мультивыбор внутри группы работает — выбрали один бренд, у остальных остались живые числа. Библиотечные фасеты так не умеют, и это дефект, а не придирка.
Всё считается за один проход по типизированным массивам, без аллокаций на кадр. Спиннеров нет намеренно: пересчёт занимает доли миллисекунды, и любой лоадер читался бы как имитация работы.
Каталог фильтруется и с отключённым JavaScript: каждый фасет — ссылка на статически собранную страницу одного фильтра.
Расчёт
Считает раскладку, а не площадь: симметрирует ряды, соблюдает правило «подрезка не уже половины плитки», учитывает шов между полем и подрезкой, знает про выход двух кусков из одной плитки только с противоположных краёв одной оси и про то, что направленный рисунок это правило отменяет.
Клей — по таблице гребёнок, обратное намазывание отдельным слагаемым, а не множителем. Затирка — по формуле, оба контрольных примера зафиксированы тестами до третьего знака. Округление до упаковок происходит один раз и в конце. Переплата показывается всегда.
Схема рисуется одним SVG-паттерном для поля целых плиток и индивидуально только для подрезок: иначе на мозаике в браузере оказалось бы десять тысяч узлов, и телефон бы встал.
Инженерная часть
Astro в режиме чистой статики плюс острова на Svelte. React в проекте отсутствует полностью — это второе демо в портфолио, и оно доказывает гибкость после первого на Next.js.
На сервере нет ни одного процесса Node: файлы раздаёт Caddy, прекомпрессия brotli делается на сборке. Данные — YAML в репозитории; сборка валидирует ссылки и реестр характеристик, детерминированно генерирует SKU, считает упаковку и вес из размеров и плотности. Ни одна упаковка не вбита руками.
Что вымышлено
Магазин «Ведомость» не существует. Ни адресов, ни телефонов, ни реквизитов на сайте нет — и не будет.
Все 13 производителей придуманы:Кронцера, Виталит, Терракорд, Гранферо, Астраплит, Крепанит, Мельбит, Оникта, Севелит, Бореалит, Каменград, Фьорит, Ведрус. Реальные торговые марки не используются сознательно: размещение чужого знака в предложении о продаже — это использование знака по ст. 1484 ГК, а компенсация по ст. 1515 назначается судом от десяти тысяч до десяти миллионов рублей. Цена отказа — ноль рублей.
Ассортимент, остатки и цены. Ценовые коридоры взяты из открытых данных, дальше цена считается от коридора с коэффициентом тира бренда и детерминированным разбросом. Совпадения с реальными ценниками случайны.
Фактуры материалов. 89 кадров, лицензия CC0 (ambientcg, polyhaven). Кадр вырезается по физическому размеру фактуры — провайдер сообщает, сколько миллиметров поверхности покрывает текстура. Поэтому плита 600 мм выглядит плитой 600 мм, а не абстрактным узором.
Предметная съёмка. 21 кадров под лицензиями Pexels и Unsplash: гребёнка клея, торец штабеля листов, россыпь саморезов, волокно утеплителя, первый экран. Всего в проекте 21 авторов, и каждый указан в исходниках, хотя обе лицензии этого не требуют. Ни одного логотипа и ни одной брендированной упаковки в кадре: чужой знак в предложении о продаже — та же ст. 1484 ГК. Кадры, где в объектив попала читаемая этикетка или марка на перчатке, отбракованы.
Запас на случай, когда кадра нет. 5 форм упаковки начерчены в языке схемы раскладки: линия, штриховка, миллиметровая сетка. Сейчас они не нужны — предметная съёмка нашлась для всех категорий, — но если для какой-то позиции пригодного кадра не будет, она получит чертёж, а не пустой прямоугольник.
Персональные данные не собираются
Формы «оставьте заявку» с именем и телефоном здесь нет намеренно. Из расчёта можно отправить смету — только позиции, количества и сумму, без контактов. Поэтому нет ни оператора персональных данных, ни политики, ни галочки согласия: 152-ФЗ просто не возникает.
Каталог и карточки отдают noindex, follow, микроразметка ограничена WebSite и BreadcrumbList. Отдавать поисковикам Product и Offer с выдуманными ценами — прямой риск для домена, который кормит.