Search Setup
Configure MeiliSearch for powerful, typo-tolerant search in your documentation
Setting Up Search
Specra supports powerful full-text search through MeiliSearch integration. This guide shows you how to set up and configure search for your documentation.
Search Options
Specra offers two search solutions:
Local Search (Default)
- Works out of the box
- No external dependencies
- Good for small to medium doc sites
- Searches in the browser
MeiliSearch (Recommended for production)
- Blazing fast search engine
- Typo tolerance
- Instant results
- Better for large doc sites
- Requires separate server
Quick Start with MeiliSearch
Prerequisites
- Docker (easiest setup) or ability to run a MeiliSearch server
- Your documentation site already set up with Specra
Installation
Run MeiliSearch with Docker
1docker run -d \2 --name meilisearch \3 -p 7700:7700 \4 -e MEILI_MASTER_KEY="aSampleMasterKey" \5 -v $(pwd)/meili_data:/meili_data \6 getmeili/meilisearch:latestThis starts MeiliSearch on http://localhost:7700 with a master key for authentication.
Configure Specra
1{2 "search": {3 "enabled": true,4 "provider": "meilisearch",5 "placeholder": "Search documentation...",6 "meilisearch": {7 "host": "http://localhost:7700",8 "apiKey": "aSampleMasterKey",9 "indexName": "docs"10 }11 }12}Index Your Content
1npm run index:searchThis scans your docs/ folder and sends all content to MeiliSearch for indexing.
Test Search
1npm run devPress ⌘K (Mac) or Ctrl+K (Windows/Linux) to open the search modal. Start typing to see instant results!
MeiliSearch Configuration
Configuration Options
All MeiliSearch settings go in specra.config.json under the search section:
1{2 "search": {3 "enabled": true,4 "provider": "meilisearch",5 "placeholder": "Search docs...",6 "meilisearch": {7 "host": "http://localhost:7700",8 "apiKey": "your-api-key",9 "indexName": "docs"10 }11 }12}Field reference:
| Field | Type | Description |
|---|---|---|
enabled | boolean | Enable/disable search feature |
provider | string | "meilisearch" or "local" |
placeholder | string | Placeholder text in search box |
meilisearch.host | string | MeiliSearch server URL |
meilisearch.apiKey | string | API key for authentication |
meilisearch.indexName | string | Index name for your docs |
Search Key vs Master Key
MeiliSearch uses two types of keys:
Master Key (development)
- Full access to all operations
- Used for indexing content
- Never expose in client-side code in production
Search Key (production)
- Read-only access
- Safe to use in browser
- Generate from master key
Generate a search key:
1curl -X POST 'http://localhost:7700/keys' \2 -H 'Authorization: Bearer aSampleMasterKey' \3 -H 'Content-Type: application/json' \4 --data-binary '{5 "description": "Search key for documentation",6 "actions": ["search"],7 "indexes": ["docs"],8 "expiresAt": null9 }'Use the returned key in your production config.
Production Deployment
Hosting MeiliSearch
For production, you need to host MeiliSearch separately from your docs. Options:
MeiliSearch Cloud (Easiest)
- Official managed hosting
- Starts at $0.02/hour
- Automatic backups and updates
- Visit meilisearch.com/cloud
Self-hosted on VPS
- DigitalOcean, AWS, Google Cloud, etc.
- More control, requires maintenance
- Use Docker or binary installation
Railway / Render / Fly.io
- One-click deploy options available
- Good for small to medium projects
Production Configuration
Update specra.config.json for production:
1{2 "search": {3 "enabled": true,4 "provider": "meilisearch",5 "meilisearch": {6 "host": "https://your-meilisearch-domain.com",7 "apiKey": "your-public-search-key",8 "indexName": "docs"9 }10 }11}Indexing in CI/CD
Automate indexing when you deploy. Example GitHub Action:
1name: Index Documentation2 3on:4 push:5 branches: [main]6 paths:7 - 'docs/**'8 9jobs:10 index:11 runs-on: ubuntu-latest12 steps:13 - uses: actions/checkout@v314 15 - name: Setup Node.js16 uses: actions/setup-node@v317 with:18 node-version: '18'19 20 - name: Install dependencies21 run: npm ci22 23 - name: Index documentation24 env:25 MEILISEARCH_HOST: ${{ secrets.MEILISEARCH_HOST }}26 MEILISEARCH_API_KEY: ${{ secrets.MEILISEARCH_MASTER_KEY }}27 run: npm run index:searchStore your MeiliSearch credentials as GitHub secrets.
Customizing Search Behavior
Search Settings
Configure how MeiliSearch handles searches:
1// In your indexing script2const settings = {3 searchableAttributes: [4 'title',5 'description',6 'content',7 'headings'8 ],9 displayedAttributes: [10 'title',11 'description',12 'url',13 'breadcrumb'14 ],15 rankingRules: [16 'words',17 'typo',18 'proximity',19 'attribute',20 'sort',21 'exactness'22 ],23 stopWords: ['the', 'a', 'an'],24 synonyms: {25 'js': ['javascript'],26 'ts': ['typescript']27 }28}Filters
Add filters to narrow search results:
1{2 "search": {3 "meilisearch": {4 "filters": "version = 'v1.0.0'"5 }6 }7}This only shows results from a specific version.
Local Search (Alternative)
If you don't want to run MeiliSearch, use local search:
1{2 "search": {3 "enabled": true,4 "provider": "local",5 "placeholder": "Search documentation..."6 }7}Local search:
- ✅ Works immediately, no setup
- ✅ No external dependencies
- ✅ Free
- ❌ Less powerful than MeiliSearch
- ❌ No typo tolerance
- ❌ Slower for large doc sites
Local search is automatically built during npm run build.
Keyboard Shortcuts
Users can trigger search with:
- ⌘K or Ctrl+K - Open search
- Escape - Close search
- ↑↓ - Navigate results
- Enter - Go to selected result
These work with both local and MeiliSearch options.
Troubleshooting
Search not appearing
Check configuration:
1{2 "search": {3 "enabled": true // ← Must be true4 }5}Verify MeiliSearch is running:
1curl http://localhost:7700/healthShould return {"status":"available"}.
No search results
Re-index your content:
1npm run index:searchCheck index exists:
1curl -X GET 'http://localhost:7700/indexes' \2 -H 'Authorization: Bearer aSampleMasterKey'CORS errors
If you get CORS errors in browser console, configure MeiliSearch to allow your domain:
1docker run -d \2 --name meilisearch \3 -p 7700:7700 \4 -e MEILI_MASTER_KEY="aSampleMasterKey" \5 -e MEILI_HTTP_ADDR="0.0.0.0:7700" \6 -e MEILI_NO_ANALYTICS=true \7 getmeili/meilisearch:latestOr set CORS headers in your reverse proxy.
Slow indexing
For large doc sites (1000+ pages):
- Index incrementally (only changed files)
- Use batch requests
- Increase MeiliSearch memory allocation
- Run indexing in background jobs
Advanced Features
Multi-Language Search
Configure language-specific stemming:
1const settings = {2 searchableAttributes: ['title', 'content'],3 attributesForFaceting: ['lang'],4 // ... other settings5}6 7// Index with language tags8{9 title: "Getting Started",10 content: "...",11 lang: "en",12 url: "/docs/en/getting-started"13}Search Analytics
Track what users search for:
1// In your search component2const logSearch = async (query, resultsCount) => {3 await fetch('/api/analytics/search', {4 method: 'POST',5 body: JSON.stringify({ query, resultsCount })6 })7}Use this data to improve documentation based on what users look for.
Custom Result Rendering
Override the search result component to customize how results appear:
1// components/custom-search-result.tsx2export function CustomSearchResult({ hit }) {3 return (4 <div className="search-result">5 <h3>{hit.title}</h3>6 <p>{hit.description}</p>7 <span className="version">{hit.version}</span>8 </div>9 )10}