Three Paths
- AI Chat (easiest)
- Algolia
- Database full-text search
Describe what you want:The AI scaffolds the schema, search endpoint, and UI component.
Database Full-Text Search (PostgreSQL)
Add a search column
setweight call gives title matches more weight than body matches in ranking.Algolia Pattern
For larger sites or when you need typo-tolerance:Sign up for Algolia
Go to algolia.com, create an app. Free tier covers up to 10k searches/month.
Copy your keys
- Application ID — public identifier
- Search-only API key — safe to expose in the browser
- Admin API key — keep server-side only (used for indexing)
Search UX Best Practices
The plumbing is easy. The UX is where most search implementations fall down.- Results as user types. Debounce 300ms so you’re not hammering the API on every keystroke.
- Highlight matched terms. Bold the portions of each result that match the query. Makes relevance obvious.
- Keyboard navigation. Arrow keys to move through results, Enter to open, Escape to close.
- Zero-results state. Don’t just say “No results.” Suggest popular queries, link to browse pages, show recent posts.
- Recent searches. If the user has searched before, show recent queries when the box is empty. Saves typing.
- Query tracking. Log queries to analytics so you know what users look for. See Track Analytics.
Filter by Content Type
On sites with multiple content types (blog, products, docs), let users narrow:Faceted Search
For catalogs with structured metadata, add facet filters:- Category
- Tags
- Date range
- Price range
- Author
For Docs Sites Specifically
If you’re building a documentation site, Algolia DocSearch is free for open-source docs and purpose-built for the use case (good hierarchical ranking, keyboard nav, autocomplete). Apply and Algolia handles indexing for you.Verify It Worked
Test a typo
If using Algolia, “webistes” should still return “websites” content. If using plain PostgreSQL, typos won’t match — consider adding
pg_trgm for similarity matching.Troubleshooting
No results for anything
No results for anything
The index is empty. For PostgreSQL: the
search_vector column is null — run the UPDATE from Step 1 to backfill. For Algolia: you haven’t pushed content yet — run the indexing script.Search is slow (>1 second)
Search is slow (>1 second)
For PostgreSQL: missing GIN index on
search_vector. Check with \d+ blog_posts and confirm an index on that column. Also look for N+1 queries — you might be fetching full rows per result when IDs would do.Typos don't match
Typos don't match
PostgreSQL full-text search doesn’t handle typos out of the box. Add the
pg_trgm extension and use similarity() or % operator for fuzzy matching. Or switch to Algolia, which handles typos automatically.Results look random (no relevance)
Results look random (no relevance)
Add ranking signals beyond raw match. Good options: recency (newer posts rank higher), popularity (view count, engagement), author authority, content type priority. Combine them into a composite score that you ORDER BY.
Algolia index out of sync with database
Algolia index out of sync with database
Make sure your content-update workflow pushes to Algolia. Add an action after any blog/product insert or update that calls
index.saveObject(...). For deletes, call index.deleteObject(objectID).What’s Next?
Track Analytics
Log search queries so you can learn what users want
Structured Data
Help search engines index your content too