Дизайн внутреннего поиска по сайту
Стратегия индексации, ранжирование, фасеты, поведение «ничего не найдено», UX поискового поля и страницы результатов.
Действуй как product engineer + UX-дизайнер. Спроектируй внутренний поиск для сайта. Контент: {{content_types}}. Объём: {{volume}}. Аудитория: {{audience}}. Сейчас: {{current_state}}.
Цель — поиск, который НЕ «filter by title», а реальная находка с релевантной выдачей за < 200ms.
Часть 1 — Стратегия индексации
Что индексировать
- Per content type — таблица:
Type | Fields indexed | Boost | Filterable - Например, для статьи: title (boost 5), description (boost 3), body (boost 1), tags (boost 4, filterable)
- Для продукта: name (5), category (4 filterable), description (2), spec_text (1)
Когда переиндексировать
- При публикации / редактировании — webhook → index в реальном времени
- Раз в сутки — полная переиндексация для надёжности
- При изменении схемы — версионирование индексов и blue/green switch
Чем индексировать
- Развилка: managed (Algolia, Typesense Cloud, Meilisearch Cloud) vs self-hosted (Meilisearch, Typesense, Elasticsearch)
- Критерии выбора: объём, бюджет, latency требования, команда
Часть 2 — Ранжирование
Базовый порядок (по убыванию веса):
- Exact title match
- Fuzzy title match (typo-tolerance)
- Tag / category match
- Body match с phrase proximity
- Popularity signal (просмотры за 30 дней)
- Recency (newer wins, если equal score)
Дополнительные сигналы
- Personalisation: user history (если логин) — boost того типа контента, который пользователь чаще читает
- Geo: для e-commerce — boost локально доступного товара
- A/B testing: разные ranking-формулы на разные cohort
Часть 3 — Фасеты (faceting)
Когда показывать:
- Только если результатов > 10
- Только если есть смысл фильтровать (для статьи: тип, дата, тег; для продукта: цена, бренд, цвет, размер)
Поведение:
- Фасеты обновляются по результатам текущего запроса (counts рядом)
- Multi-select: cmd/ctrl+click для добавления, не замены
- "Clear all" button сверху если активны фильтры
- Mobile: фасеты в bottom-sheet, не sidebar
Часть 4 — UX поискового поля
- Расположение: top-bar, всегда видим
- Hotkey: cmd+k / ctrl+k (документировано в плейсхолдере: «Search (⌘K)»)
- Plaeholder подсказывает scope: «Search docs» а не «Search»
- Autocomplete на 200ms typing pause:
- Top 5 results с превью
- "Recent searches" если поле пусто
- "Popular searches" если нет recent
- Esc закрывает, Enter переходит на полную страницу результатов
Часть 5 — Страница результатов (/search?q=...)
Структура:
- H1: "Results for '{query}'" + количество
- Левая колонка: фасеты (desktop)
- Центральная: список результатов
- Каждый результат: title (highlight match), type badge, snippet (highlight match, ±15 слов от первого совпадения), url breadcrumb
- Pagination или infinite scroll (зависит от типа — для docs pagination, для feed infinite)
- URL state: query, фильтры, page — всё в query string для shareable links
Часть 6 — Поведение «ничего не найдено»
НЕ просто «No results». Делай так:
- «No exact matches for '{query}'»
- Suggest: «Did you mean: ...» (если есть close terms через Levenshtein)
- Show: «Popular topics» — 5 топ-результатов по сайту
- Show: «Browse by category» — линки на основные разделы
- CTA: «Contact support» или «Suggest a topic» (для docs)
- НИКОГДА не показывай пустой экран без выхода
Часть 7 — Performance
- Search response: p95 < 200ms
- Autocomplete: p95 < 100ms
- Initial bundle для search UI: < 30 KB gzipped
- Lazy-load: search UI грузится только после фокуса в поле / hotkey
- Cache: typical queries в edge / CDN на 5 минут
Часть 8 — Analytics
Отслеживай:
- Queries без результатов (топ-50 — это roadmap для контента)
- Queries с CTR 0 (есть результаты, но никто не кликает — плохая релевантность)
- Average time-to-click
- % searches → conversion
Dashboard еженедельно: топ-50 «zero results», топ-50 «high volume, low CTR».
Часть 9 — Edge cases
- Очень короткие запросы (1-2 char): autocomplete только если popular, не fire полный поиск
- Очень длинные запросы (> 100 char): обрезать, показать предупреждение
- Спец-символы: эскейп, не падать
- Multi-language: язык запроса определяется → ищем в соответствующем индексе
Anti-patterns
- ❌ Поиск = LIKE %q% в БД — медленно и нерелевантно
- ❌ Один индекс для всех типов контента без типа в выдаче
- ❌ Фасеты для 5 результатов — занимают экран, бесполезны
- ❌ «No results» без альтернатив — пользователь уходит
- ❌ Autocomplete без debounce — запрос на каждую букву
- ❌ URL без query string — поделиться поиском нельзя
- ❌ Highlight matches не работает с typo-tolerance
- ❌ Поиск без аналитики — нет данных для улучшения
- ❌ Гнаться за «AI-powered semantic search» когда BM25 + synonyms покрывают 80% кейсов
Полный UX-аудит сайта
Эвристическая оценка по Нильсену + проверка ключевых сценариев. На выходе — приоритизированный список проблем.
Технический SEO-аудит
Crawl, индексация, мета-теги, sitemap, robots, schema.org и Core Web Vitals в одном отчёте.
Стартовать новый Next.js проект
Создание Next.js приложения с разумными настройками: App Router, TypeScript, Tailwind, базовые компоненты, SEO.