Skip to Content
Global SearchGlobal Search

Global Search

[Live] — Fully implemented April 2026. Typesense container, search-indexer worker, Fastify routers, Next.js API routes, and GlobalSearch UI are all running in production.

Overview

Global Search provides a unified, typo-tolerant, cross-entity search experience across all three portals (Dashboard, DM, Manage). Users invoke it with Ctrl+K from anywhere in the application and get instant results across blogs, contacts, campaigns, activities, and twelve other entity types.

The search engine is Typesense — a self-hosted, open-source engine that stores its own indexed copy of the data and returns ranked results in under 10ms. PostgreSQL remains the source of truth; Typesense is a read replica for search only.


Documents in This Section

FileContents
architecture.mdCollections schema, sync strategy, multi-tenant isolation, API contract
implementation.mdPackages to create, file structures, code patterns, where to add sync calls
ui.mdGlobalSearch component, Ctrl+K modal design, portal integration

Design Decisions

DecisionChoiceReason
Search engineTypesenseTypo-tolerance, ranked results, federation search, simple Docker deploy
Sync strategyBullMQ (event-driven)Fits existing queue architecture; retries handle Typesense downtime
Initial indexFresh writes onlyAvoids bulk-import complexity at launch; historical data indexed as records are updated
API layerFastify proxyJWT validated server-side; tenantId filter injected by API — Typesense key never exposed to browser
Multi-tenant isolationtenantId filter field on every documentSingle collection per entity type; tenant scope enforced at query time
HostingSelf-hosted Docker on DigitalOceanSame infra as everything else; Typesense Cloud can replace later with zero code changes

Scope per Portal

PortalWho uses itSearch scope
DashboardClient userTheir tenant’s entities only
DMReviewerActive tenant’s entities (cookie-gated)
ManageSuper adminCross-tenant — all entities, all tenants; each result shows tenant name

Entity Coverage

Thirteen entity types are indexed across both tenant-scoped portals and Manage:

EntityCollectionKey text fields
Blog postblogstitle, metaDescription
Social postsocial_postsbodyText, engagementHook
Landing pagelanding_pagestitle, metaDescription
Email newsletternewsletterssubject, previewText
Activityactivitieslabel, notes
Campaigncampaignsname
Content briefcontent_briefstitle, topic, angle
Contactcontactsname, email, company
Leadleadsname, company, jobTitle
Keywordkeywordskeyword
Reportreportslabel
BacklinkbacklinkssourceDomain, anchorText
Tenanttenantsname, website, pocName, industry

tenants is returned in Manage searches only. All other collections are available in Dashboard, DM, and Manage.


High-Level Flow

WRITE PATH ────────── API router / server action → writes record to Postgres (source of truth) → enqueueSearchSync({ collection, operation, recordId, tenantId }) apps/servers/search-indexer (BullMQ worker) → reads full record from Postgres → upserts / deletes document in Typesense → eventual consistency: ~100–500ms after write READ PATH ───────── User presses Ctrl+K → types query → POST /v1/search (tenant-scoped) [Dashboard / DM] → POST /v1/admin/search [Manage] Fastify search router → validates JWT, resolves tenantId → calls Typesense multi-search (1 request across all collections) → injects filter_by: "tenantId:=<id>" (tenant-scoped routes) → returns unified ranked results with deep-link hrefs GlobalSearch modal renders grouped results

Infrastructure

Typesense runs as a Docker container alongside the existing services. Add to docker-compose.yml:

typesense: image: typesense/typesense:27.1 restart: unless-stopped ports: - "8108:8108" volumes: - typesense-data:/data command: > --data-dir /data --api-key=${TYPESENSE_ADMIN_API_KEY} --enable-cors

Two environment variables are required across all services that touch Typesense:

TYPESENSE_URL=http://localhost:8108 TYPESENSE_ADMIN_API_KEY=your-admin-key-here

See env-vars.md for the full per-service breakdown.

© 2026 Leadmetrics — Internal use only