mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Mixedbread integration (#2089)
* feat: add mixedbread integration * chore(release): add changeset * docs: add mixedbread integration ui docs * feat: update tag filtering and extract title from chunked text * feat: improve extractHeadingTitle * fix: fix slug generation * feat: add a minor adjustment * feat: add adjustments * chore: make mixedbread sdk optional * feat: add metadata filtering * inline deps * Update sour-teeth-deny.md --------- Co-authored-by: Fuma Nama <[email protected]> Co-authored-by: Fuma Nama <[email protected]>
This commit is contained in:
committed by
Fuma Nama
co-authored by
Fuma Nama
Fuma Nama
parent
38c099ae46
commit
1b0e9d5cda
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-core': patch
|
||||
---
|
||||
|
||||
Add mixedbread integration
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
title: Mixedbread
|
||||
description: Integrate Mixedbread Search with Fumadocs
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
The Mixedbread Integration uses vector search to provide semantic search capabilities for your documentation. It indexes your documentation content into a vector store, enabling users to search using natural language queries and find relevant content based on meaning rather than just keyword matching.
|
||||
|
||||
## Setup
|
||||
|
||||
### Get your API Key
|
||||
|
||||
1. Sign up at [Mixedbread](https://platform.mixedbread.com)
|
||||
2. Navigate to [API Keys](https://platform.mixedbread.com/platform?next=api-keys)
|
||||
3. Create a new API key and store it in your environment variables
|
||||
|
||||
### Create a Vector Store
|
||||
|
||||
To sync your documentation, you'll need to create a vector store:
|
||||
|
||||
1. Go to the [Vector Stores](https://platform.mixedbread.com/platform?next=vector-stores) in your Mixedbread dashboard
|
||||
2. Create a new vector store for your documentation
|
||||
3. Copy the vector store ID
|
||||
|
||||
### Sync Documentation
|
||||
|
||||
Use the [Mixedbread CLI](https://www.mixedbread.com/cli) to sync your documentation:
|
||||
|
||||
Install the CLI:
|
||||
|
||||
```package-install
|
||||
@mixedbread/cli -D
|
||||
```
|
||||
|
||||
Configure authentication and sync your documentation:
|
||||
|
||||
```bash
|
||||
# Configure authentication
|
||||
mxbai config keys add YOUR_API_KEY
|
||||
|
||||
# Sync your documentation
|
||||
mxbai vs sync YOUR_VECTOR_STORE_ID "./content/docs"
|
||||
```
|
||||
|
||||
The CLI will automatically detect changes in your documentation and update the vector store accordingly.
|
||||
|
||||
### Workflow
|
||||
|
||||
You can automatically sync your documentation by adding a sync script to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"build": "next build && npm run sync-content",
|
||||
"sync-content": "mxbai vs sync YOUR_VECTOR_STORE_ID './content/docs' --ci"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### Tag Filter
|
||||
|
||||
To filter search results by tags, add a tag field to your document metadata:
|
||||
|
||||
```typescript
|
||||
---
|
||||
title: Mixedbread
|
||||
description: Integrate Mixedbread Search with Fumadocs
|
||||
url: /docs/headless/search/mixedbread
|
||||
// [!code ++]
|
||||
tag: docs
|
||||
---
|
||||
...
|
||||
```
|
||||
|
||||
And update your search client:
|
||||
|
||||
- **Fumadocs UI**: Enable [Tag Filter](/docs/ui/search/orama#tag-filter) on Search UI.
|
||||
- **Search Client**: You can add the tag filter like:
|
||||
|
||||
```ts
|
||||
import { useDocsSearch } from 'fumadocs-core/search/client';
|
||||
|
||||
const { search, setSearch, query } = useDocsSearch({
|
||||
tag: '<your tag value>',
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
This allows you to scope searches to specific sections of your documentation.
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Mixedbread
|
||||
description: Using Mixedbread with Fumadocs UI.
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
For the setup guide, see [Integrate Mixedbread Search](/docs/headless/search/mixedbread).
|
||||
|
||||
## Setup
|
||||
|
||||
Create a search dialog, replace `apiKey` and `vectorStoreId` with your desired values.
|
||||
|
||||
<include meta='title="components/search.tsx"'>./mixedbread.tsx</include>
|
||||
|
||||
<include>.shared.mdx</include>
|
||||
|
||||
### Tag Filter
|
||||
|
||||
Optionally, you can add UI for filtering results by tags. Configure [Tag Filter](/docs/headless/search/mixedbread#tag-filter) on search server and add the following:
|
||||
|
||||
<include>.tag-filter.mdx</include>
|
||||
@@ -0,0 +1,60 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
SearchDialog,
|
||||
SearchDialogClose,
|
||||
SearchDialogContent,
|
||||
SearchDialogFooter,
|
||||
SearchDialogHeader,
|
||||
SearchDialogIcon,
|
||||
SearchDialogInput,
|
||||
SearchDialogList,
|
||||
SearchDialogOverlay,
|
||||
type SharedProps,
|
||||
} from 'fumadocs-ui/components/dialog/search';
|
||||
import { useDocsSearch } from 'fumadocs-core/search/client';
|
||||
import { useI18n } from 'fumadocs-ui/contexts/i18n';
|
||||
import Mixedbread from '@mixedbread/sdk';
|
||||
|
||||
const client = new Mixedbread({
|
||||
apiKey: 'mxb_xxxx',
|
||||
baseURL: 'https://api.example.com', // Optional, defaults to https://api.mixedbread.com
|
||||
});
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
const { locale } = useI18n(); // (optional) for i18n
|
||||
const { search, setSearch, query } = useDocsSearch({
|
||||
type: 'mixedbread',
|
||||
client,
|
||||
vectorStoreId: 'vectorStoreId',
|
||||
locale,
|
||||
});
|
||||
|
||||
return (
|
||||
<SearchDialog
|
||||
search={search}
|
||||
onSearchChange={setSearch}
|
||||
isLoading={query.isLoading}
|
||||
{...props}
|
||||
>
|
||||
<SearchDialogOverlay />
|
||||
<SearchDialogContent>
|
||||
<SearchDialogHeader>
|
||||
<SearchDialogIcon />
|
||||
<SearchDialogInput />
|
||||
<SearchDialogClose />
|
||||
</SearchDialogHeader>
|
||||
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
|
||||
<SearchDialogFooter>
|
||||
<a
|
||||
href="https://mixedbread.com"
|
||||
rel="noreferrer noopener"
|
||||
className="ms-auto text-xs text-fd-muted-foreground"
|
||||
>
|
||||
Search powered by Mixedbread
|
||||
</a>
|
||||
</SearchDialogFooter>
|
||||
</SearchDialogContent>
|
||||
</SearchDialog>
|
||||
);
|
||||
}
|
||||
+10
-9
@@ -15,6 +15,7 @@
|
||||
"@ai-sdk/openai": "^1.3.23",
|
||||
"@ai-sdk/react": "^1.2.12",
|
||||
"@fumadocs/mdx-remote": "workspace:*",
|
||||
"@mixedbread/sdk": "^0.19.0",
|
||||
"@orama/orama": "^3.1.11",
|
||||
"@oramacloud/client": "^2.1.4",
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
@@ -36,10 +37,10 @@
|
||||
"katex": "^0.16.22",
|
||||
"lucide-react": "^0.525.0",
|
||||
"mermaid": "^11.9.0",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"next-themes": "^0.4.6",
|
||||
"octokit": "^5.0.3",
|
||||
"oxc-transform": "^0.77.3",
|
||||
"oxc-transform": "^0.78.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"rehype-katex": "^7.0.1",
|
||||
@@ -51,22 +52,22 @@
|
||||
"scroll-into-view-if-needed": "^3.1.0",
|
||||
"shiki": "^3.8.1",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"twoslash": "^0.3.2",
|
||||
"twoslash": "^0.3.3",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"zod": "^4.0.5"
|
||||
"zod": "^4.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fumadocs/cli": "workspace:*",
|
||||
"@next/bundle-analyzer": "15.4.2",
|
||||
"@next/env": "15.4.2",
|
||||
"@next/eslint-plugin-next": "15.4.2",
|
||||
"@next/bundle-analyzer": "15.4.3",
|
||||
"@next/env": "15.4.3",
|
||||
"@next/eslint-plugin-next": "15.4.3",
|
||||
"@tailwindcss/postcss": "^4.1.11",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"algoliasearch": "5.34.0",
|
||||
"algoliasearch": "5.34.1",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"gray-matter": "^4.0.3",
|
||||
"next-validate-link": "^1.5.2",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"@fumadocs/content-collections": "workspace:*",
|
||||
"fumadocs-core": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"next": "^15.4.2",
|
||||
"next": "^15.4.3",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"fumadocs-core": "workspace:*",
|
||||
"fumadocs-mdx": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"fumadocs-core": "workspace:*",
|
||||
"fumadocs-mdx": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"fumadocs-mdx": "workspace:*",
|
||||
"fumadocs-openapi": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"shiki": "^3.8.1"
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
"fumadocs-mdx": "workspace:*",
|
||||
"fumadocs-python": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.11",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"postcss": "^8.5.6",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"devDependencies": {
|
||||
"@react-router/dev": "^7.7.0",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@types/node": "^24.0.15",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/react": "^19.1.2",
|
||||
"@types/react-dom": "^19.1.2",
|
||||
"tailwindcss": "^4.1.11",
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"devDependencies": {
|
||||
"@react-router/dev": "^7.7.0",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@types/node": "^24.0.15",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"react-router-devtools": "^5.0.6",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"@fumadocs/mdx-remote": "workspace:*",
|
||||
"fumadocs-core": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"tinyglobby": "^0.2.14"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@types/node": "^24.0.15",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/react": "^19.0.8",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
"@vitejs/plugin-react": "^4.7.0",
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
"tsup": "8.5.0",
|
||||
"turbo": "2.5.5",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.37.0",
|
||||
"typescript-eslint": "^8.38.0",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"packageManager": "[email protected]",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"ts-morph": "^26.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"tsconfig": "workspace:*",
|
||||
"tsx": "^4.20.3"
|
||||
|
||||
@@ -37,12 +37,12 @@
|
||||
"devDependencies": {
|
||||
"@content-collections/core": "^0.10.0",
|
||||
"@content-collections/mdx": "^0.2.2",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"fumadocs-core": "workspace:*",
|
||||
"tsconfig": "workspace:*",
|
||||
"unified": "^11.0.5",
|
||||
"zod": "^4.0.5"
|
||||
"zod": "^4.0.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@content-collections/core": "0.x.x",
|
||||
|
||||
@@ -112,28 +112,31 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mdx-js/mdx": "^3.1.0",
|
||||
"@mixedbread/sdk": "^0.19.0",
|
||||
"@oramacloud/client": "^2.1.4",
|
||||
"@tanstack/react-router": "^1.129.0",
|
||||
"@types/estree-jsx": "^1.0.5",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/mdast": "^4.0.3",
|
||||
"@types/negotiator": "^0.6.4",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"algoliasearch": "5.34.0",
|
||||
"algoliasearch": "5.34.1",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"mdast-util-mdx-jsx": "^3.2.0",
|
||||
"mdast-util-mdxjs-esm": "^2.0.1",
|
||||
"next": "^15.4.2",
|
||||
"next": "^15.4.3",
|
||||
"react-router": "^7.7.0",
|
||||
"remark-mdx": "^3.1.0",
|
||||
"remove-markdown": "^0.6.2",
|
||||
"tsconfig": "workspace:*",
|
||||
"typescript": "^5.8.3",
|
||||
"unified": "^11.0.5",
|
||||
"vfile": "^6.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mixedbread/sdk": "^0.19.0",
|
||||
"@oramacloud/client": "1.x.x || 2.x.x",
|
||||
"@types/react": "*",
|
||||
"algoliasearch": "5.x.x",
|
||||
@@ -142,6 +145,9 @@
|
||||
"react-dom": "18.x.x || 19.x.x"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@mixedbread/sdk": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useOnChange } from '@/utils/use-on-change';
|
||||
import { type StaticOptions } from '@/search/client/static';
|
||||
import { type AlgoliaOptions } from '@/search/client/algolia';
|
||||
import { type OramaCloudOptions } from '@/search/client/orama-cloud';
|
||||
import { type MixedbreadOptions } from '@/search/client/mixedbread';
|
||||
|
||||
interface UseDocsSearch {
|
||||
search: string;
|
||||
@@ -29,7 +30,10 @@ export type Client =
|
||||
} & AlgoliaOptions)
|
||||
| ({
|
||||
type: 'orama-cloud';
|
||||
} & OramaCloudOptions);
|
||||
} & OramaCloudOptions)
|
||||
| ({
|
||||
type: 'mixedbread';
|
||||
} & MixedbreadOptions);
|
||||
|
||||
function isDifferentDeep(a: unknown, b: unknown): boolean {
|
||||
if (Array.isArray(a) && Array.isArray(b)) {
|
||||
@@ -146,6 +150,11 @@ export function useDocsSearch(
|
||||
return search(debouncedValue, client);
|
||||
}
|
||||
|
||||
if (client.type === 'mixedbread') {
|
||||
const { search } = await import('./client/mixedbread');
|
||||
return search(debouncedValue, client);
|
||||
}
|
||||
|
||||
throw new Error('unknown search client');
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import { SortedResult } from '@/server';
|
||||
import Mixedbread from '@mixedbread/sdk';
|
||||
import { VectorStoreSearchResponse } from '@mixedbread/sdk/resources/vector-stores';
|
||||
import removeMd from 'remove-markdown';
|
||||
import Slugger from 'github-slugger';
|
||||
|
||||
export interface MixedbreadOptions {
|
||||
/**
|
||||
* The ID of the vector store to search in
|
||||
*/
|
||||
vectorStoreId: string;
|
||||
|
||||
/**
|
||||
* The Mixedbread SDK client instance
|
||||
*/
|
||||
client: Mixedbread;
|
||||
|
||||
/**
|
||||
* Filter results with specific tag.
|
||||
*/
|
||||
tag?: string;
|
||||
|
||||
/**
|
||||
* Filter by locale (unsupported at the moment)
|
||||
*/
|
||||
locale?: string;
|
||||
}
|
||||
|
||||
export interface SearchMetadata {
|
||||
title?: string;
|
||||
description?: string;
|
||||
url?: string;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
type VectorStoreSearchResult = VectorStoreSearchResponse['data'][number] & {
|
||||
generated_metadata: SearchMetadata;
|
||||
};
|
||||
|
||||
const slugger = new Slugger();
|
||||
|
||||
function extractHeadingTitle(text: string): string {
|
||||
const trimmedText = text.trim();
|
||||
|
||||
if (!trimmedText.startsWith('#')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const lines = trimmedText.split('\n');
|
||||
const firstLine = lines[0]?.trim();
|
||||
|
||||
if (firstLine) {
|
||||
// Use remove-markdown to convert to plain text and remove colons
|
||||
const plainText = removeMd(firstLine, {
|
||||
useImgAltText: false,
|
||||
});
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export async function search(
|
||||
query: string,
|
||||
options: MixedbreadOptions,
|
||||
): Promise<SortedResult[]> {
|
||||
const { client, vectorStoreId, tag } = options;
|
||||
|
||||
if (!query.trim()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const res = await client.vectorStores.search({
|
||||
query,
|
||||
vector_store_identifiers: [vectorStoreId],
|
||||
top_k: 10,
|
||||
filters: {
|
||||
key: 'generated_metadata.tag',
|
||||
operator: 'eq',
|
||||
value: tag,
|
||||
},
|
||||
search_options: {
|
||||
return_metadata: true,
|
||||
},
|
||||
});
|
||||
|
||||
const results = (res.data as VectorStoreSearchResult[]).flatMap((item) => {
|
||||
const metadata = item.generated_metadata;
|
||||
|
||||
const url = metadata.url || '#';
|
||||
const title = metadata.title || 'Untitled';
|
||||
|
||||
const chunkResults: SortedResult[] = [
|
||||
{
|
||||
id: `${item.file_id}-${item.chunk_index}-page`,
|
||||
type: 'page',
|
||||
content: title,
|
||||
url,
|
||||
},
|
||||
];
|
||||
|
||||
const headingTitle =
|
||||
item.type === 'text' ? extractHeadingTitle(item.text) : '';
|
||||
|
||||
if (headingTitle) {
|
||||
slugger.reset();
|
||||
|
||||
chunkResults.push({
|
||||
id: `${item.file_id}-${item.chunk_index}-heading`,
|
||||
type: 'heading',
|
||||
content: headingTitle,
|
||||
url: `${url}#${slugger.slug(headingTitle)}`,
|
||||
});
|
||||
}
|
||||
|
||||
return chunkResults;
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -16,13 +16,13 @@
|
||||
"@tanstack/react-router": "^1.129.0",
|
||||
"@tanstack/react-start": "^1.129.0",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"@vitejs/plugin-react": "^4.7.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"isbot": "^5.1.28",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"postcss": "^8.5.6",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cross-spawn": "^6.0.6",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"tinyglobby": "^0.2.14",
|
||||
"tsconfig": "workspace:*"
|
||||
|
||||
@@ -40,16 +40,16 @@
|
||||
"estree-util-to-js": "^2.0.0",
|
||||
"estree-util-value-to-estree": "^3.4.0",
|
||||
"npm-to-yarn": "^3.0.1",
|
||||
"oxc-transform": "^0.77.3",
|
||||
"oxc-transform": "^0.78.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"zod": "^4.0.5"
|
||||
"zod": "^4.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mdx-js/mdx": "^3.1.0",
|
||||
"@types/estree": "^1.0.8",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/mdast": "^4.0.3",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"mdast-util-mdx-jsx": "^3.2.0",
|
||||
"remark": "^15.0.0",
|
||||
|
||||
@@ -38,11 +38,11 @@
|
||||
"dependencies": {
|
||||
"@mdx-js/mdx": "^3.1.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"zod": "^4.0.5"
|
||||
"zod": "^4.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"fumadocs-core": "workspace:*",
|
||||
|
||||
@@ -69,19 +69,19 @@
|
||||
"tinyexec": "^1.0.1",
|
||||
"tinyglobby": "^0.2.14",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"zod": "^4.0.5"
|
||||
"zod": "^4.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fumadocs/mdx-remote": "workspace:*",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/mdast": "^4.0.3",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^24.0.15",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"fumadocs-core": "workspace:*",
|
||||
"mdast-util-mdx-jsx": "^3.2.0",
|
||||
"next": "^15.4.2",
|
||||
"next": "^15.4.3",
|
||||
"react": "^19.1.0",
|
||||
"tsconfig": "workspace:*",
|
||||
"unified": "^11.0.5",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"js-yaml": "^4.1.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"openapi-sampler": "^1.6.1",
|
||||
"react-hook-form": "^7.60.0",
|
||||
"react-hook-form": "^7.61.0",
|
||||
"remark": "^15.0.1",
|
||||
"remark-rehype": "^11.1.2",
|
||||
"shiki": "^3.8.1",
|
||||
@@ -77,12 +77,12 @@
|
||||
"devDependencies": {
|
||||
"@scalar/api-client-react": "^1.3.24",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/openapi-sampler": "^1.0.3",
|
||||
"@types/react": "^19.1.8",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"json-schema-typed": "^8.0.1",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"openapi-types": "^12.1.3",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"tsc-alias": "^1.8.16",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^24.0.15",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"fumadocs-core": "workspace:*",
|
||||
|
||||
@@ -48,12 +48,12 @@
|
||||
"mdast-util-to-hast": "^13.2.0",
|
||||
"shiki": "^3.8.1",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"twoslash": "^0.3.2"
|
||||
"twoslash": "^0.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/mdast": "^4.0.3",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
"@types/estree": "^1.0.8",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/mdast": "^4.0.3",
|
||||
"@types/node": "24.0.15",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/react": "19.1.8",
|
||||
"@types/react-dom": "19.1.6",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
|
||||
@@ -103,14 +103,14 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fumadocs/cli": "workspace:*",
|
||||
"@next/eslint-plugin-next": "^15.4.2",
|
||||
"@next/eslint-plugin-next": "^15.4.3",
|
||||
"@tailwindcss/cli": "^4.1.11",
|
||||
"@types/lodash.merge": "^4.6.9",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"fumadocs-core": "workspace:*",
|
||||
"next": "15.4.2",
|
||||
"next": "15.4.3",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"tsc-alias": "^1.8.16",
|
||||
"tsconfig": "workspace:*"
|
||||
|
||||
Generated
+847
-912
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user