{"post":{"slug":"how-to-add-search-to-a-site-2026","title":"How to add search to a site in 2026","excerpt":"Site search ranges from a client-side index for a blog to a full Elasticsearch cluster for an enterprise app. This guide maps the right tool to your actual scale and stack.","category":"code","date":"March 11, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">A</span>dding search to a site sounds simple until you realise there are a dozen architecturally different approaches and picking the wrong one means re-implementing it six months later. The right answer depends on whether your content is static or dynamic, how many documents you have, and whether you need semantic (meaning-based) results or keyword results. This is the 2026 decision framework.\n\n## What changed in 2026\n\n- **Pagefind 2.0** added vector search on top of its static index — you can ship semantic search on a Jamstack site with no server.\n- **Meilisearch 1.x** stabilized its vector search and hybrid mode, making it a credible alternative to Algolia for self-hosters.\n- **pgvector 0.7** added HNSW indexing, which makes approximate nearest-neighbor search fast enough for production at moderate scale.\n- **Algolia** added AI-based relevance tuning; the free tier still caps at 10,000 records.\n- **Full-text search in Postgres** (`tsvector` / `ts_query`) remains underrated — for apps already on Postgres, it's often the right answer with no extra infrastructure.\n\n## Tool comparison\n\n| Tool | Type | Self-host | Free tier | Best for |\n| --- | --- | --- | --- | --- |\n| Pagefind | Static WASM | Yes (build output) | Free | Docs, blogs, static sites |\n| Algolia | SaaS | No | 10k records | Product/content with budget |\n| Meilisearch | Open source / cloud | Yes | Cloud free tier | Self-hosted alternative to Algolia |\n| Typesense | Open source / cloud | Yes | Cloud free tier | Self-hosted, exact Algolia parity |\n| Postgres FTS | DB built-in | Yes (your DB) | Free | Apps already on Postgres |\n| pgvector | Postgres extension | Yes | Free | Semantic/hybrid search in Postgres |\n| Elasticsearch | Open source / cloud | Yes | None free | Very large scale, complex queries |\n\n## Pagefind (static sites)\n\n```bash\nnpx pagefind --site dist --output-path dist/pagefind\n```\n\n```html\n<!-- Add to your page -->\n<link rel=\"stylesheet\" href=\"/pagefind/pagefind-ui.css\" />\n<div id=\"search\"></div>\n<script>\n  window.addEventListener('load', () => {\n    new PagefindUI({ element: '#search', showImages: true })\n  })\n</script>\n<script src=\"/pagefind/pagefind-ui.js\"></script>\n```\n\nRun `pagefind` after every build. It indexes HTML, generates a WASM binary, and everything runs in the browser — no API key, no server, no cost.\n\n## Algolia / Typesense (instant search)\n\n```ts\n// Push records to Algolia\nimport algoliasearch from 'algoliasearch'\n\nconst client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_WRITE_KEY!)\nconst index = client.initIndex('products')\n\nawait index.saveObjects(products.map(p => ({ objectID: p.id, ...p })))\n```\n\n```tsx\n// React InstantSearch\nimport { InstantSearch, SearchBox, Hits } from 'react-instantsearch'\n\n<InstantSearch indexName=\"products\" searchClient={searchClient}>\n  <SearchBox />\n  <Hits hitComponent={ProductCard} />\n</InstantSearch>\n```\n\nTypesense has a drop-in `instantsearch-adapter` package — swap the client, keep the UI components.\n\n## Postgres full-text search\n\n```sql\n-- Add a tsvector column\nALTER TABLE articles ADD COLUMN search_vector tsvector;\n\nUPDATE articles\nSET search_vector = to_tsvector('english', title || ' ' || body);\n\nCREATE INDEX articles_search_idx ON articles USING GIN(search_vector);\n\n-- Query\nSELECT id, title\nFROM articles\nWHERE search_vector @@ plainto_tsquery('english', 'query terms')\nORDER BY ts_rank(search_vector, plainto_tsquery('english', 'query terms')) DESC\nLIMIT 20;\n```\n\nFor semantic search, add pgvector:\n\n```sql\n-- Hybrid: BM25 + vector similarity\nSELECT id, title,\n  ts_rank(search_vector, query) * 0.5 +\n  (1 - (embedding <=> $1::vector)) * 0.5 AS score\nFROM articles, plainto_tsquery('english', $2) query\nWHERE search_vector @@ query\nORDER BY score DESC\nLIMIT 20;\n```\n\n## How to pick\n\n| Your situation | Recommendation |\n| --- | --- |\n| Static site / docs | Pagefind |\n| App on Postgres, < 1M rows | Postgres FTS or pgvector |\n| Need facets + instant UX | Algolia (paid) or Typesense |\n| Self-host, Algolia-like features | Meilisearch or Typesense |\n| Millions of documents, complex | Elasticsearch / OpenSearch |\n\n## Common mistakes\n\n**Building search before content exists** — don't over-engineer a search solution for 50 articles. Pagefind or Ctrl+F is fine until you have real scale.\n\n**Not debouncing the search input** — fire one API call per keystroke and you'll hit rate limits and slow down the UI. Debounce to ~250 ms.\n\n**Forgetting to re-index on data changes** — search indices go stale. Trigger re-indexing in your deployment pipeline or via webhooks on content changes.\n\n**No fallback for zero results** — an empty results page frustrates users. Show \"did you mean?\", recent searches, or popular pages.\n\n## What to skip\n\n- **Building your own inverted index** — there are a dozen excellent open-source tools; reinventing this is a waste of engineering time.\n- **Elasticsearch for a blog** — the operational overhead (JVM heap, index shards, snapshot management) is massive for small content sets.\n- **Client-side Fuse.js for large datasets** — Fuse.js is fine for a small in-memory search over <1,000 items; beyond that, use a proper search tool.\n\n## FAQ\n\n**Can I add search to a Next.js app?**\nYes. For static content use Pagefind at build time. For dynamic content, use the Algolia, Typesense, or Meilisearch JavaScript client in an API route or server action.\n\n**How do I handle multilingual search?**\nAlgolia and Typesense support per-language analyzers. Postgres FTS uses language-specific dictionaries (`to_tsvector('french', ...)`). Pagefind supports multiple languages via the `--language` flag.\n\n**What about search analytics?**\nAlgolia has first-class analytics in the dashboard. For self-hosted tools, log search queries and result click-through to your own analytics; Posthog works well.\n\n**Do I need a vector database for semantic search?**\nNot necessarily. If you are already on Postgres, pgvector handles vectors and SQL queries in the same database. A standalone vector DB (Pinecone, Qdrant) is worth it only at large scale or if you need features pgvector does not cover.\n\n## Where to go next\n\n- [How to add full-text search in 2026](/blog/how-to-add-full-text-search-2026)\n- [How to set up Stripe payments in 2026](/blog/how-to-set-up-stripe-payments-2026)\n- [How to optimize images for the web in 2026](/blog/how-to-optimize-images-for-web-2026)","hue":320,"metaTitle":"How to Add Search to a Site in 2026","metaDescription":"2026 guide to adding site search. Compare Pagefind, Algolia, Meilisearch, Typesense, and pgvector — with setup code for each approach.","keywords":["how to add search to a site 2026","site search options 2026","pagefind static site search","algolia vs meilisearch 2026","typesense setup 2026","pgvector full text search","javascript search 2026","semantic search website 2026","add search bar react 2026","elasticsearch alternative 2026"],"tldr":["**Pagefind for static sites** — runs at build time, generates a WASM-powered index, zero server required.","**Algolia / Meilisearch for product search** — facets, typo-tolerance, and instant results without building a search engine from scratch.","**pgvector + full-text for apps already on Postgres** — hybrid search (vector similarity + ts_query) covers semantic and keyword in one query.","**Typesense** is the self-hosted alternative to Algolia with near-identical features and a generous cloud free tier.","**Skip:** running Elasticsearch for a site with fewer than 100k documents — it's massive operational overhead for a problem smaller tools solve better."],"readTime":"4 min read","wordCount":966},"related":[{"slug":"how-to-add-full-text-search-2026","title":"How to add full-text search in 2026: Postgres FTS, Typesense, and when to use each","excerpt":"Full-text search in 2026 runs the spectrum from Postgres built-in FTS to dedicated engines. This guide shows which to pick and how to implement each correctly.","category":"code","date":"April 14, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":306},{"slug":"how-to-deploy-a-website-2026","title":"How to Deploy a Website in 2026: a step-by-step guide","excerpt":"Deploying a website in 2026 means pushing your code to a host that serves it to the public. Here is the simplest reliable path, from static sites to apps.","category":"code","date":"June 20, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":205},{"slug":"how-to-build-a-website-2026","title":"How to build a website in 2026: from zero to live in a weekend","excerpt":"Building a website in 2026 is faster than ever, but the options are more confusing. This guide picks the right path for your goal and skill level.","category":"code","date":"March 28, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":306}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"how-to-install-linux-2026","title":"How to install Linux in 2026: choose a distro, partition, and go live","excerpt":"Linux installation in 2026 is more beginner-friendly than ever, but choosing the right distro and partition scheme still determines whether it works long-term.","category":"tech","date":"March 12, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":228},"older":{"slug":"how-to-automate-bill-payments-2026","title":"How to automate bill payments in 2026: set it up once, stress less forever","excerpt":"Late fees and missed payments are expensive and preventable. Here is the 2026 system for automating every bill so nothing slips through the cracks.","category":"finance","date":"March 11, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":304}}