Interactive demo — facet.manticoresearch.com
Read the faceted-search documentation · Read the feature article
Faceted search that adapts to every filter.
This is a small, production-shaped storefront demo for Manticore Search. It shows how facet_filter_mode lets a catalog keep filters useful after each selection—without an application building a separate filter tree for every facet.
The catalog has 80 products, four live facets, fuzzy product search, and a visible request workbench. Select a brand, color, or size, then compare the modes:
| Mode | What the facet inherits | What it demonstrates |
|---|---|---|
strict |
Every active filter | The exact current result set |
auto |
Every filter except the facet itself | Natural alternatives within each facet |
max |
A configurable per-facet scope | Selected, available, and unavailable choices |
max is the default. Its controls show three native scopes—Storefront, Current result, and Whole catalog—plus optional zero-count recovery choices. The One live request panel below the catalog exposes the generated JSON request, an equivalent SQL statement, and the raw Manticore facet buckets.
The demo includes a copyable three-step browser integration walkthrough: create Manticore’s official JavaScript client, describe the facet aggregations, then render the returned product hits and native bucket states. The snippets are annotated production patterns, not a complete application: replace the endpoint and credentials, and supply your own filter-building code.
No custom application backend is required to translate facets. The browser sends one JSON request to Manticore’s HTTP API; Manticore returns the products and aggregations together. For storefront-style self-exclusion, each aggregation simply declares exclude_filters: [field]. Use filters instead when a facet should inherit one explicit set of fields. JSON aggregation buckets use bucket.key, bucket.doc_count, and bucket.status.
For a public deployment, expose a browser-reachable read-only HTTP endpoint over HTTPS. This repository uses Nginx as a same-origin static host and restricted gateway—it is a deployment boundary, not application-side facet logic. The public browser credential only has read permission on the demo table.
Requirements: Docker with the Compose plugin. Node.js 22+ is required to run the build and checks locally.
First start (new catalog volume): generate the administrator password once and save it in the ignored .env file. Compose automatically reads this file on later starts.
git clone https://github.com/manticoresoftware/facet_demo.git
cd facet_demo
printf 'MANTICORE_ADMIN_PASSWORD=Aa1_%s\n' "$(openssl rand -hex 24)" > .env
chmod 600 .env
docker compose up -d --build --wait --wait-timeout 120
curl -f http://127.0.0.1:18090/healthzOpen http://127.0.0.1:18090.
For later starts, keep both .env and the manticore-data volume, then run:
docker compose up -d --build --wait --wait-timeout 120Do not generate a new password when restarting an existing volume. The authentication store in manticore-data requires the password used when that volume was first initialized. If .env has been lost, either restore its original value or intentionally reset the catalog and authentication volume with docker compose down -v before generating a new password.
Compose creates a fixed Linux bridge named facet-demo-br0. On hosts where firewalld controls forwarding—especially when Docker is configured with "iptables": false—trust that bridge once so the web container can reach Manticore Search:
sudo firewall-cmd --permanent --zone=trusted --add-interface=facet-demo-br0
sudo firewall-cmd --reloadThe permanent rule can be added before the bridge exists. Start the stack normally, then verify both the interface assignment and application health:
docker compose up -d --build --wait --wait-timeout 120
sudo firewall-cmd --get-zone-of-interface=facet-demo-br0
curl -f http://127.0.0.1:18090/healthzThe zone command should print trusted. Because the bridge name is fixed in compose.yaml, the rule remains valid after docker compose down or network recreation. Removing volumes with docker compose down -v does not require a firewall change.
The web service binds to loopback by default. To use another local port, set FACET_DEMO_PORT before starting Compose:
FACET_DEMO_PORT=8080 docker compose up -d --buildTo reset the local catalog and authentication volume, no password needs to be exported because this command only tears services down:
docker compose down -vIf docker compose up stops partway through and a retry reports an error such as endpoint with name facet-demo-manticore-1 already exists in network facet-demo_default, Compose has left incomplete containers or a network endpoint behind. It is not an application or password error. Current versions of this repository use facet-demo-v2_default, so updating the repository lets new starts avoid that stale legacy network automatically.
From this repository, clean up only this Compose project, keeping the catalog volume intact:
docker compose down --remove-orphansThen start it again with the administrator password already associated with this catalog volume. Reuse the value from the original start; generating a new value only works after intentionally removing the volume with docker compose down -v:
export MANTICORE_ADMIN_PASSWORD='the same password used for this catalog volume'
docker compose up -d --buildIf Docker still says an endpoint exists after the cleanup, the container runtime has retained stale network state. Restart the Docker runtime, then rerun the two commands above:
- OrbStack: quit and reopen OrbStack.
- Docker Desktop: Troubleshoot → Restart Docker Desktop.
Do not use docker compose down -v unless you intend to discard the local catalog and authentication volume.
npm ci
npm testnpm test regenerates the deterministic 80-product catalog and static frontend, then validates the client integration, request contracts, read-only authorization, proxy limits, generated assets, and public repository metadata.
With the local stack running, exercise the real Manticore endpoint too:
FACET_DEMO_URL=http://127.0.0.1:18090 npm run test:liveflowchart LR
Browser[Browser\nOfficial Manticore JavaScript client] -->|POST /search\nBasic auth| Nginx[Nginx\nStatic frontend + restricted proxy]
Nginx -->|Authenticated read-only JSON search| Manticore[Manticore Search\nfacet_demo_products]
-
src/contains the editable storefront template, CSS, JavaScript, product images, and SVG logo. -
scripts/build.mjsbundles the officialmanticoresearchJavaScript client intopublic/index.html; do not hand-edit generated files underpublic/. -
Nginx serves static files and exposes only
POST /search. Manticore's database ports are not published. -
The browser uses a deliberately public
facet_demoaccount with one permission:GRANT read ON 'facet_demo_products' TO 'facet_demo';
Its password is visible in the static demo by design and is not a secret. It has no
write,schema,replication, oradminpermission. The administrator password remains outside the image and must be supplied asMANTICORE_ADMIN_PASSWORD.
- Set a strong
MANTICORE_ADMIN_PASSWORDin your deployment secret store. - Run
npm test, thendocker compose up -d --build. - Keep the Compose port bound to loopback.
- Terminate TLS in a reverse proxy and forward your public hostname to that loopback port.
- Verify
/healthz, all three facet modes, fuzzy search, zero-count choices, and the request workbench.
Use HTTPS for any public deployment because the browser sends Basic authentication to the same origin. The Manticore image is pinned by digest; change MANTICORE_IMAGE only after an explicit compatibility test.
Bug reports and focused pull requests are welcome. See CONTRIBUTING.md for the local checks and scope guidelines.
MIT © 2020–2026 Manticore Software Ltd.
