Поле, яке гасить вісь, а не перелічує знайдене
Заморожений контракт пошуку розконсервовано: фільтри скасовано, додано український стемер, а сам пошук повернувся шаром над віссю — за 2426 байтів JavaScript.
Пошук стояв під шапкою відтоді, як репозиторію було чотири дні: модуль, якого ніхто не імпортував, збережений і покритий тестами навмисно, під правилом проєкту, що забороняло і видаляти його, і видавати пошук за доступний. Цей прохід зняв шапку у два кроки — спершу контракт, потім те, чим читач може користуватися.
Фільтри не побудовано, а скасовано
Заморожений модуль мав дві половини. Одна — пошук по тексту; друга — набір фільтрів: обрати організації, обрати людей, АБО всередині групи та І між групами, з обходом зв’язків owned_by і developed_by, щоб вибір компанії захоплював і зроблені нею моделі.
Фільтри пішли. Не відкладено вкотре — скасовано. Читач, який шукає OpenAI, друкує «OpenAI»; він не відкриває форму, щоб знайти організацію в списку з кількох сотень і поставити позначку. Ті самі імена в пошуковому тексті роблять ту саму роботу взагалі без інтерфейсу, а обхід графа існував лише заради фасетів. Третя гілка шукала по tags, а колекція не має жодного: 483 записи, нуль тегів. Ця гілка ніколи нічого не знаходила.
Лишилася одна група токенів, поєднаних через І, по назвах, коротких описах та іменах, які згадує запис.
Індексу немає, бо перебір і так швидший за кадр
Очевидний вибір для пошуку на статичному сайті — Pagefind, а до нього MiniSearch, FlexSearch, Fuse чи Orama. Жоден тут себе не виправдовує.
483 записи відповідають на запит із чотирьох токенів за 0,07 мс простим перебором. Префіксне дерево чи таблиця BM25 купили б ранжування, якого цей інтерфейс не використовує — результати тут не список, який треба впорядкувати, а позначки, що зберігають своє місце в часі, — і витратили б байти на проблему, якої немає. Pagefind був найближчим до вибору й не підійшов з іншої причини: він індексує відрендерений HTML і повертає URL сторінок. Осі потрібні ідентифікатори записів, щоб підсвітити позначки. Список посилань поруч із віссю — це друга навігація, а не пошук по першій.
Наперед обчислюється те, по чому шукають, бо стемінг — повільна половина: 12,8 мс один раз, коли приходить відкладений текст, далі 0,15–0,26 мс на натискання клавіші.
Українська — причина, чому стемер узагалі потрібен
Мова відмінює суфікс. «Модель», «моделі» й «моделями» — одне слово для читача і три для підрядкового збігу, а читач, який друкує будь-яке з них, має на увазі всі три. Англійська відмінює додаванням у кінці, що вже покриває префіксний збіг, тож для неї стемера немає.
У Snowball української немає взагалі — а це тихо відкидає Pagefind і кожного іншого споживача rust-stemmers, бо для головної мови атласу вони відкотилися б до повної відсутності стемінгу. Orama постачає стемер окремим модулем без залежностей: 731 байт у стисненому вигляді. Його вендорено байт-у-байт, а не встановлено, бо пакет несе двадцять вісім мов, щоб дати одну, і виключено з Prettier, щоб він лишався тотожним випуску, з якого прийшов.
Він приносить із собою одну річ, яку варто знати. «Роботи» — праці, у родовому відмінку — і «робот» мають спільну основу. Пошук роботів повертає записи про наукову роботу. Це те, чим стемінг є, а не хиба в підключенні; розвести їх зможе тема, за якою вісь уже розфарбована.
У розкладці не було місця, тож поле його й не займає
Панель зміряна до пікселя: нижче 420px вона вже віддала лічильник записів, нижче 380px — скидання. Сітка під нею віддає смузі кожен решту рядок, а саме це міряє прийомка першого екрана. Рядка, куди можна було б покласти поле пошуку, не забравши його в одного з цих двох, не існувало.
Тому панель плаває над смугою, кнопка, що її відкриває, нижче 420px стає гліфом, зберігаючи доступне ім’я, а результати не перелічуються взагалі. Позначки-збіги лишаються яскравими, решта падає до 22%, а підпис називає кількість. Погашена позначка — це так само запис на своїй даті, і вона так само відкривається; пошук міняє наголос, а не мапу. У списку місць зберігати нема, тож там той самий пошук прибирає рядки, а не сірить їх.
Одне видно лише на телефоні: на вузькому екрані час іде вгору, тож найновіше десятиліття — те, яким відповідає більшість пошуків, — стоїть рівно там, де плаває панель. Поки поле відкрите, смуга починається на 108px нижче. Саме відступом на кресленні, а не полем на рамці: виміряна коробка рамки керує малюванням, і її зменшення перепаковувало б кожну позначку на кожне відкриття.
Три речі, які виявив прохід
Острівець досі складав time, event і mode вручну — рівно той розхід, який шапка замороженого модуля передбачила письмово. Тепер обидва йдуть через контракт, а виклики називають лише те поле, яке змінюють.
Поле пошуку — перший текстовий ввід на цій сторінці за весь час, а вісь прив’язує звичайні друковані клавіші як команди. Набір «GPT-4» віддаляв вісь. Тепер обробник відступає всередині поля вводу — помилка, якої до цього проходу не могло існувати і яка поїхала б у прод без ручного проходу по клавіатурі.
Брама публічного артефакту навідріз відмовилася збирати, доки names не з’явилося в її дозвільному списку. Це брама, що працює як задумано: поле не залишає цю збірку лише тому, що якийсь код поклав його в проєкцію.
Чого це коштувало
2426 байтів JavaScript у стисненому вигляді за всю можливість разом зі стемером — 88 747 із бюджету 184 320. Імена сутностей додали 7036 байтів до українського data.json: 51 389 зі 122 880. LCP 1803 мс, CLS 0,026, 63 браузерні випадки зелені.
Сторінка «Про проєкт» десять днів казала «пошук і фільтри відкладено». На першому кроці її не чіпали, бо готовність контракту — не те саме, що можливість читача друкувати, а сторінка, яка заявляє про можливість, якої немає, — це єдине, чим цьому атласу бути не можна. Вона змінилася на другому кроці, тим самим комітом, який поставив поле на екран.
Запис зроблено 21 вересня 2026 р.
Коміти, про які цей запис
90711115825a78