Search page: full-text query UI and results #32

Closed
opened 2026-04-29 23:56:26 +02:00 by myrmidex · 0 comments
Owner

Goal

A public search page at / (or /search) where users enter a query and get ranked results from the pages table.

Acceptance criteria

  • Route + Livewire component (or plain Blade + controller — decide at implementation time)
  • Query input: plainto_tsquery(:config, :q) against keywords_tsv, config from user's detected language or a language selector
  • Results: URL, title, ts_rank(keywords_tsv, query) score — ordered by rank desc, paginated (10/page)
  • Only pages with status = fetched and non-null keywords_tsv appear in results
  • Empty query → no results, no DB hit
  • No results → friendly empty state message
  • Basic XSS safety: query term reflected in UI must be escaped (Blade does this by default with {{ }})
  • Tests: feature test hitting the search route with seeded keywords_tsv rows (requires real PG), asserting results appear in correct rank order

Notes

  • Language for plainto_tsquery config: default to simple until a language selector is built; simple works across all languages (no stemming, but correct matches)
  • Ranking: ts_rank only for v0.2. Link-count signal (inbound page_links count) deferred to a follow-up once we have enough indexed pages to validate it adds value.
  • Pagination: Laravel's paginate() works fine; simplePaginate() is cheaper if we don't need total count.
## Goal A public search page at `/` (or `/search`) where users enter a query and get ranked results from the `pages` table. ## Acceptance criteria - [ ] Route + Livewire component (or plain Blade + controller — decide at implementation time) - [ ] Query input: `plainto_tsquery(:config, :q)` against `keywords_tsv`, config from user's detected language or a language selector - [ ] Results: URL, title, `ts_rank(keywords_tsv, query)` score — ordered by rank desc, paginated (10/page) - [ ] Only pages with `status = fetched` and non-null `keywords_tsv` appear in results - [ ] Empty query → no results, no DB hit - [ ] No results → friendly empty state message - [ ] Basic XSS safety: query term reflected in UI must be escaped (Blade does this by default with `{{ }}`) - [ ] Tests: feature test hitting the search route with seeded `keywords_tsv` rows (requires real PG), asserting results appear in correct rank order ## Notes - Language for `plainto_tsquery` config: default to `simple` until a language selector is built; `simple` works across all languages (no stemming, but correct matches) - Ranking: `ts_rank` only for v0.2. Link-count signal (inbound `page_links` count) deferred to a follow-up once we have enough indexed pages to validate it adds value. - Pagination: Laravel's `paginate()` works fine; `simplePaginate()` is cheaper if we don't need total count.
myrmidex added this to the v0.2 milestone 2026-04-29 23:56:26 +02:00
myrmidex self-assigned this 2026-04-29 23:56:26 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lvl0/trove#32
No description provided.