diff --git a/.env.local.example b/.env.local.example
index b75174ae5..2fa613e3e 100644
--- a/.env.local.example
+++ b/.env.local.example
@@ -9,3 +9,8 @@ OPENAI_API_KEY=
# Get a key from https://console.anthropic.com/
# Falls back to OPENAI_API_KEY if not set
ANTHROPIC_API_KEY=
+
+# Algolia search (search API key is public/read-only)
+NEXT_PUBLIC_ALGOLIA_APP_ID=
+NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY=
+NEXT_PUBLIC_ALGOLIA_INDEX_NAME=
diff --git a/.gitignore b/.gitignore
index 8e9f00c4e..da4d2840a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,8 +5,6 @@ node_modules
.env.local
public/sitemap*.xml
.env
-_pagefind/
-
# TypeScript
*.tsbuildinfo
diff --git a/app/_components/algolia-search.tsx b/app/_components/algolia-search.tsx
new file mode 100644
index 000000000..cf0dbdec4
--- /dev/null
+++ b/app/_components/algolia-search.tsx
@@ -0,0 +1,181 @@
+"use client";
+
+import { liteClient as algoliasearch } from "algoliasearch/lite";
+import { Search } from "lucide-react";
+import { useEffect, useState } from "react";
+import {
+ Highlight,
+ Hits,
+ InstantSearch,
+ SearchBox,
+ useInstantSearch,
+} from "react-instantsearch";
+
+type HitRecord = {
+ objectID: string;
+ title?: string;
+ description?: string;
+ url?: string;
+};
+
+const appId = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID;
+const searchKey = process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY;
+const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX_NAME;
+
+const searchClient =
+ appId && searchKey ? algoliasearch(appId, searchKey) : null;
+
+function safeHref(url: string | undefined): string {
+ if (!url) {
+ return "/";
+ }
+ if (url.startsWith("/") || url.startsWith("https://")) {
+ return url;
+ }
+ return "/";
+}
+
+function SearchHit({ hit }: { hit: HitRecord }) {
+ return (
+
+
+ [0]["hit"]}
+ />
+
+ {hit.description && (
+
+ [0]["hit"]}
+ />
+
+ )}
+
+ );
+}
+
+function EmptyQuery() {
+ const { indexUiState } = useInstantSearch();
+ if (indexUiState.query) {
+ return null;
+ }
+ return (
+
+ Start typing to search the docs…
+
+ );
+}
+
+function NoResults() {
+ const { results } = useInstantSearch();
+ if (!results?.query || results.nbHits > 0) {
+ return null;
+ }
+ return (
+
+ No results for{" "}
+ "{results.query}"
+
+ );
+}
+
+function SearchUnavailable() {
+ return (
+
+ Add NEXT_PUBLIC_ALGOLIA_APP_ID,{" "}
+ NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY, and{" "}
+ NEXT_PUBLIC_ALGOLIA_INDEX_NAME to your
+ environment to enable search.
+
+ );
+}
+
+export function AlgoliaSearch() {
+ const [isOpen, setIsOpen] = useState(false);
+
+ useEffect(() => {
+ const handler = (e: KeyboardEvent) => {
+ if ((e.metaKey || e.ctrlKey) && e.key === "k") {
+ e.preventDefault();
+ setIsOpen((prev) => !prev);
+ }
+ if (e.key === "Escape") {
+ setIsOpen(false);
+ }
+ };
+ window.addEventListener("keydown", handler);
+ return () => window.removeEventListener("keydown", handler);
+ }, []);
+
+ return (
+ <>
+
+
+ {isOpen && (
+
+
+ )}
+ >
+ );
+}
diff --git a/app/_components/toolkit-docs/components/documentation-chunk-renderer.tsx b/app/_components/toolkit-docs/components/documentation-chunk-renderer.tsx
index 70ccf3740..8ed9808ca 100644
--- a/app/_components/toolkit-docs/components/documentation-chunk-renderer.tsx
+++ b/app/_components/toolkit-docs/components/documentation-chunk-renderer.tsx
@@ -112,19 +112,14 @@ const MDX_COMPONENTS = {
// Maximum number of MDX components to cache to prevent unbounded memory growth
const MDX_CACHE_MAX_SIZE = 100;
-const mdxCache =
- createMdxCache>(
- MDX_CACHE_MAX_SIZE
- );
+const mdxCache = createMdxCache(MDX_CACHE_MAX_SIZE);
/**
* Renders MDX content from a string with custom components.
*/
function MdxContent({ content }: { content: string }) {
const source = useMemo(() => stripMdxImports(content), [content]);
- const [Component, setComponent] = useState | null>(null);
+ const [Component, setComponent] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
diff --git a/app/globals.css b/app/globals.css
index eb7ac1ba2..4896714a7 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -145,7 +145,7 @@ nav > a[aria-label="Home page"] {
margin-inline-end: 3.5rem !important;
}
-nav > div:has(.nextra-search) {
+nav > div:has(.algolia-search-button) {
order: -1;
margin-inline-start: 1rem;
margin-inline-end: auto;
@@ -157,6 +157,21 @@ nav > div:has(.nextra-search) {
}
}
+/* Algolia search hit highlight — brand red */
+.ais-Highlight-highlighted,
+.ais-Snippet-highlighted {
+ background: color-mix(in oklch, var(--primary) 15%, transparent);
+ color: var(--primary);
+ border-radius: 2px;
+ font-style: normal;
+ font-weight: 600;
+}
+
+.dark .ais-Highlight-highlighted,
+.dark .ais-Snippet-highlighted {
+ background: color-mix(in oklch, var(--primary) 20%, transparent);
+}
+
/* Override Nextra code highlight colors to use green instead of red */
[data-highlighted-line] {
background-color: color-mix(in oklab, #22c55e 20%, transparent) !important;
diff --git a/app/layout.tsx b/app/layout.tsx
index 2d8aa10e4..dcb44963a 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,4 +1,5 @@
import { getDictionary } from "@/_dictionaries/get-dictionary";
+import { AlgoliaSearch } from "@/app/_components/algolia-search";
import { SignupLink } from "@/app/_components/analytics";
import CustomLayout from "@/app/_components/custom-layout";
import { getDashboardUrl } from "@/app/_components/dashboard-link";
@@ -171,6 +172,7 @@ export default async function RootLayout({
}
nextThemes={{ defaultTheme: "dark" }}
pageMap={pageMap}
+ search={}
sidebar={{
defaultMenuCollapseLevel: 2,
autoCollapse: true,
diff --git a/middleware.ts b/middleware.ts
index 7cd936828..26d0f14c3 100644
--- a/middleware.ts
+++ b/middleware.ts
@@ -239,6 +239,6 @@ export function middleware(request: NextRequest) {
export const config = {
matcher: [
- "/((?!api|_next/static|_next/image|favicon.ico|manifest|_pagefind|public|.*.svg|.*.png|.*.jpg|.*.jpeg|.*.gif|.*.webp|.*.ico|.*.css|.*.js|.*.woff|.*.woff2|.*.ttf|.*.eot|.*.otf|.*.pdf|.*.txt|.*.xml|.*.json|.*.py|.*.mp4).*)",
+ "/((?!api|_next/static|_next/image|favicon.ico|manifest|public|.*.svg|.*.png|.*.jpg|.*.jpeg|.*.gif|.*.webp|.*.ico|.*.webmanifest|.*.css|.*.js|.*.woff|.*.woff2|.*.ttf|.*.eot|.*.otf|.*.pdf|.*.txt|.*.xml|.*.json|.*.py|.*.mp4).*)",
],
};
diff --git a/next.config.ts b/next.config.ts
index ca7f49680..a8dbde6a3 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -7,6 +7,7 @@ import { remarkGlossary } from "./lib/remark-glossary";
const withNextra = nextra({
defaultShowCopyCode: true,
codeHighlight: true,
+ search: false,
mdxOptions: {
remarkPlugins: [
[
diff --git a/package.json b/package.json
index f796fcd9b..de66c501b 100644
--- a/package.json
+++ b/package.json
@@ -5,17 +5,16 @@
"type": "module",
"scripts": {
"dev": "next dev --webpack",
- "build": "pnpm run toolkit-markdown && next build --webpack && pnpm run custompagefind",
+ "build": "pnpm run toolkit-markdown && next build --webpack",
"start": "next start",
"lint": "pnpm exec ultracite check",
"format": "pnpm exec ultracite fix",
"prepare": "husky install",
"toolkit-markdown": "pnpm dlx tsx toolkit-docs-generator/scripts/generate-toolkit-markdown.ts",
- "postbuild": "if [ \"$SKIP_POSTBUILD\" != \"true\" ]; then pnpm run generate:markdown && pnpm run custompagefind; fi",
+ "postbuild": "if [ \"$SKIP_POSTBUILD\" != \"true\" ]; then pnpm run generate:markdown; fi",
"generate:markdown": "pnpm dlx tsx scripts/generate-clean-markdown.ts",
"translate": "pnpm dlx tsx scripts/i18n-sync/index.ts && pnpm format",
"llmstxt": "pnpm dlx tsx scripts/generate-llmstxt.ts",
- "custompagefind": "pnpm dlx tsx scripts/pagefind.ts",
"test": "vitest --run",
"test:watch": "vitest --watch",
"vale": "vale",
@@ -49,6 +48,7 @@
"@ory/client": "1.22.7",
"@theguild/remark-mermaid": "0.3.0",
"@uidotdev/usehooks": "2.4.1",
+ "algoliasearch": "^5.49.1",
"chalk": "^5.6.2",
"lucide-react": "0.548.0",
"mdast-util-to-string": "4.0.0",
@@ -61,6 +61,7 @@
"react": "19.2.3",
"react-dom": "19.2.3",
"react-hook-form": "7.65.0",
+ "react-instantsearch": "^7.26.0",
"react-markdown": "^10.1.0",
"react-syntax-highlighter": "16.1.0",
"remark-gfm": "^4.0.1",
@@ -93,12 +94,8 @@
"next-validate-link": "1.6.3",
"openai": "6.7.0",
"ora": "9.0.0",
- "pagefind": "1.4.0",
"picocolors": "1.1.1",
"postcss": "8.5.6",
- "rehype-stringify": "^10.0.1",
- "remark": "^15.0.1",
- "remark-rehype": "^11.1.2",
"tailwindcss": "4.1.16",
"turndown": "^7.2.2",
"typescript": "5.9.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 212a48a6d..36ab95e17 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -32,6 +32,9 @@ importers:
'@uidotdev/usehooks':
specifier: 2.4.1
version: 2.4.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ algoliasearch:
+ specifier: ^5.49.1
+ version: 5.49.1
chalk:
specifier: ^5.6.2
version: 5.6.2
@@ -68,6 +71,9 @@ importers:
react-hook-form:
specifier: 7.65.0
version: 7.65.0(react@19.2.3)
+ react-instantsearch:
+ specifier: ^7.26.0
+ version: 7.26.0(algoliasearch@5.49.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
react-markdown:
specifier: ^10.1.0
version: 10.1.0(@types/react@19.2.7)(react@19.2.3)
@@ -159,24 +165,12 @@ importers:
ora:
specifier: 9.0.0
version: 9.0.0
- pagefind:
- specifier: 1.4.0
- version: 1.4.0
picocolors:
specifier: 1.1.1
version: 1.1.1
postcss:
specifier: 8.5.6
version: 8.5.6
- rehype-stringify:
- specifier: ^10.0.1
- version: 10.0.1
- remark:
- specifier: ^15.0.1
- version: 15.0.1
- remark-rehype:
- specifier: ^11.1.2
- version: 11.1.2
tailwindcss:
specifier: 4.1.16
version: 4.1.16
@@ -198,6 +192,65 @@ importers:
packages:
+ '@algolia/abtesting@1.15.1':
+ resolution: {integrity: sha512-2yuIC48rUuHGhU1U5qJ9kJHaxYpJ0jpDHJVI5ekOxSMYXlH4+HP+pA31G820lsAznfmu2nzDV7n5RO44zIY1zw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-abtesting@5.49.1':
+ resolution: {integrity: sha512-h6M7HzPin+45/l09q0r2dYmocSSt2MMGOOk5c4O5K/bBBlEwf1BKfN6z+iX4b8WXcQQhf7rgQwC52kBZJt/ZZw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-analytics@5.49.1':
+ resolution: {integrity: sha512-048T9/Z8OeLmTk8h76QUqaNFp7Rq2VgS2Zm6Y2tNMYGQ1uNuzePY/udB5l5krlXll7ZGflyCjFvRiOtlPZpE9g==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-common@5.49.1':
+ resolution: {integrity: sha512-vp5/a9ikqvf3mn9QvHN8PRekn8hW34aV9eX+O0J5mKPZXeA6Pd5OQEh2ZWf7gJY6yyfTlLp5LMFzQUAU+Fpqpg==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-insights@5.49.1':
+ resolution: {integrity: sha512-B6N7PgkvYrul3bntTz/l6uXnhQ2bvP+M7NqTcayh681tSqPaA5cJCUBp/vrP7vpPRpej4Eeyx2qz5p0tE/2N2g==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-personalization@5.49.1':
+ resolution: {integrity: sha512-v+4DN+lkYfBd01Hbnb9ZrCHe7l+mvihyx218INRX/kaCXROIWUDIT1cs3urQxfE7kXBFnLsqYeOflQALv/gA5w==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-query-suggestions@5.49.1':
+ resolution: {integrity: sha512-Un11cab6ZCv0W+Jiak8UktGIqoa4+gSNgEZNfG8m8eTsXGqwIEr370H3Rqwj87zeNSlFpH2BslMXJ/cLNS1qtg==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-search@5.49.1':
+ resolution: {integrity: sha512-Nt9hri7nbOo0RipAsGjIssHkpLMHHN/P7QqENywAq5TLsoYDzUyJGny8FEiD/9KJUxtGH8blGpMedilI6kK3rA==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/events@4.0.1':
+ resolution: {integrity: sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==}
+
+ '@algolia/ingestion@1.49.1':
+ resolution: {integrity: sha512-b5hUXwDqje0Y4CpU6VL481DXgPgxpTD5sYMnfQTHKgUispGnaCLCm2/T9WbJo1YNUbX3iHtYDArp804eD6CmRQ==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/monitoring@1.49.1':
+ resolution: {integrity: sha512-bvrXwZ0WsL3rN6Q4m4QqxsXFCo6WAew7sAdrpMQMK4Efn4/W920r9ptOuckejOSSvyLr9pAWgC5rsHhR2FYuYw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/recommend@5.49.1':
+ resolution: {integrity: sha512-h2yz3AGeGkQwNgbLmoe3bxYs8fac4An1CprKTypYyTU/k3Q+9FbIvJ8aS1DoBKaTjSRZVoyQS7SZQio6GaHbZw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/requester-browser-xhr@5.49.1':
+ resolution: {integrity: sha512-2UPyRuUR/qpqSqH8mxFV5uBZWEpxhGPHLlx9Xf6OVxr79XO2ctzZQAhsmTZ6X22x+N8MBWpB9UEky7YU2HGFgA==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/requester-fetch@5.49.1':
+ resolution: {integrity: sha512-N+xlE4lN+wpuT+4vhNEwPVlrfN+DWAZmSX9SYhbz986Oq8AMsqdntOqUyiOXVxYsQtfLwmiej24vbvJGYv1Qtw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/requester-node-http@5.49.1':
+ resolution: {integrity: sha512-zA5bkUOB5PPtTr182DJmajCiizHp0rCJQ0Chf96zNFvkdESKYlDeYA3tQ7r2oyHbu/8DiohAQ5PZ85edctzbXA==}
+ engines: {node: '>= 14.0.0'}
+
'@alloc/quick-lru@5.2.0':
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
@@ -981,36 +1034,6 @@ packages:
'@ory/client@1.22.7':
resolution: {integrity: sha512-DOiZOXFAqG5d1AVgGhqkP3Hhvq9cf9b3EHJDXea6nSHGCg6isKbE/DFIYuAy220ymZ/J3IYYHG8k8CLje9VipA==}
- '@pagefind/darwin-arm64@1.4.0':
- resolution: {integrity: sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==}
- cpu: [arm64]
- os: [darwin]
-
- '@pagefind/darwin-x64@1.4.0':
- resolution: {integrity: sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==}
- cpu: [x64]
- os: [darwin]
-
- '@pagefind/freebsd-x64@1.4.0':
- resolution: {integrity: sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==}
- cpu: [x64]
- os: [freebsd]
-
- '@pagefind/linux-arm64@1.4.0':
- resolution: {integrity: sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==}
- cpu: [arm64]
- os: [linux]
-
- '@pagefind/linux-x64@1.4.0':
- resolution: {integrity: sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==}
- cpu: [x64]
- os: [linux]
-
- '@pagefind/windows-x64@1.4.0':
- resolution: {integrity: sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==}
- cpu: [x64]
- os: [win32]
-
'@posthog/core@1.22.0':
resolution: {integrity: sha512-WkmOnq95aAOu6yk6r5LWr5cfXsQdpVbWDCwOxQwxSne8YV6GuZET1ziO5toSQXgrgbdcjrSz2/GopAfiL6iiAA==}
@@ -2068,6 +2091,9 @@ packages:
'@swc/helpers@0.5.17':
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
+ '@swc/helpers@0.5.18':
+ resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==}
+
'@tailwindcss/node@4.1.16':
resolution: {integrity: sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==}
@@ -2299,6 +2325,9 @@ packages:
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+ '@types/dom-speech-recognition@0.0.1':
+ resolution: {integrity: sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw==}
+
'@types/estree-jsx@1.0.5':
resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
@@ -2308,9 +2337,15 @@ packages:
'@types/geojson@7946.0.16':
resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
+ '@types/google.maps@3.58.1':
+ resolution: {integrity: sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==}
+
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+ '@types/hogan.js@3.0.5':
+ resolution: {integrity: sha512-/uRaY3HGPWyLqOyhgvW9Aa43BNnLZrNeQxl2p8wqId4UHMfPKolSB+U7BlZyO1ng7MkLnyEAItsBzCG0SDhqrA==}
+
'@types/katex@0.16.7':
resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
@@ -2332,6 +2367,9 @@ packages:
'@types/prismjs@1.26.5':
resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==}
+ '@types/qs@6.14.0':
+ resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
+
'@types/ramda@0.30.2':
resolution: {integrity: sha512-PyzHvjCalm2BRYjAU6nIB3TprYwMNOUY/7P/N8bSzp9W/yM2YrtGtAnnVtaCNSeOZ8DzKyFDvaqQs7LnWwwmBA==}
@@ -2412,6 +2450,9 @@ packages:
'@zod/core@0.9.0':
resolution: {integrity: sha512-bVfPiV2kDUkAJ4ArvV4MHcPZA8y3xOX6/SjzSy2kX2ACopbaaAP4wk6hd/byRmfi9MLNai+4SFJMmcATdOyclg==}
+ abbrev@1.1.1:
+ resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -2422,6 +2463,15 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ algoliasearch-helper@3.28.0:
+ resolution: {integrity: sha512-GBN0xsxGggaCPElZq24QzMdfphrjIiV2xA+hRXE4/UMpN3nsF2WrM8q+x80OGvGpJWtB7F+4Hq5eSfWwuejXrg==}
+ peerDependencies:
+ algoliasearch: '>= 3.1 < 6'
+
+ algoliasearch@5.49.1:
+ resolution: {integrity: sha512-X3Pp2aRQhg4xUC6PQtkubn5NpRKuUPQ9FPDQlx36SmpFwwH2N0/tw4c+NXV3nw3PsgeUs+BuWGP0gjz3TvENLQ==}
+ engines: {node: '>= 14.0.0'}
+
ansi-escapes@7.2.0:
resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==}
engines: {node: '>=18'}
@@ -3192,6 +3242,13 @@ packages:
highlightjs-vue@1.0.0:
resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==}
+ hogan.js@3.0.2:
+ resolution: {integrity: sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==}
+ hasBin: true
+
+ htm@3.1.1:
+ resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==}
+
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
@@ -3230,6 +3287,14 @@ packages:
inline-style-parser@0.2.7:
resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+ instantsearch-ui-components@0.20.0:
+ resolution: {integrity: sha512-wZ+GT8lb10m3r6+9TEVLDQeB1YNRgXFSFSsfhzh4jUFMVDiovY+NE+cj7oNFk7GzFWvxQvXd7aPjTLDD7RkhnA==}
+
+ instantsearch.js@4.90.0:
+ resolution: {integrity: sha512-HfMMvQCsmrLikx93skFNXsoX+zkPEqzszYuFbh1nKMI7qy18QfL+yG7BKX/mt7HPC/SbP+k4vZQzXgIT2+SXPw==}
+ peerDependencies:
+ algoliasearch: '>= 3.1 < 6'
+
internmap@1.0.1:
resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==}
@@ -3490,6 +3555,15 @@ packages:
markdown-table@3.0.4:
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+ markdown-to-jsx@7.7.17:
+ resolution: {integrity: sha512-7mG/1feQ0TX5I7YyMZVDgCC/y2I3CiEhIRQIhyov9nGBP5eoVrOXXHuL5ZP8GRfxVZKRiXWJgwXkb9It+nQZfQ==}
+ engines: {node: '>= 10'}
+ peerDependencies:
+ react: '>= 0.14.0'
+ peerDependenciesMeta:
+ react:
+ optional: true
+
marked@16.4.2:
resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==}
engines: {node: '>= 20'}
@@ -3716,6 +3790,10 @@ packages:
mj-context-menu@0.6.1:
resolution: {integrity: sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==}
+ mkdirp@0.3.0:
+ resolution: {integrity: sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==}
+ deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
+
mlly@1.8.0:
resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
@@ -3828,6 +3906,10 @@ packages:
resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
hasBin: true
+ nopt@1.0.10:
+ resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==}
+ hasBin: true
+
npm-run-path@5.3.0:
resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -3845,6 +3927,10 @@ packages:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
onetime@6.0.0:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'}
@@ -3886,10 +3972,6 @@ packages:
package-manager-detector@1.6.0:
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
- pagefind@1.4.0:
- resolution: {integrity: sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==}
- hasBin: true
-
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
@@ -3994,6 +4076,10 @@ packages:
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ qs@6.15.0:
+ resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==}
+ engines: {node: '>=0.6'}
+
query-selector-shadow-dom@1.0.1:
resolution: {integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==}
@@ -4081,6 +4167,19 @@ packages:
peerDependencies:
react: ^16.8.4 || ^17.0.0 || ^18.0.0
+ react-instantsearch-core@7.26.0:
+ resolution: {integrity: sha512-Pi+sUkOLQhWG0rv550YowJHk0wLVGiLiz6SK3s0Fbz4V2tJqd2t692jZ29zNWJPooFLHzMjTDQ4Wf2CDLXfHDw==}
+ peerDependencies:
+ algoliasearch: '>= 3.1 < 6'
+ react: '>= 16.8.0 < 20'
+
+ react-instantsearch@7.26.0:
+ resolution: {integrity: sha512-XzkNdH5ZVuwEyl7IUQabyi5OEqKWsEo6ny72saLdNCIfXL0O6wkcQvfhSzursoqw1zrwq3r0s+3dKRY4tVh6Cw==}
+ peerDependencies:
+ algoliasearch: '>= 3.1 < 6'
+ react: '>= 16.8.0 < 20'
+ react-dom: '>= 16.8.0 < 20'
+
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -4222,9 +4321,6 @@ packages:
rehype-recma@1.0.0:
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
- rehype-stringify@10.0.1:
- resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
-
remark-frontmatter@5.0.0:
resolution: {integrity: sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==}
@@ -4327,6 +4423,9 @@ packages:
scroll-into-view-if-needed@3.1.0:
resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==}
+ search-insights@2.17.3:
+ resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==}
+
section-matter@1.0.0:
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
engines: {node: '>=4'}
@@ -4371,6 +4470,22 @@ packages:
resolution: {integrity: sha512-KRT/hufMSxXKEDSQujfVE0Faa/kZ51ihUcZQAcmP04t00DvPj7Ox5anHke1sJYUtzSuiT/Y5uyzg/W7bBEGhCg==}
hasBin: true
+ side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
+ engines: {node: '>= 0.4'}
+
siginfo@2.0.0:
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
@@ -4881,6 +4996,11 @@ packages:
zenscroll@4.0.2:
resolution: {integrity: sha512-jEA1znR7b4C/NnaycInCU6h/d15ZzCd1jmsruqOKnZP6WXQSMH3W2GL+OXbkruslU4h+Tzuos0HdswzRUk/Vgg==}
+ zod-to-json-schema@3.24.6:
+ resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==}
+ peerDependencies:
+ zod: ^3.24.1
+
zod@4.0.0-beta.20250424T163858:
resolution: {integrity: sha512-fKhW+lEJnfUGo0fvQjmam39zUytARR2UdCEh7/OXJSBbKScIhD343K74nW+UUHu/r6dkzN6Uc/GqwogFjzpCXg==}
@@ -4910,6 +5030,92 @@ packages:
snapshots:
+ '@algolia/abtesting@1.15.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/client-abtesting@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/client-analytics@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/client-common@5.49.1': {}
+
+ '@algolia/client-insights@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/client-personalization@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/client-query-suggestions@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/client-search@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/events@4.0.1': {}
+
+ '@algolia/ingestion@1.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/monitoring@1.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/recommend@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
+ '@algolia/requester-browser-xhr@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+
+ '@algolia/requester-fetch@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+
+ '@algolia/requester-node-http@5.49.1':
+ dependencies:
+ '@algolia/client-common': 5.49.1
+
'@alloc/quick-lru@5.2.0': {}
'@antfu/install-pkg@1.1.0':
@@ -5567,24 +5773,6 @@ snapshots:
transitivePeerDependencies:
- debug
- '@pagefind/darwin-arm64@1.4.0':
- optional: true
-
- '@pagefind/darwin-x64@1.4.0':
- optional: true
-
- '@pagefind/freebsd-x64@1.4.0':
- optional: true
-
- '@pagefind/linux-arm64@1.4.0':
- optional: true
-
- '@pagefind/linux-x64@1.4.0':
- optional: true
-
- '@pagefind/windows-x64@1.4.0':
- optional: true
-
'@posthog/core@1.22.0':
dependencies:
cross-spawn: 7.0.6
@@ -6958,6 +7146,10 @@ snapshots:
dependencies:
tslib: 2.8.1
+ '@swc/helpers@0.5.18':
+ dependencies:
+ tslib: 2.8.1
+
'@tailwindcss/node@4.1.16':
dependencies:
'@jridgewell/remapping': 2.3.5
@@ -7201,6 +7393,8 @@ snapshots:
'@types/deep-eql@4.0.2': {}
+ '@types/dom-speech-recognition@0.0.1': {}
+
'@types/estree-jsx@1.0.5':
dependencies:
'@types/estree': 1.0.8
@@ -7209,10 +7403,14 @@ snapshots:
'@types/geojson@7946.0.16': {}
+ '@types/google.maps@3.58.1': {}
+
'@types/hast@3.0.4':
dependencies:
'@types/unist': 3.0.3
+ '@types/hogan.js@3.0.5': {}
+
'@types/katex@0.16.7': {}
'@types/mdast@4.0.4':
@@ -7233,6 +7431,8 @@ snapshots:
'@types/prismjs@1.26.5': {}
+ '@types/qs@6.14.0': {}
+
'@types/ramda@0.30.2':
dependencies:
types-ramda: 0.30.1
@@ -7317,12 +7517,36 @@ snapshots:
'@zod/core@0.9.0': {}
+ abbrev@1.1.1: {}
+
acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
acorn: 8.15.0
acorn@8.15.0: {}
+ algoliasearch-helper@3.28.0(algoliasearch@5.49.1):
+ dependencies:
+ '@algolia/events': 4.0.1
+ algoliasearch: 5.49.1
+
+ algoliasearch@5.49.1:
+ dependencies:
+ '@algolia/abtesting': 1.15.1
+ '@algolia/client-abtesting': 5.49.1
+ '@algolia/client-analytics': 5.49.1
+ '@algolia/client-common': 5.49.1
+ '@algolia/client-insights': 5.49.1
+ '@algolia/client-personalization': 5.49.1
+ '@algolia/client-query-suggestions': 5.49.1
+ '@algolia/client-search': 5.49.1
+ '@algolia/ingestion': 1.49.1
+ '@algolia/monitoring': 1.49.1
+ '@algolia/recommend': 5.49.1
+ '@algolia/requester-browser-xhr': 5.49.1
+ '@algolia/requester-fetch': 5.49.1
+ '@algolia/requester-node-http': 5.49.1
+
ansi-escapes@7.2.0:
dependencies:
environment: 1.1.0
@@ -8201,6 +8425,13 @@ snapshots:
highlightjs-vue@1.0.0: {}
+ hogan.js@3.0.2:
+ dependencies:
+ mkdirp: 0.3.0
+ nopt: 1.0.10
+
+ htm@3.1.1: {}
+
html-url-attributes@3.0.1: {}
html-void-elements@3.0.0: {}
@@ -8225,6 +8456,35 @@ snapshots:
inline-style-parser@0.2.7: {}
+ instantsearch-ui-components@0.20.0(react@19.2.3):
+ dependencies:
+ '@swc/helpers': 0.5.18
+ markdown-to-jsx: 7.7.17(react@19.2.3)
+ zod: 4.1.12
+ zod-to-json-schema: 3.24.6(zod@4.1.12)
+ transitivePeerDependencies:
+ - react
+
+ instantsearch.js@4.90.0(algoliasearch@5.49.1):
+ dependencies:
+ '@algolia/events': 4.0.1
+ '@swc/helpers': 0.5.18
+ '@types/dom-speech-recognition': 0.0.1
+ '@types/google.maps': 3.58.1
+ '@types/hogan.js': 3.0.5
+ '@types/qs': 6.14.0
+ algoliasearch: 5.49.1
+ algoliasearch-helper: 3.28.0(algoliasearch@5.49.1)
+ hogan.js: 3.0.2
+ htm: 3.1.1
+ instantsearch-ui-components: 0.20.0(react@19.2.3)
+ preact: 10.28.0
+ qs: 6.15.0
+ react: 19.2.3
+ search-insights: 2.17.3
+ zod: 4.1.12
+ zod-to-json-schema: 3.24.6(zod@4.1.12)
+
internmap@1.0.1: {}
internmap@2.0.3: {}
@@ -8444,6 +8704,10 @@ snapshots:
markdown-table@3.0.4: {}
+ markdown-to-jsx@7.7.17(react@19.2.3):
+ optionalDependencies:
+ react: 19.2.3
+
marked@16.4.2: {}
math-intrinsics@1.1.0: {}
@@ -8980,6 +9244,8 @@ snapshots:
mj-context-menu@0.6.1: {}
+ mkdirp@0.3.0: {}
+
mlly@1.8.0:
dependencies:
acorn: 8.15.0
@@ -9138,6 +9404,10 @@ snapshots:
node-gyp-build@4.8.4:
optional: true
+ nopt@1.0.10:
+ dependencies:
+ abbrev: 1.1.1
+
npm-run-path@5.3.0:
dependencies:
path-key: 4.0.0
@@ -9154,6 +9424,8 @@ snapshots:
object-assign@4.1.1: {}
+ object-inspect@1.13.4: {}
+
onetime@6.0.0:
dependencies:
mimic-fn: 4.0.0
@@ -9196,15 +9468,6 @@ snapshots:
package-manager-detector@1.6.0: {}
- pagefind@1.4.0:
- optionalDependencies:
- '@pagefind/darwin-arm64': 1.4.0
- '@pagefind/darwin-x64': 1.4.0
- '@pagefind/freebsd-x64': 1.4.0
- '@pagefind/linux-arm64': 1.4.0
- '@pagefind/linux-x64': 1.4.0
- '@pagefind/windows-x64': 1.4.0
-
parse-entities@4.0.2:
dependencies:
'@types/unist': 2.0.11
@@ -9337,6 +9600,10 @@ snapshots:
proxy-from-env@1.1.0: {}
+ qs@6.15.0:
+ dependencies:
+ side-channel: 1.1.0
+
query-selector-shadow-dom@1.0.1: {}
querystringify@2.2.0: {}
@@ -9468,6 +9735,27 @@ snapshots:
dependencies:
react: 19.2.3
+ react-instantsearch-core@7.26.0(algoliasearch@5.49.1)(react@19.2.3):
+ dependencies:
+ '@swc/helpers': 0.5.18
+ algoliasearch: 5.49.1
+ algoliasearch-helper: 3.28.0(algoliasearch@5.49.1)
+ instantsearch.js: 4.90.0(algoliasearch@5.49.1)
+ react: 19.2.3
+ use-sync-external-store: 1.6.0(react@19.2.3)
+ zod: 4.1.12
+ zod-to-json-schema: 3.24.6(zod@4.1.12)
+
+ react-instantsearch@7.26.0(algoliasearch@5.49.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ '@swc/helpers': 0.5.18
+ algoliasearch: 5.49.1
+ instantsearch-ui-components: 0.20.0(react@19.2.3)
+ instantsearch.js: 4.90.0(algoliasearch@5.49.1)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-instantsearch-core: 7.26.0(algoliasearch@5.49.1)(react@19.2.3)
+
react-is@16.13.1: {}
react-markdown@10.1.0(@types/react@19.2.7)(react@19.2.3):
@@ -9664,12 +9952,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- rehype-stringify@10.0.1:
- dependencies:
- '@types/hast': 3.0.4
- hast-util-to-html: 9.0.5
- unified: 11.0.5
-
remark-frontmatter@5.0.0:
dependencies:
'@types/mdast': 4.0.4
@@ -9852,6 +10134,8 @@ snapshots:
dependencies:
compute-scroll-into-view: 3.1.1
+ search-insights@2.17.3: {}
+
section-matter@1.0.0:
dependencies:
extend-shallow: 2.0.1
@@ -9932,6 +10216,34 @@ snapshots:
short-unique-id@5.3.2: {}
+ side-channel-list@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
siginfo@2.0.0: {}
signal-exit@4.1.0: {}
@@ -10474,6 +10786,10 @@ snapshots:
zenscroll@4.0.2: {}
+ zod-to-json-schema@3.24.6(zod@4.1.12):
+ dependencies:
+ zod: 4.1.12
+
zod@4.0.0-beta.20250424T163858:
dependencies:
'@zod/core': 0.9.0
diff --git a/scripts/pagefind.ts b/scripts/pagefind.ts
deleted file mode 100644
index 5e8e912be..000000000
--- a/scripts/pagefind.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-import fs from "node:fs/promises";
-import path, { dirname } from "node:path";
-import { fileURLToPath } from "node:url";
-import glob from "fast-glob";
-import { createIndex } from "pagefind";
-import rehypeStringify from "rehype-stringify";
-import { remark } from "remark";
-import remarkRehype from "remark-rehype";
-import { readToolkitData } from "@/app/_lib/toolkit-data";
-import { listToolkitRoutes } from "@/app/_lib/toolkit-static-params";
-import { toolkitDataToSearchMarkdown } from "../toolkit-docs-generator/scripts/pagefind-toolkit-content";
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-
-// Directory containing pre-generated clean markdown files
-const CLEAN_MARKDOWN_DIR = path.join(__dirname, "..", "public", "_markdown");
-
-/**
- * Converts clean markdown to HTML for Pagefind indexing.
- * This function expects pre-cleaned markdown (no MDX syntax).
- */
-async function markdownToHtml(markdownContent: string): Promise {
- try {
- const result = await remark()
- .use(remarkRehype)
- .use(rehypeStringify)
- .process(markdownContent);
-
- return String(result);
- } catch (error) {
- console.warn(
- `Warning: Failed to convert markdown to HTML, using plain text: ${error}`
- );
- return markdownContent;
- }
-}
-
-/**
- * Checks if clean markdown files exist and returns the appropriate source directory
- */
-async function getMarkdownSource(language: string): Promise<{
- dir: string;
- pattern: string;
- isClean: boolean;
-}> {
- const cleanDir = path.join(CLEAN_MARKDOWN_DIR, language);
-
- try {
- await fs.access(cleanDir);
- const files = await fs.readdir(cleanDir);
- if (files.length > 0) {
- return { dir: cleanDir, pattern: "**/*.md", isClean: true };
- }
- } catch {
- // Clean markdown directory doesn't exist
- }
-
- // Fallback to raw MDX (with warning)
- console.warn(
- `⚠️ Clean markdown not found for ${language}, falling back to raw MDX`
- );
- console.warn(
- ` Run "pnpm run generate:markdown" first to generate clean files`
- );
- return {
- dir: path.join(__dirname, "..", "app", language),
- pattern: "**/*.mdx",
- isClean: false,
- };
-}
-
-const { index } = await createIndex();
-if (!index) {
- throw new Error("Failed to create index");
-}
-
-console.log("\r\n🔍 BUILDING SEARCH INDEX\r\n");
-
-// valid languages are those in the app directory that do not start with an underscore and are not "api"
-const appDir = path.join(__dirname, "..", "app");
-const entries = await fs.readdir(appDir);
-const languages = await Promise.all(
- entries.map(async (dir: string) => {
- if (dir.startsWith("_") || dir === "api") {
- return null;
- }
- const entryPath = path.join(appDir, dir);
- const stats = await fs.stat(entryPath);
- return stats.isDirectory() ? dir : null;
- })
-).then((results) => results.filter((dir): dir is string => dir !== null));
-
-let page_count = 0;
-
-console.log("Building search index for languages: ", languages.join(", "));
-
-for (const language of languages) {
- const source = await getMarkdownSource(language);
-
- console.log(
- `Adding directory: ${source.dir} (${source.isClean ? "clean markdown" : "raw MDX"})`
- );
-
- for (const entry of glob.sync(source.pattern, { cwd: source.dir })) {
- // Skip dynamic templates (we index concrete toolkit pages separately).
- if (
- !source.isClean &&
- entry.includes("resources/integrations") &&
- entry.includes("[toolkitId]/page.mdx")
- ) {
- continue;
- }
-
- const filePath = path.join(source.dir, entry);
-
- // Build URL from file path
- // Clean markdown: "home/quickstart.md" -> "/en/home/quickstart"
- // Raw MDX: "home/quickstart/page.mdx" -> "/en/home/quickstart"
- let urlPath: string;
- if (source.isClean) {
- urlPath = entry.replace(/\.md$/, "");
- } else {
- urlPath = entry.split("/page.mdx")[0];
- }
- const url = `/${language}/${urlPath}`;
-
- const markdownContent = await fs.readFile(filePath, "utf-8");
- const htmlContent = await markdownToHtml(markdownContent);
-
- const { errors, file } = await index.addHTMLFile({
- url,
- content: `${htmlContent}`,
- });
-
- const fileInfo = file
- ? ` (${file.uniqueWords} words${file.meta?.title ? `, title: ${file.meta.title}` : ""})`
- : "";
- console.log(`Adding page: ${url}${fileInfo}`);
-
- if (errors.length > 0) {
- console.error(`Error adding page: ${url}`);
- console.error(errors);
- }
-
- page_count += 1;
- }
-
- // Index toolkit docs pages (rendered from JSON), so search can find tools.
- // These pages live under /en/resources/integrations//.
- if (language === "en") {
- const toolkitRoutes = await listToolkitRoutes();
- for (const route of toolkitRoutes) {
- const toolkitData = await readToolkitData(route.toolkitId);
- if (!toolkitData) {
- continue;
- }
-
- const url = `/en/resources/integrations/${route.category}/${route.toolkitId}`;
- const markdown = toolkitDataToSearchMarkdown(toolkitData);
- const htmlContent = await markdownToHtml(markdown);
-
- const { errors, file } = await index.addHTMLFile({
- url,
- content: `${htmlContent}`,
- });
-
- const fileInfo = file
- ? ` (${file.uniqueWords} words${file.meta?.title ? `, title: ${file.meta.title}` : ""})`
- : "";
- console.log(`Adding page: ${url}${fileInfo}`);
-
- if (errors.length > 0) {
- console.error(`Error adding page: ${url}`);
- console.error(errors);
- }
-
- page_count += 1;
- }
- }
-}
-
-console.log(`Added ${page_count} pages`);
-
-await index.writeFiles({
- outputPath: path.join(__dirname, "..", "public", "_pagefind"),
-});