Skip to content

Commit

Permalink
Docs: Update search section
Browse files Browse the repository at this point in the history
  • Loading branch information
fuma-nama committed Sep 14, 2024
1 parent 6b353c1 commit c14e332
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 156 deletions.
2 changes: 1 addition & 1 deletion apps/docs/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ function Why(): React.ReactElement {
<Accordion className="text-sm" title="Full-text Search">
<p>
Implementing search is difficult. Fumadocs offers native support for
Flexsearch and Algolia Search, it is as simple as plugging a route
Orama and Algolia Search, it is as simple as plugging a route
handler.
</p>
<Link
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/app/static.json/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextResponse } from 'next/server';
import { type DocumentRecord } from 'fumadocs-core/search-algolia/server';
import { type DocumentRecord } from 'fumadocs-core/search/algolia';
import { utils } from '@/app/source';

export const revalidate = false;
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/docs/headless/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ icon: Album

Fumadocs Core offers server-side functions and headless components, built for App Router.

- Search (built-in: Flexsearch, Algolia Search)
- Search (built-in: Orama, Algolia Search)
- Breadcrumb, Sidebar, TOC Components
- Remark/Rehype Plugins
- Additional utilities
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/docs/headless/internationalization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,4 @@ see [Page Conventions](/docs/headless/page-conventions#internationalization) to

### Search

For Flexsearch, see [Setup I18n](/docs/headless/search/flexsearch#internationalization).
For Orama, see [Setup I18n](/docs/headless/search/orama#internationalization).
2 changes: 1 addition & 1 deletion apps/docs/content/docs/headless/remote/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Next.js offers a Metadata API for SEO, you can configure it with `generateMetada
### Document Search

This can be difficult considering your content may not be necessarily Markdown/MDX.
For Markdown and MDX, the built-in [Search API](/docs/headless/search/flexsearch) is adequate for most use cases.
For Markdown and MDX, the built-in [Search API](/docs/headless/search/orama) is adequate for most use cases.
Otherwise, you will have to bring your own implementation.

We recommend 3rd party solutions like Algolia Search. They are more flexible than the built-in Search API, and is easier to integrate with remote sources.
Expand Down
100 changes: 78 additions & 22 deletions apps/docs/content/docs/headless/search/algolia.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The `sync` function will update the index settings and sync search indexes.

```js title="update-index.mjs"
import algosearch from 'algoliasearch';
import { sync } from 'fumadocs-core/search-algolia/server';
import { sync } from 'fumadocs-core/search/algolia';

const client = algosearch('id', 'key');

Expand All @@ -54,9 +54,56 @@ sync(client, {
});
```

The `indexes` variable should be provided by your content source provider. If you are using Fumadocs MDX, see [Manifest](/docs/mdx/manifest).
The `indexes` variable should be provided by your content source provider.
With Source API, you can do:

```ts title="app/static.json/route.ts"
import { NextResponse } from 'next/server';
import { type DocumentRecord } from 'fumadocs-core/search/algolia';
import { source } from '@/lib/source';

export const revalidate = false;

export function GET() {
const results: DocumentRecord[] = [];
const pages = source.getPages();

for (const page of pages) {
results.push({
_id: page.url,
structured: page.data.structuredData,
tag: page.slugs[0],
url: page.url,
title: page.data.title,
description: page.data.description,
});
}

return NextResponse.json(results);
}
```

And read it after build:

```json title="package.json"
{
"scripts": {
"build": "next build && node ./update-index.mjs"
}
}
```

```js title="update-index.mjs"
import * as fs from 'node:fs';

const content = fs.readFileSync('.next/server/app/static.json.body');

// now you can pass it to `sync`
/** @type {import('fumadocs-core/search/algolia').DocumentRecord[]} **/
const records = JSON.parse(content.toString());
```

Notably, it requires a `structured` property, this can be obtained from [Remark Structure](/docs/headless/mdx/structure), or sometimes supplied by the content source you are using.
### Workflow

You may make it a script and manually sync with `node ./update-index.mjs`, or
integrate it with your CI/CD pipeline.
Expand All @@ -72,17 +119,19 @@ integrate it with your CI/CD pipeline.

### Search Client

To search documents on the client side, use the [Fumadocs UI Search Dialog](/docs/ui/search#algolia), or your own implementation.
To search documents on the client side, use [Fumadocs UI Search Dialog](/docs/ui/search#algolia), or make your own implementation.

In addition, the `useAlgoliaSearch` hook can handle state management with SWR.
In addition, the headless search client of Fumadocs can handle state management for React.

```ts
import algosearch from 'algoliasearch';
import { useAlgoliaSearch } from 'fumadocs-core/search-algolia/client';
import { useDocsSearch } from 'fumadocs-core/search/client';

const index = algosearch('id', 'key').initIndex('document');

const { search, setSearch, query } = useAlgoliaSearch(index, {
const { search, setSearch, query } = useDocsSearch({
type: 'algolia',
index,
distinct: 5,
hitsPerPage: 10,
});
Expand All @@ -96,7 +145,7 @@ To configure tag filtering, add a `tag` value to indexes.

```js
import algosearch from 'algoliasearch';
import { sync } from 'fumadocs-core/search-algolia/server';
import { sync } from 'fumadocs-core/search/algolia';

const client = algosearch('id', 'key');

Expand All @@ -110,16 +159,23 @@ sync(client, {

For Fumadocs UI, enable [Tag Filter](/docs/ui/search#tag-filter-1) on Search Dialog.

The `tag` field is an attribute for faceting, use the filter `tag:value` on search clients to filter indexes by tag.
The `tag` field is an attribute for faceting. To filter indexes by tag, use the filter `tag:value` on Algolia search clients.
On Fumadocs search client, you can add the tag filter like:

```ts
import { useAlgoliaSearch } from 'fumadocs-core/search-algolia/client';
import algosearch from 'algoliasearch';
import { useDocsSearch } from 'fumadocs-core/search/client';

useAlgoliaSearch(index, {
distinct: 5,
hitsPerPage: 10,
filters: 'tag:value',
});
const index = algosearch('id', 'key').initIndex('document');

const { search, setSearch, query } = useDocsSearch(
{
type: 'algolia',
index,
},
undefined,
'<your tag value>',
);
```

### Customise Attributes & Settings
Expand All @@ -128,16 +184,16 @@ While the default attributes might not suit your case, you can pass `extra_data`
to index options for adding extra fields to each record.

```js
import { sync } from 'fumadocs-core/search-algolia/server'
import { sync } from 'fumadocs-core/search/algolia';

sync(client, {
documents: indexes.map(docs => ({
...,
documents: indexes.map((docs) => ({
...docs,
extra_data: {
tag: docs.tag
}
}))
})
value: 'hello world',
},
})),
});
```

To customize the default index settings, set index settings, and update
Expand Down
Loading

0 comments on commit c14e332

Please sign in to comment.