Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Typesense Laravel Package

statamic-rad-pack/typesense

A Typesense search driver for Statamic that replaces the default search with fast, typo-tolerant results. Automatically index your entries and query them through a simple, configurable integration built for Laravel and PHP.

View on GitHub
Deep Wiki
Context7

Getting Started

This is the Typesense search driver for Statamic — the day-to-day value is that Statamic's built-in search (the {{ search:results }} tag, the Search facade, and the control-panel search UX) is backed by Typesense instead of the default local index, giving you typo tolerance, faceted filtering, and fast sorting.

First moves:

  1. Stand up Typesense (Docker is fastest) and note the host/port/protocol.
  2. composer require statamic-rad-pack/typesense, then publish the config (php artisan vendor:publish --tag=typesense-config).
  3. Set env vars: TYPESENSE_API_KEY, TYPESENSE_HOST, TYPESENSE_PORT, TYPESENSE_PROTOCOL, and a TYPESENSE_SEARCH_ONLY_KEY for the browser side.
  4. Declare at least one index in config/typesense.php (collection name, field schema, which fields are searchable/filterable/sortable).
  5. Point Statamic at it in config/statamic/search.php: set 'default' => 'typesense' and add a driver block with 'driver' => 'typesense', 'searchables' => ['collection:pages'], and the fields to index.
  6. Run the indexer (php please search:update) and confirm the collection exists in Typesense.

First use case: make a blog/pages collection searchable, then drop {{ search:results index="blog" }} into a template and verify results come back. That end-to-end loop (config → search:update → tag) is the whole package in miniature.

Implementation Patterns

One index per search "surface". Rather than one giant index, define per-collection or per-concern indexes (e.g. pages, blog, docs) in config/typesense.php, and reference them explicitly with index="blog" in Antlers. This keeps schemas lean and lets you tune query_by weights per surface.

Schema-first, then content. Define fields with concrete Typesense types (string, int32, float, bool, geopoint) and mark only what you need as searchable, filterable, or sortable. A common pattern:

'indexes' => [
    'blog' => [
        'collection' => 'blog',
        'fields' => [
            'title'     => ['type' => 'string'],
            'content'   => ['type' => 'string'],
            'published' => ['type' => 'bool'],
            'date'      => ['type' => 'int64'],
        ],
        'searchable' => ['title', 'content'],
    ],
],

Keep sync explicit and scheduled. Statamic updates the index on entry save/publish/delete for configured searchables, but bulk work (imports, migrations, blueprint changes, new collections) needs an explicit php please search:update. In CI/deploy hooks, run it after migrate; on large sites, chain it behind a queued job or run it off-peak so a full reimport doesn't stall the deployment.

Use the search-only key in the frontend. If you're wiring Typesense's InstantSearch UI rather than the Antlers tag, configure the search-only key in your JS bundle (never the admin API key) and keep the collection naming aligned with what the PHP config produces.

Filter and sort explicitly rather than post-processing in PHP. Push filter_by/sort_by down to Typesense where the driver allows it — that's where the speed and facet counts come from. Only fall back to Collection filtering for edge cases the index can't express.

Test the config, not just the results. A quick php artisan tinker round-trip that hits the collection and returns a document count is the fastest way to distinguish "no results because of a query" from "no results because the index is empty or the schema is wrong."

Gotchas and Tips

exists() is now read-only (v3.3.1 change). As of this release, the collection exists() check only reports whether the collection is present — it no longer has any side effects. If any of your setup/import code relied on calling exists() and then assuming the collection was ready, move the creation/indexing step to an explicit call or to search:update in your deploy pipeline. This is a subtle behavior change rather than an API break, so it won't show up in a type check; it shows up as "collection missing" errors on a fresh environment.

Changing a field's type is not an in-place operation. Typesense can't alter a field type on an existing collection. After any schema change (type, new filterable field, renamed field), drop and reimport the collection — search:update alone may silently not apply the change. Plan schema edits as a reindex event.

Empty results usually mean config drift, not a broken package. Check, in order: is the collection actually populated? Does searchables include the collection you're expecting? Are the fields you're searching listed in searchable? Is the field mapping in config/typesense.php consistent with the Statamic field handles (not the display names)?

Namespace collections per environment. Dev, staging, and prod pointing at the same Typesense node will clobber each other's indexes. Use a per-environment collection prefix (or separate Typesense instances) and make sure your deploy step doesn't reindex prod from a staging config.

Environment variable mismatches fail loudly but unhelpfully. Wrong port or protocol (http vs https) surfaces as a connection error, not a config error. Bake a small health check into your local setup script so you learn about it before the first search request.

Queueing and freshness. If entries are created programmatically or in bulk, the per-save index update can lag or be skipped (e.g. saveQuietly-style paths, imports that bypass events). Treat search:update as the reconciliation tool of record and schedule it, rather than trusting event-driven sync alone.

Control-panel search inherits the driver. If you switch the default driver, CP search behavior changes too — worth verifying on staging before a release, since editors notice immediately.

Extension point for odd content. When a field needs to be searchable but isn't a plain string (computed labels, related-entry titles, taxonomy names), compute it into a dedicated field during save and index that — rather than trying to teach the schema about the relationship.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource