Skip to content

feat: better search#1550

Open
tankerkiller125 wants to merge 7 commits into
mainfrom
mk/better-search
Open

feat: better search#1550
tankerkiller125 wants to merge 7 commits into
mainfrom
mk/better-search

Conversation

@tankerkiller125

@tankerkiller125 tankerkiller125 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • feature

What this PR does / why we need it:

Tokenizes the database search, and make search in general more extensible (and in that regard adds Meillisearch capabilities)

This is entirely a backend change with minimal API and front-end chages, however, it should in theory support an "e-commerce" like search experience if we wanted.

Fixes: #1021
Fixes: #438

Special notes for your reviewer:

Validated multiple times in regular database mode, and Meillisearch mode. Should double check and ensure that there's no cross-tenant issues.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR implements a pluggable search engine architecture supporting database (default) and Meilisearch backends. The database engine uses dialect-aware SQL predicates for accent- and case-insensitive matching. Meilisearch adds typo tolerance and auto-indexing with debounced mutation coalescing. Entity queries now support MatchAllTags for AND-based tag filtering. The frontend items page gains a UI toggle for tag matching strategy.

Changes

Search Engine Infrastructure & Integration

Layer / File(s) Summary
Search engine abstraction and tokenization
backend/internal/data/search/search.go, tokenize.go, tokenize_test.go
Defines Engine interface for pluggable search, Faceter optional interface for facet queries, TagFacet/FieldFacet data types, and Tokenize utility for query parsing with deduplication and quote handling.
Database-backed search engine
backend/internal/data/search/database.go, database_test.go
Implements SQL-based free-text search with dialect-aware (SQLite/PostgreSQL) case/accent-insensitive predicates via hb_fold and unaccent functions; includes SearchTags, SearchFieldValues, and FieldFacets for UI facet display.
Meilisearch-backed search engine
backend/internal/data/search/meilisearch.go, meilisearch_test.go
Implements Meilisearch-indexed search with index auto-creation and configuration; debounced mutation scheduling for incremental reindexing; event-bus integration for group/tag mutations; intersects Meilisearch hits with database predicates for pagination and group isolation.
Text folding and SQLite function
backend/pkgs/textutils/normalize.go, normalize_test.go, backend/pkgs/cgofreesqlite/sqlite.go
Introduces Fold function for Unicode case/accent-insensitive normalization; registers SQLite scalar function hb_fold for case/accent-insensitive SQL matching across backends.
Search configuration and initialization
backend/internal/sys/config/conf.go, conf_search_test.go, backend/app/api/main.go, backend/internal/data/repo/repos_all.go
Adds SearchConf and MeilisearchConf config types with JSON API key redaction; wires search engine creation and error handling in app startup; updates repo.New signature to accept and wire searchEngine.
Entity query with search predicates and tag filtering
backend/internal/data/repo/repo_entities.go
Integrates search engine into EntityRepository for free-text predicates; adds MatchAllTags flag to EntityQuery for AND-based tag filtering; refactors tag predicate logic into tagPredicates helper supporting OR (default), negate, and match-all modes.
API parameter and frontend integration
backend/app/api/handlers/v1/v1_ctrl_entities.go, frontend/lib/api/classes/items.ts, frontend/pages/items.vue, frontend/locales/en.json
Adds matchAllTags query parameter to GET /v1/entities; extends frontend ItemsQuery type and items.vue with route-linked matchAllTags toggle bound to UI switch and search tips; includes localization strings.
Test updates and search behavior validation
backend/internal/core/services/main_test.go, service_items_attachments_test.go, backend/internal/data/repo/main_test.go, repo_item_attachments_test.go, repo_items_search_test.go
Updates test call sites to new repo.New signature; replaces accent-normalization unit tests with comprehensive repository search tests covering Unicode, accents, multi-token AND, field matching, tag search, custom fields, wildcards, and MatchAllTags semantics.
Documentation, dependencies, and development tooling
docs/src/content/docs/en/quick-start/configure/database.mdx, index.mdx, search.mdx, backend/go.mod, Taskfile.yml
Adds environment variable documentation for search driver and Meilisearch configuration; documents database and Meilisearch behavior with PostgreSQL unaccent setup guidance; adds meilisearch-go dependency; adds Taskfile task for Meilisearch integration tests with Docker container management.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • sysadminsmedia/homebox#797: Modifies the same repo.New constructor signature that this PR extends with the searchEngine parameter.
  • sysadminsmedia/homebox#887: Related accent-insensitive matching refactoring; this PR integrates that work into the new pluggable search engine layer via the Fold function and dialect-aware predicates.
  • sysadminsmedia/homebox#1040: Overlaps at the frontend items.vue router query handling; both modify search flow and boolean query parameter serialization.

Suggested reviewers

  • katosdev
  • tonyaellie

⚠️ Security Recommendations

  1. API Key Redaction ✅: The MeilisearchConf.MarshalJSON correctly redacts the API key in JSON output (good practice for logs/debugging). Verify that Meilisearch credentials are never logged in plaintext elsewhere—check startup logs, error messages, and debug output for any accidental credential leakage. The main.go error logging should also avoid leaking the full config object.

  2. Meilisearch Health Check & Configuration Errors ✅: The engine fails fast if Meilisearch is unreachable at startup (NewMeilisearchEngine performs a health check). Ensure error messages clearly distinguish connection failures from misconfiguration (typo in host, wrong port) so operators can debug effectively without guessing.

  3. SQL Injection in Facet Queries ✅: The database engine builds SQL via Ent predicates (safe), but FieldFacets uses direct QueryContext. Audit ensures dynamic field names and group IDs are properly parameterized. Spot-check confirms field names come from schema/enum (not user input) and group IDs are parameterized as UUID values.

  4. Meilisearch Index Scope & Cross-Group Data Leakage ✅: Verify all index queries include group_id filtering—inspect Predicate, SearchTags, FieldFacets, and SearchFieldValues. Cross-group leakage would violate data isolation guarantees. All confirmed to filter by group_id at the query layer and validated in the integration tests.

  5. Unaccent Extension Availability: PostgreSQL unaccent probing happens once at query time with a cached result. Document fallback behavior when the extension is unavailable (accented characters treated as distinct) so operators understand the behavior change and can enable the extension if needed for consistent search behavior across deployments.

  6. Reindex Stale Document Pruning ✅: The pruneStale routine in Meilisearch is marked as "best-effort hygiene," meaning failures don't block the reindex. This is acceptable for eventual consistency, but document in deployment/monitoring guides that operators should periodically monitor index size growth to catch unexpected document accumulation.

Poem

🔍 A search engine born anew,
Two backends dance—database's true,
And Meilisearch with style,
Typos forgiven all the while,
Tags now match in AND-flavored hue.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.74% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: better search' is vague and generic, using non-descriptive language that doesn't clearly convey the specific implementation details (tokenization, Meilisearch support, database engine abstraction). Consider a more specific title like 'feat: add tokenized search with Meilisearch support' or 'feat: implement pluggable search engine abstraction with Meilisearch integration'.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed PR description covers required sections: type (feature), what it does (tokenized search + Meilisearch), related issues (#1021, #438), and reviewer notes. All mandatory elements present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch mk/better-search

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot requested review from katosdev and tonyaellie June 13, 2026 19:32
@coderabbitai coderabbitai Bot added ⬆️ enhancement New feature or request review needed A review is needed on this PR or Issue labels Jun 13, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
backend/internal/sys/config/conf_search_test.go (1)

30-30: Fix: sentinel exists in this test package, so conf_search_test.go compiles.
backend/internal/sys/config/conf_search_test.go uses sentinel, which is declared at package scope in backend/internal/sys/config/conf_redact_test.go as const sentinel = redactedValue, making it available to other package config test files.

Security: keep the redaction sentinel stable/non-plausible (redactedValue) so real secrets can’t accidentally equal the marker.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/sys/config/conf_search_test.go` at line 30, The test in
conf_search_test.go calls assert.Contains(t, string(out), sentinel) but sentinel
must be defined at package scope; declare const sentinel = redactedValue in the
package test file conf_redact_test.go (where other tests share package config)
so conf_search_test.go compiles, and ensure redactedValue remains a stable,
non-plausible marker to avoid matching real secrets.
Taskfile.yml (1)

118-118: ⚡ Quick win

Bind the test Meilisearch port to loopback only.

Publishing on all interfaces is broader than needed for local integration tests; bind to 127.0.0.1 to reduce exposure on shared runners/dev hosts.

Suggested fix
-      - docker run -d --rm --name homebox-meili-test -p 7711:7700 -e MEILI_MASTER_KEY=test-master-key -e MEILI_NO_ANALYTICS=true getmeili/meilisearch:v1.22
+      - docker run -d --rm --name homebox-meili-test -p 127.0.0.1:7711:7700 -e MEILI_MASTER_KEY=test-master-key -e MEILI_NO_ANALYTICS=true getmeili/meilisearch:v1.22
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Taskfile.yml` at line 118, The docker run command currently publishes
Meilisearch on all interfaces (-p 7711:7700); restrict it to loopback by
changing the port mapping to -p 127.0.0.1:7711:7700 in the docker run line (the
entry starting with "docker run -d --rm --name homebox-meili-test ...
getmeili/meilisearch:v1.22") so the container only binds to localhost for test
runs.
docs/src/content/docs/en/quick-start/configure/search.mdx (1)

42-43: ⚡ Quick win

Prefer scoped Meilisearch keys in examples, not the master key.

Using your_master_key in sample config normalizes over-privileged credentials. Recommend showing a scoped key as the default example and reserving master-key usage for setup/admin notes.

Suggested doc tweak
-      - HBOX_SEARCH_MEILISEARCH_API_KEY=your_master_key
+      - HBOX_SEARCH_MEILISEARCH_API_KEY=your_homebox_rw_key
@@
-      - MEILI_MASTER_KEY=your_master_key
+      - MEILI_MASTER_KEY=your_bootstrap_master_key
@@
-| HBOX_SEARCH_MEILISEARCH_API_KEY     |                         | Meilisearch API key (the master key, or a key with index read/write access)   |
+| HBOX_SEARCH_MEILISEARCH_API_KEY     |                         | Meilisearch API key (prefer a scoped key with index read/write access; avoid using the master key for app runtime) |

Also applies to: 49-50, 62-63

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/src/content/docs/en/quick-start/configure/search.mdx` around lines 42 -
43, Replace the example value for the HBOX_SEARCH_MEILISEARCH_API_KEY env var so
it shows a scoped/search-only key (e.g., "your_scoped_search_key" or
"scoped_search_key") instead of "your_master_key" in all examples, and add a
brief note nearby that the master key should only be used for setup/admin
operations; update every occurrence of HBOX_SEARCH_MEILISEARCH_API_KEY in the
file to use the scoped-key example and keep master-key usage documented only in
an admin/setup note.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/data/search/database.go`:
- Around line 133-155: The code uses sync.Once (e.unaccentOnce) in
unaccentAvailable which can permanently cache a transient context-cancel/timeout
failure; replace the sync.Once approach with an explicit lock + checked flag so
transient ctx errors don't mark the probe as finished: add (or use) a mutex
(e.g., unaccentMu) and a bool (e.g., unaccentChecked) on DatabaseEngine, then in
unaccentAvailable acquire the mutex, if unaccentChecked return e.unaccent; run
the probe using the provided ctx, but if the probe fails due to ctx
cancellation/deadline (ctx.Err()==context.Canceled or context.DeadlineExceeded)
do not set unaccentChecked and return (so future calls will retry); only set
e.unaccent and unaccentChecked=true when the probe completes without a
caller-context cancellation (successful probe or definitive DB response).
Reference: unaccentAvailable, e.unaccentOnce, e.unaccent (replace e.unaccentOnce
use with unaccentMu + unaccentChecked).

In `@backend/internal/data/search/meilisearch.go`:
- Around line 357-397: The reindex loop builds `indexed` from multiple
offset-paged queries which is not a stable snapshot and can miss concurrent
mutations; to fix, make `reindex` first capture a stable list of target entity
IDs (e.g., call the same query but use .IDs(ctx) or a single transaction to
collect all entity IDs matching the filters) and then iterate that static slice
in batches (using meiliReindexBatch) to load full entities, call
buildMeiliDocument, add documents with e.index.AddDocumentsWithContext and
populate the `indexed` set from the static ID list; finally call pruneStale with
that `indexed` set so pruning is based on the immutable snapshot rather than
offset-paged, concurrently-changing results.

In `@backend/internal/sys/config/conf_search_test.go`:
- Around line 12-21: The test Test_SearchConf_Defaults reads environment
variables via conf.Parse so make it deterministic by clearing the relevant
HBOXTEST_* env keys before parsing: in the test (before calling conf.Parse) call
t.Setenv("HBOXTEST_SEARCH_DRIVER", ""),
t.Setenv("HBOXTEST_SEARCH_MEILISEARCH_HOST", ""),
t.Setenv("HBOXTEST_SEARCH_MEILISEARCH_INDEX", ""), and
t.Setenv("HBOXTEST_SEARCH_MEILISEARCH_MAXHITS", "") (or any other HBOXTEST_*
keys your config reads) so conf.Parse uses the code defaults; keep the rest of
the assertions unchanged.

In `@backend/internal/sys/config/conf.go`:
- Around line 80-81: The Meilisearch config exposes Host and APIKey without
enforcing secure transport; add a validation routine (e.g., ValidateMeiliConfig
or a method Validate on the struct that contains Host and APIKey) that parses
Host as a URL and returns an error if the scheme is not "https" unless the host
is explicitly local (allow "localhost", "127.0.0.1", "[::1]" and their ports);
call this validation during config load/initialization so non-local HTTP
endpoints are rejected and only localhost may use http. Ensure the validation
uses url.Parse, checks u.Scheme and normalized u.Hostname() and returns clear
errors for invalid/missing Host or insecure scheme.

In `@Taskfile.yml`:
- Around line 120-121: The health-check loop line "until curl -sf
http://localhost:7711/health > /dev/null; do sleep 0.5; done" can hang CI
indefinitely; replace it with a bounded wait that times out and fails the task
if Meilisearch doesn't become healthy (for example, implement a retry counter or
elapsed-time check and exit non-zero after a max wait like 30s/60 attempts).
Keep the subsequent test invocation "TEST_MEILISEARCH_URL=...
TEST_MEILISEARCH_KEY=... go test ./internal/data/search/ -v -count=1" unchanged;
ensure the bounded-wait returns success only when the curl succeeds and
otherwise prints a clear error and exits non-zero so the task fails fast.

---

Nitpick comments:
In `@backend/internal/sys/config/conf_search_test.go`:
- Line 30: The test in conf_search_test.go calls assert.Contains(t, string(out),
sentinel) but sentinel must be defined at package scope; declare const sentinel
= redactedValue in the package test file conf_redact_test.go (where other tests
share package config) so conf_search_test.go compiles, and ensure redactedValue
remains a stable, non-plausible marker to avoid matching real secrets.

In `@docs/src/content/docs/en/quick-start/configure/search.mdx`:
- Around line 42-43: Replace the example value for the
HBOX_SEARCH_MEILISEARCH_API_KEY env var so it shows a scoped/search-only key
(e.g., "your_scoped_search_key" or "scoped_search_key") instead of
"your_master_key" in all examples, and add a brief note nearby that the master
key should only be used for setup/admin operations; update every occurrence of
HBOX_SEARCH_MEILISEARCH_API_KEY in the file to use the scoped-key example and
keep master-key usage documented only in an admin/setup note.

In `@Taskfile.yml`:
- Line 118: The docker run command currently publishes Meilisearch on all
interfaces (-p 7711:7700); restrict it to loopback by changing the port mapping
to -p 127.0.0.1:7711:7700 in the docker run line (the entry starting with
"docker run -d --rm --name homebox-meili-test ... getmeili/meilisearch:v1.22")
so the container only binds to localhost for test runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 46c26ef3-5928-47ff-a613-8df799666f35

📥 Commits

Reviewing files that changed from the base of the PR and between 9200882 and c17f58c.

⛔ Files ignored due to path filters (11)
  • backend/app/api/static/docs/docs.go is excluded by !backend/app/api/static/docs/**
  • backend/app/api/static/docs/openapi-3.json is excluded by !backend/app/api/static/docs/**
  • backend/app/api/static/docs/openapi-3.yaml is excluded by !backend/app/api/static/docs/**
  • backend/app/api/static/docs/swagger.json is excluded by !backend/app/api/static/docs/**
  • backend/app/api/static/docs/swagger.yaml is excluded by !backend/app/api/static/docs/**
  • backend/go.sum is excluded by !**/*.sum
  • backend/internal/data/ent/external.go is excluded by !backend/internal/data/ent/**
  • docs/public/api/openapi-3.0.json is excluded by !docs/public/api/**
  • docs/public/api/openapi-3.0.yaml is excluded by !docs/public/api/**
  • docs/public/api/swagger-2.0.json is excluded by !docs/public/api/**
  • docs/public/api/swagger-2.0.yaml is excluded by !docs/public/api/**
📒 Files selected for processing (30)
  • Taskfile.yml
  • backend/app/api/cli_reset_password.go
  • backend/app/api/handlers/v1/v1_ctrl_entities.go
  • backend/app/api/main.go
  • backend/go.mod
  • backend/internal/core/services/main_test.go
  • backend/internal/core/services/service_items_attachments_test.go
  • backend/internal/data/repo/main_test.go
  • backend/internal/data/repo/repo_entities.go
  • backend/internal/data/repo/repo_item_attachments_test.go
  • backend/internal/data/repo/repo_items_search_test.go
  • backend/internal/data/repo/repos_all.go
  • backend/internal/data/search/database.go
  • backend/internal/data/search/database_test.go
  • backend/internal/data/search/meilisearch.go
  • backend/internal/data/search/meilisearch_test.go
  • backend/internal/data/search/search.go
  • backend/internal/data/search/tokenize.go
  • backend/internal/data/search/tokenize_test.go
  • backend/internal/sys/config/conf.go
  • backend/internal/sys/config/conf_search_test.go
  • backend/pkgs/cgofreesqlite/sqlite.go
  • backend/pkgs/textutils/normalize.go
  • backend/pkgs/textutils/normalize_test.go
  • docs/src/content/docs/en/quick-start/configure/database.mdx
  • docs/src/content/docs/en/quick-start/configure/index.mdx
  • docs/src/content/docs/en/quick-start/configure/search.mdx
  • frontend/lib/api/classes/items.ts
  • frontend/locales/en.json
  • frontend/pages/items.vue

Comment thread backend/internal/data/search/database.go Outdated
Comment thread backend/internal/data/search/meilisearch.go
Comment thread backend/internal/sys/config/conf_search_test.go
Comment thread backend/internal/sys/config/conf.go
Comment thread Taskfile.yml Outdated
@coderabbitai coderabbitai Bot added the go Pull requests that update Go code label Jun 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
backend/internal/sys/config/conf.go (1)

100-125: 💤 Low value

Well-implemented secure transport validation addressing the previous review concern.

The loopback allowlist correctly handles common cases. One minor edge case: Go's url.Parse doesn't normalize IPv6 addresses, so the full notation http://[0:0:0:0:0:0:0:1]:7700 bypasses the check since u.Hostname() returns 0:0:0:0:0:0:0:1 rather than ::1. This is obscure (requires intentional configuration by admin), but for completeness you could parse loopback IPs properly:

🛡️ Optional: normalize IPv6 loopback detection
 	case "http":
-		switch strings.ToLower(u.Hostname()) {
-		case "localhost", "127.0.0.1", "::1":
+		host := strings.ToLower(u.Hostname())
+		if host == "localhost" || host == "127.0.0.1" {
 			return nil
-		default:
+		}
+		if ip := net.ParseIP(host); ip != nil && ip.IsLoopback() {
+			return nil
+		}
 			return fmt.Errorf("search.meilisearch.host uses insecure http for non-local host %q: use https", u.Host)
-		}

This uses net.ParseIP(...).IsLoopback() which handles all IPv6 loopback representations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/sys/config/conf.go` around lines 100 - 125, The Validate()
method of MeilisearchConf uses string comparison on u.Hostname() to detect
loopback addresses, but Go's url.Parse does not normalize IPv6 addresses,
causing full IPv6 notation like http://[0:0:0:0:0:0:0:1]:7700 to bypass the
loopback check. Replace the string-based hostname check in the http case with a
proper IP-based check by parsing the hostname using net.ParseIP() and calling
IsLoopback() on the resulting net.IP object, which handles all IPv6 and IPv4
loopback representations correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@backend/internal/sys/config/conf.go`:
- Around line 100-125: The Validate() method of MeilisearchConf uses string
comparison on u.Hostname() to detect loopback addresses, but Go's url.Parse does
not normalize IPv6 addresses, causing full IPv6 notation like
http://[0:0:0:0:0:0:0:1]:7700 to bypass the loopback check. Replace the
string-based hostname check in the http case with a proper IP-based check by
parsing the hostname using net.ParseIP() and calling IsLoopback() on the
resulting net.IP object, which handles all IPv6 and IPv4 loopback
representations correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5d25a27b-c0ff-4338-8637-3754bad95873

📥 Commits

Reviewing files that changed from the base of the PR and between c17f58c and 5ecf47d.

📒 Files selected for processing (6)
  • Taskfile.yml
  • backend/internal/data/search/database.go
  • backend/internal/data/search/database_test.go
  • backend/internal/data/search/meilisearch.go
  • backend/internal/sys/config/conf.go
  • backend/internal/sys/config/conf_search_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • backend/internal/sys/config/conf_search_test.go
  • Taskfile.yml
  • backend/internal/data/search/database_test.go
  • backend/internal/data/search/database.go
  • backend/internal/data/search/meilisearch.go

# Conflicts:
#	backend/go.mod
#	backend/go.sum
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploying homebox-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4dff7eb
Status: ✅  Deploy successful!
Preview URL: https://792f864a.homebox-docs.pages.dev
Branch Preview URL: https://mk-better-search.homebox-docs.pages.dev

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📖 documentation Improvements or additions to documentation ⬆️ enhancement New feature or request go Pull requests that update Go code review needed A review is needed on this PR or Issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Search fails for Ukrainian items containing uppercase letters Better Search handling

1 participant