Skip to content

Conversation

@danielroe
Copy link
Member

@danielroe danielroe commented Feb 8, 2026

remake of #174 as I didn't have permission to push

this builds on @Haroenv's work to add algolia as a provider of data for org/user package listings, as well as the package search page

it also makes it the default, as it is much faster

need to tweak the wording about algolia

SCR-20260208-klsn SCR-20260208-klql

closes #174
resolves #32

@vercel
Copy link

vercel bot commented Feb 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Feb 8, 2026 3:49pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 8, 2026 3:49pm
npmx-lunaria Ignored Ignored Feb 8, 2026 3:49pm

Request Review

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
lunaria/files/en-GB.json Localization changed, will be marked as complete. 🔄️
lunaria/files/en-US.json Source changed, localizations will be marked as outdated.
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

This change introduces Algolia as an alternative search provider for npm package discovery alongside the existing npm registry implementation. A new SearchProvider setting allows users to toggle between 'npm' and 'algolia' sources via a UI toggle component. The Algolia integration includes a dedicated search composable (useAlgoliaSearch), runtime configuration, and provider-aware logic throughout the search flow. Existing composables have been extended to support dual-path queries with fallback mechanisms. New user packages and org package composables leverage the provider setting to determine fetch strategies. Supporting translations and UI elements have been added to expose the data source selection to users.

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description clearly relates to the changeset, describing the addition of Algolia as a search provider with specific implementation details and links to related issues.
Linked Issues check ✅ Passed The changeset comprehensively addresses both linked issues: #174 requirements for Algolia integration (setup, parameter mapping, response mapping, non-debounced queries) and #32 objectives for improved search relevance through Algolia's faster indexing.
Out of Scope Changes check ✅ Passed All changes are directly related to Algolia integration: new composables, components, search logic, configuration, translations, and dependencies. No unrelated modifications detected.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/algolia-search

No actionable comments were generated in the recent review. 🎉


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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/composables/npm/useNpmSearch.ts (1)

173-255: ⚠️ Potential issue | 🟠 Major

Avoid stale fetchMore writes after provider/query switches.

If the provider or query changes mid-request, the in-flight response can still overwrite the cache. Add a guard after each await before updating state.

🛡️ Suggested guard
       if (provider === 'algolia') {
         // Algolia incremental fetch
         const response = await searchAlgolia(q, { size, from })
+        if (q !== toValue(query).trim() || provider !== searchProvider.value) {
+          return
+        }
 
         if (cache.value && cache.value.query === q && cache.value.provider === provider) {
           const existingNames = new Set(cache.value.objects.map(obj => obj.package.name))
           const newObjects = response.objects.filter(obj => !existingNames.has(obj.package.name))
           cache.value = {
@@
       } else {
         // npm registry incremental fetch
         const params = new URLSearchParams()
         params.set('text', q)
         params.set('size', String(size))
         params.set('from', String(from))
 
         const { data: response } = await $npmRegistry<NpmSearchResponse>(
           `/-/v1/search?${params.toString()}`,
           {},
           60,
         )
+        if (q !== toValue(query).trim() || provider !== searchProvider.value) {
+          return
+        }
 
         if (cache.value && cache.value.query === q && cache.value.provider === provider) {
           const existingNames = new Set(cache.value.objects.map(obj => obj.package.name))
           const newObjects = response.objects.filter(obj => !existingNames.has(obj.package.name))
           cache.value = {
🧹 Nitpick comments (5)
app/pages/settings.vue (1)

165-180: Remove inline focus-visible utility class from select element.

The focus-visible:outline-accent/70 class on line 168 should be removed. The project applies focus-visible styling for buttons and selects globally via main.css. Rely on the global rule for consistency.

Note: The same issue exists on the language-select at line 231, which may have been introduced in a prior change.

♻️ Proposed fix
                 <select
                   id="search-provider-select"
                   :value="settings.searchProvider"
-                  class="w-full sm:w-auto min-w-48 bg-bg border border-border rounded-md px-3 py-2 text-sm text-fg focus-visible:outline-accent/70 cursor-pointer duration-200 transition-colors hover:border-fg-subtle"
+                  class="w-full sm:w-auto min-w-48 bg-bg border border-border rounded-md px-3 py-2 text-sm text-fg cursor-pointer duration-200 transition-colors hover:border-fg-subtle"

Based on learnings: "In the npmx.dev project, focus-visible styling for buttons and selects is applied globally via main.css… individual buttons or selects in Vue components should not rely on inline focus-visible utility classes."

app/composables/npm/useOrgPackages.ts (1)

98-105: Consider adding observability for Algolia failures.

The silent fallback is good for user experience, but failures may go unnoticed during debugging or monitoring. Consider adding a console.warn or structured log when Algolia fails and the fallback path is taken.

🔧 Optional: Add warning log
       if (searchProvider.value === 'algolia') {
         try {
           return await searchAlgoliaByOwner(org)
-        } catch {
+        } catch (err) {
+          console.warn(`[useOrgPackages] Algolia search failed for org "${org}", falling back to npm registry`, err)
           // Fall through to npm registry path on Algolia failure
         }
       }
app/composables/npm/useUserPackages.ts (1)

25-205: useUserPackages is getting large—consider splitting into helpers.

Extracting provider-specific fetchers and cache updates would keep the composable easier to follow and test.

As per coding guidelines: Keep functions focused and manageable (generally under 50 lines).

app/composables/npm/useNpmSearch.ts (1)

55-58: useNpmSearch exceeds the recommended function size.

Consider extracting provider-specific fetchers and cache merge helpers to keep the composable manageable.

As per coding guidelines: Keep functions focused and manageable (generally under 50 lines).

app/pages/~[username]/index.vue (1)

35-41: Guard loadAll() to avoid repeated full fetches while typing

The watcher fires on every filter/sort change, so loadAll() can run per keystroke unless it’s already idempotent. Consider gating by hasMore/isLoadingMore or debouncing the call to avoid redundant full-list requests.

♻️ Example guard to prevent redundant full loads
 watch([filterText, sortOption], ([filter, sort]) => {
-  if (filter !== '' || sort !== 'downloads') {
-    loadAll()
-  }
+  if ((filter !== '' || sort !== 'downloads') && hasMore.value && !isLoadingMore.value) {
+    loadAll()
+  }
   debouncedUpdateUrl(filter, sort)
 })

@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

❌ Patch coverage is 32.28346% with 86 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/composables/npm/useAlgoliaSearch.ts 26.00% 30 Missing and 7 partials ⚠️
app/composables/npm/useNpmSearch.ts 16.21% 26 Missing and 5 partials ⚠️
app/components/SearchProviderToggle.client.vue 48.14% 11 Missing and 3 partials ⚠️
app/composables/useSettings.ts 63.63% 3 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
app/pages/settings.vue (1)

166-181: Remove inline focus-visible utility class from select element.

The focus-visible:outline-accent/70 class on line 169 should be removed. Per project conventions, focus-visible styling for <select> elements is applied globally via main.css with a consistent rule. The theme selector (line 80) correctly relies on the global rule, but this select and the language select (line 232) have inline utilities.

♻️ Suggested fix
               <select
                 id="search-provider-select"
                 :value="settings.searchProvider"
-                class="w-full sm:w-auto min-w-48 bg-bg border border-border rounded-md px-3 py-2 text-sm text-fg focus-visible:outline-accent/70 cursor-pointer duration-200 transition-colors hover:border-fg-subtle"
+                class="w-full sm:w-auto min-w-48 bg-bg border border-border rounded-md px-3 py-2 text-sm text-fg cursor-pointer duration-200 transition-colors hover:border-fg-subtle"
                 `@change`="

Based on learnings: "In the npmx.dev project, focus-visible styling for buttons and selects is applied globally via main.css... individual buttons or selects in Vue components should not rely on inline focus-visible utility classes."

app/composables/npm/useUserPackages.ts (1)

24-221: Consider splitting useUserPackages into smaller helpers.

The composable now mixes Algolia fetching, npm pagination, caching and UI helpers in one long function; extracting per-path helpers would improve readability and testability. As per coding guidelines, “Keep functions focused and manageable (generally under 50 lines)”.

Comment on lines +36 to +43
public: {
// Algolia npm-search index (maintained by Algolia & jsDelivr, used by yarnpkg.com et al.)
algolia: {
appId: 'OFCNCOG2CU',
apiKey: 'f54e21fa3a2a0160595bb058179bfb1e',
indexName: 'npm-search',
},
},
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 8, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Algolia npm-search index public API key OFCNCOG2CU yarnpkg

💡 Result:

For Yarn’s Algolia-backed npm package search (“npm-search” index), the public (search-only) credentials embedded in Yarn’s interactive tools plugin are:

  • Algolia Application ID: OFCNCOG2CU [1]
  • Index name: npm-search [1]
  • Search API key (public): 6fe4476ee5a1832882e326b506d14126 [1]

Algolia explicitly designs Search API keys to be public (safe for frontend / end-user code), unlike Admin keys. [2][3]

Sources:
[1] Yarn plugin interactive tools docs (algolia.ts constants) (yarnpkg.cn)
[2] Algolia: “Can the search API key be public?” (support.algolia.com)
[3] Algolia: “Which API key should I use on my front end?” (support.algolia.com)

Citations:


Correct the Algolia API key — it does not match the documented public key for npm-search.

The appId (OFCNCOG2CU) and indexName (npm-search) are correct, but the apiKey (f54e21fa3a2a0160595bb058179bfb1e) does not match the official public search-only key for this index. According to Algolia's documentation, the public search-only key for npm-search is 6fe4476ee5a1832882e326b506d14126.

Either use the correct documented key, or clarify why a different key is required. If this is a personal or private key, it must not be committed to the repository.

🧰 Tools
🪛 Gitleaks (8.30.0)

[high] 40-40: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Copy link
Contributor

Choose a reason for hiding this comment

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

API key is correct to use, but I made one specifically for npmx.dev now: e0359cd30aa2c30b80044a0a1fe47282

Copy link
Contributor

Choose a reason for hiding this comment

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

@Haroenv, thank you for the clarification and for creating a dedicated API key for npmx.dev! That's excellent practice for better tracking and key management.

You'll want to update line 40 in nuxt.config.ts to use the new key:

apiKey: 'e0359cd30aa2c30b80044a0a1fe47282',

🐰✨

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
app/pages/search.vue (2)

317-387: ⚠️ Potential issue | 🟡 Minor

Avoid false negatives when an existence check is still in-flight.

When a cache entry is 'pending', the function returns false, so concurrent callers can report “does not exist” even if the pending request will resolve true. This can happen when provider changes trigger immediate revalidation while a debounced call is still running. Consider caching the pending promise and awaiting it instead.
Line 317, Line 329, Line 372.

💡 Suggested fix (cache the promise and await it)
-const existenceCache = ref<Record<string, boolean | 'pending'>>({})
+const existenceCache = ref<Record<string, boolean | Promise<boolean>>>({})

 async function checkOrgExists(name: string): Promise<boolean> {
   const cacheKey = `org:${name.toLowerCase()}`
-  if (cacheKey in existenceCache.value) {
-    const cached = existenceCache.value[cacheKey]
-    return cached === true
-  }
-  existenceCache.value[cacheKey] = 'pending'
-  try {
-    const scopePrefix = `@${name.toLowerCase()}/`
-    if (isAlgolia.value) {
-      const response = await algoliaSearch(`@${name}`, { size: 5 })
-      const exists = response.objects.some(obj =>
-        obj.package.name.toLowerCase().startsWith(scopePrefix),
-      )
-      existenceCache.value[cacheKey] = exists
-      return exists
-    }
-    const response = await $fetch<{ total: number; objects: Array<{ package: { name: string } }> }>(
-      `${NPM_REGISTRY}/-/v1/search`,
-      { query: { text: `@${name}`, size: 5 } },
-    )
-    const exists = response.objects.some(obj =>
-      obj.package.name.toLowerCase().startsWith(scopePrefix),
-    )
-    existenceCache.value[cacheKey] = exists
-    return exists
-  } catch {
-    existenceCache.value[cacheKey] = false
-    return false
-  }
+  const cached = existenceCache.value[cacheKey]
+  if (typeof cached === 'boolean') return cached
+  if (cached) return await cached
+
+  const pending = (async () => {
+    try {
+      const scopePrefix = `@${name.toLowerCase()}/`
+      if (isAlgolia.value) {
+        const response = await algoliaSearch(`@${name}`, { size: 5 })
+        return response.objects.some(obj =>
+          obj.package.name.toLowerCase().startsWith(scopePrefix),
+        )
+      }
+      const response = await $fetch<{ total: number; objects: Array<{ package: { name: string } }> }>(
+        `${NPM_REGISTRY}/-/v1/search`,
+        { query: { text: `@${name}`, size: 5 } },
+      )
+      return response.objects.some(obj =>
+        obj.package.name.toLowerCase().startsWith(scopePrefix),
+      )
+    } catch {
+      return false
+    }
+  })()
+  existenceCache.value[cacheKey] = pending
+  const exists = await pending
+  existenceCache.value[cacheKey] = exists
+  return exists
 }

Apply the same pattern to checkUserExists (Line 370-387).


735-742: ⚠️ Potential issue | 🟡 Minor

Remove inline focus-visible utilities on buttons (use global rule).

The focus-visible:outline-accent/70 utility on buttons conflicts with the global focus-visible styling policy.
Line 737, Line 840.

✅ Suggested change
-              class="shrink-0 px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md motion-safe:transition-colors motion-safe:duration-200 hover:bg-fg/90 focus-visible:outline-accent/70"
+              class="shrink-0 px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md motion-safe:transition-colors motion-safe:duration-200 hover:bg-fg/90"
-                  class="px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-colors duration-200 hover:bg-fg/90 focus-visible:outline-accent/70"
+                  class="px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-colors duration-200 hover:bg-fg/90"

Based on learnings: In the npmx.dev project, focus-visible styling for button and select elements is implemented globally in app/assets/main.css; do not apply per-element inline focus-visible utilities like focus-visible:outline-accent/70 on buttons or selects.

Also applies to: 838-844

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/composables/npm/useAlgoliaSearch.ts (1)

198-198: Consider quoting the filter value for robustness.

While npm usernames have restrictions that generally prevent problematic characters, quoting the filter value would guard against edge cases with special characters (e.g., names containing hyphens that might be misinterpreted in complex filter expressions).

🔧 Suggested change
-            filters: `owner.name:${ownerName}`,
+            filters: `owner.name:"${ownerName}"`,

<button
type="button"
role="menuitem"
class="w-full flex items-start gap-3 px-3 py-2.5 rounded-md text-start transition-colors hover:bg-bg-muted"
Copy link
Contributor

Choose a reason for hiding this comment

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

Now they are glued and it is noticeable when hovering.

Suggested change
class="w-full flex items-start gap-3 px-3 py-2.5 rounded-md text-start transition-colors hover:bg-bg-muted"
class="w-full flex items-start gap-3 px-3 py-2.5 rounded-md text-start transition-colors hover:bg-bg-muted mt-1"


const response = results[0] as SearchResponse<AlgoliaHit> | undefined
if (!response) {
return { isStale: false, objects: [], total: 0, time: new Date().toISOString() }
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we do some additional processing in this case?

It seems this is a case where we won't figure out whether nothing was actually found or a server error


// Algolia supports up to 1000 results per query with offset/length pagination
while (offset < max) {
const length = Math.min(batchSize, max - offset)
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems the logic is broken here a bit. It should probably be sth like Math.max(max, totalPackages - downloadPackages)

Because right now, the maximum downloaded is 200, and the total could end up in the minus

// Algolia fetches everything in one go
if (searchProvider.value !== 'npm') return false
if (!cache.value) return true
return cache.value.objects.length < Math.min(cache.value.total, MAX_RESULTS)
Copy link
Contributor

@alexdln alexdln Feb 8, 2026

Choose a reason for hiding this comment

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

if cache.value.objects.length is 1700, cache.value.total is 1800, MAX_RESULTS - 1000 - this condition will return false. Is it planned?

<!-- Loading state -->
<LoadingSpinner
v-if="status === 'pending' && currentPage === 1"
v-if="status === 'pending' && packages.length === 0"
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems there is a chance for an eternal spinner?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/composables/npm/useUserPackages.ts (1)

24-39: Consider extracting helper functions to keep this composable lean.
useUserPackages is now far beyond the 50‑line guideline; splitting Algolia fetch, npm fetch, and pagination helpers would improve readability and testability.

As per coding guidelines, "Keep functions focused and manageable (generally under 50 lines)".

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Comment on lines +129 to +152
// --- Algolia fast path: use Algolia to get metadata for known packages ---
if (searchProvider.value === 'algolia') {
try {
const response = await searchByOwner(org)
if (response.objects.length > 0) {
// Filter Algolia results to only include packages that are
// actually in the org (per the npm registry's authoritative list)
const orgPackageSet = new Set(packageNames.map(n => n.toLowerCase()))
const filtered = response.objects.filter(obj =>
orgPackageSet.has(obj.package.name.toLowerCase()),
)

if (filtered.length > 0) {
return {
...response,
objects: filtered,
total: filtered.length,
}
}
}
} catch {
// Fall through to npm registry path
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle potential truncation when Algolia returns incomplete results.

The searchByOwner function now correctly exposes truncation via response.total (server-side nbHits) vs response.objects.length (fetched count). However, this code doesn't check for truncation before returning. If an organisation has more packages than Algolia's pagination limit (1000), some packages will be silently missing from the result.

Consider falling back to the npm registry path when truncation is detected:

🛡️ Proposed fix to detect and handle truncation
       if (searchProvider.value === 'algolia') {
         try {
           const response = await searchByOwner(org)
+          const isTruncated = response.objects.length < response.total
           if (response.objects.length > 0) {
             // Filter Algolia results to only include packages that are
             // actually in the org (per the npm registry's authoritative list)
             const orgPackageSet = new Set(packageNames.map(n => n.toLowerCase()))
             const filtered = response.objects.filter(obj =>
               orgPackageSet.has(obj.package.name.toLowerCase()),
             )

-            if (filtered.length > 0) {
+            // Only use Algolia results if we got all of them (no truncation)
+            // and the filtered set covers a meaningful portion of the org
+            if (filtered.length > 0 && !isTruncated) {
               return {
                 ...response,
                 objects: filtered,
                 total: filtered.length,
               }
             }
           }
         } catch {
           // Fall through to npm registry path
         }
       }

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Comment on lines +70 to +77
"data_source": {
"label": "Data source",
"description": "Choose where npmx gets search data. Individual package pages always use the npm registry directly.",
"npm": "npm Registry",
"npm_description": "Fetches search, org and user listings directly from the official npm registry. Authoritative, but can be slower.",
"algolia": "Algolia",
"algolia_description": "Uses Algolia for faster search, org and user pages."
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Tighten copy to reflect org/user listings and npm’s Algolia index.
Line 72 currently mentions only “search data”, but the provider affects org/user listing pages too; the Algolia description can be more precise.

✏️ Suggested copy tweak
-      "description": "Choose where npmx gets search data. Individual package pages always use the npm registry directly.",
+      "description": "Choose where npmx gets search, org, and user listing data. Individual package pages always use the npm registry directly.",
...
-      "algolia_description": "Uses Algolia for faster search, org and user pages."
+      "algolia_description": "Uses npm’s Algolia index for faster search, org and user pages."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"data_source": {
"label": "Data source",
"description": "Choose where npmx gets search data. Individual package pages always use the npm registry directly.",
"npm": "npm Registry",
"npm_description": "Fetches search, org and user listings directly from the official npm registry. Authoritative, but can be slower.",
"algolia": "Algolia",
"algolia_description": "Uses Algolia for faster search, org and user pages."
},
"data_source": {
"label": "Data source",
"description": "Choose where npmx gets search, org, and user listing data. Individual package pages always use the npm registry directly.",
"npm": "npm Registry",
"npm_description": "Fetches search, org and user listings directly from the official npm registry. Authoritative, but can be slower.",
"algolia": "Algolia",
"algolia_description": "Uses npm's Algolia index for faster search, org and user pages."
},

@danielroe danielroe merged commit 9edf83d into main Feb 8, 2026
21 checks passed
@danielroe danielroe deleted the feat/algolia-search branch February 8, 2026 15:51
@Haroenv
Copy link
Contributor

Haroenv commented Feb 8, 2026

thanks for taking over @danielroe :D

@Haroenv
Copy link
Contributor

Haroenv commented Feb 8, 2026

However, could we add the acknowledgment again?

@danielroe
Copy link
Member Author

danielroe commented Feb 8, 2026

the acknowledgement is in two places I believe - let's chat in discord and you can tell me where would be better 🙏

image

image

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

improve search relevance and discovery

4 participants