Developer Docs

Search Configuration

The Search Configuration panel is an admin-facing tool for managing the Meilisearch synonym dictionaries that power the Mallnline discovery engine. Malet Owners with the MANAGE_SEARCH permission can create, edit, and delete synonym groups across 7 industry verticals, push changes to the live Meilisearch index, and monitor the index reconciliation status.

NOTE

The Search Configuration is accessed from the Admin Dashboard's Search tab. All synonym mutations require the MANAGE_SEARCH permission, enforced by the backend SynonymResolver.

Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Admin Dashboard (+page.svelte)            โ”‚
โ”‚  Tab: "Search" (lazy-loaded)                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚  โ”‚         SearchConfigPanel.svelte              โ”‚ โ”‚
โ”‚  โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚
โ”‚  โ”‚ โ”‚  Synonym Panel   โ”‚ โ”‚  Actions Sidebar     โ”‚ โ”‚ โ”‚
โ”‚  โ”‚ โ”‚ (vertical tabs   โ”‚ โ”‚ (apply, reconcile)   โ”‚ โ”‚ โ”‚
โ”‚  โ”‚ โ”‚  + CRUD table)   โ”‚ โ”‚                      โ”‚ โ”‚ โ”‚
โ”‚  โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ”‚                      โ†•                            โ”‚
โ”‚     searchConfigStore.svelte.ts (Zod validation)  โ”‚
โ”‚     searchConfig.ts (GraphQL queries/mutations)   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ†• (GraphQL via gateway)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     search subgraph (SynonymResolver)             โ”‚
โ”‚     Redis + Meilisearch                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Store: `searchConfigStore.svelte.ts`

Exports pure functions and constants (no class โ€” GraphQL calls are handled by the component):

  • Zod validation โ€” validateSynonymInput() validates term + synonyms + vertical
  • Synonym parsing โ€” parseSynonymString() splits comma-separated input โ†’ lowercased array
  • Vertical constants โ€” ALL_VERTICALS, VERTICAL_LABELS, VERTICAL_ICONS

Queries & Mutations: `searchConfig.ts`

Operation Query/Mutation Backend Target
List synonyms searchSynonyms(vertical?) SynonymResolver.searchSynonyms
Create/Update setSynonymGroup(input) SynonymResolver.setSynonymGroup
Delete deleteSynonymGroup(input) SynonymResolver.deleteSynonymGroup
Apply to search applySynonyms SynonymResolver.applySynonyms
Reconciliation status reconciliationStatus ReconciliationResolver.reconciliationStatus
Trigger reconciliation triggerReconciliation ReconciliationResolver.triggerReconciliation

Component: `SearchConfigPanel.svelte`

Two-column layout:

  1. Synonym Panel (left)

    • Vertical pill tabs (7 industries with emoji icons)
    • Inline add form: term input + comma-separated synonyms + "Add" button
    • Synonym table: each row shows term badge + synonym chips + edit/delete buttons
    • Inline edit mode: replaces chips with input, Save/Cancel buttons
  2. Actions Sidebar (right)

    • Apply to Search card: pushes all synonym groups to Meilisearch
    • Reconciliation card: status (running/idle), last run stats, manual trigger button

Verticals

Vertical Icon Example Synonyms
General ๐ŸŒ shop โ†’ store, malet, boutique
Restaurant ๐Ÿฝ๏ธ takeout โ†’ takeaway, carry out, to go
Tour & Safari ๐Ÿ”๏ธ safari โ†’ game drive, wildlife tour, bush trip
Photography ๐Ÿ“ธ session โ†’ booking, appointment, sitting
Fashion ๐Ÿ‘— clothing โ†’ apparel, garments, wear, attire
Wellness ๐Ÿง˜ spa โ†’ wellness center, treatment, massage
Entertainment ๐ŸŽญ concert โ†’ show, performance, gig, live music

Each vertical has its own isolated synonym dictionary in Redis (search:synonyms:{VERTICAL}), preventing cross-domain pollution (e.g. "session" in photography doesn't affect restaurant results).

Apply Workflow

When "Apply Synonyms" is clicked:

  1. All synonym groups across all verticals are fetched from Redis
  2. Groups are merged into a bidirectional synonym map
  3. The map is pushed to the Meilisearch index via updateSynonyms()
  4. Success banner shows total groups applied

Reconciliation

The reconciliation system ensures the Meilisearch index stays in sync with MongoDB source data.

Field Description
isRunning Whether a reconciliation is currently in progress
lastRunAt ISO timestamp of the last completed run
added Documents added to the index
removed Orphaned documents removed
unchanged Documents already in sync
errors Errors encountered during the run
durationMs Total reconciliation duration in milliseconds

File Map

File Purpose
src/lib/queries/searchConfig.ts GraphQL queries/mutations + TypeScript types
src/stores/searchConfigStore.svelte.ts Zod validation, parsing, vertical constants
src/lib/components/admin/SearchConfigPanel.svelte Two-column admin UI
src/routes/admin/+page.svelte Search tab integration
tests/searchConfigStore.test.ts 14 unit tests