npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

typesense-nextra-adapter

v0.0.2

Published

An adapter that adds lightning-fast, typo-tolerant, Typesense-powered search to your Nextra site

Downloads

171

Readme

Typesense Nextra Adapter 🔎⚡️

An adapter that brings lightning-fast, typo-tolerant search powered by Typesense to your Nextra site.

About Typesense & Nextra

Typesense is an open-source, lightning-fast search engine that delivers instant, typo-tolerant results with minimal setup. It's an open source alternative to Algolia and an easier-to-use alternative to ElasticSearch.

Nextra is a lightweight, React-based static site generator built on top of Next.js. It allows developers to create high-performance, content-driven websites with ease, making it a popular choice for documentation sites.

Together, Typesense and Nextra provide a seamless way to add powerful, blazingly-fast search to modern documentation websites.

Installation

npm install typesense-nextra-adapter

Usage

1. Start typesense server

You can either self-host the Typesense server or use Typesense Cloud service. Follow this getting started guide to set up your server and obtain the API key and server URL.

2. Configure the adapter

First, create the file scripts/indexTypesense.ts. You must provide your Typesense server details and an API key with write permissions so the plugin can create collections and index your documents during the build.

// scripts/indexTypesense.ts
import { indexNextraToTypesense } from 'typesense-nextra-adapter';

indexNextraToTypesense({
  serverConfig: {
    nodes: [{ url: 'YOUR_TYPESENSE_SERVER_URL' }],
    apiKey: 'YOUR_TYPESENSE_ADMIN_API_KEY', // Requires Write permissions
  },
  collectionName: 'nextra-docs',
});
// package.json
{
  "scripts": {
    // for Node.js < v23.6.0 use `npx tsx scripts/indexTypesense.ts`
    "postbuild": "node scripts/indexTypesense.ts"
  }
}

3. Override the search component

Next, override Nextra's default Search component via a Custom Theme.

Provide a Search-Only API Key here. For security reasons, never expose your Admin API Key in the frontend.

// apps/layout.tsx
import { Search } from 'typesense-nextra-adapter/client';

const search = (
  <Search
    docSearchProps={{
      typesenseServerConfig: {
        nodes: [{ url: 'YOUR_TYPESENSE_SERVER_URL' }],
        apiKey: 'YOUR_TYPESENSE_SEARCH_ONLY_API_KEY', // Safe for browsers
      },
    }}
    collectionName='nextra-docs'
  />
);

const RootLayout = ({ children }) => {
  return (
    <html lang='en'>
      <body>
        <Layout
          // replace Nextra's default search with our Typesense-powered search component
          search={search}
          //...otherProps
        >
          {children}
        </Layout>
      </body>
    </html>
  );
};

export default RootLayout;

4. Build and index

Run the build command to generate your site and index your content into Typesense.

npm run build

All set! You've successfully integrated typo-tolerant search into your documentation.

Adapter configuration (Backend)

The indexNextraToTypesense function accepts an options object with the following properties:

export interface NextraTypesenseOptions {
  /**
   * Typesense server connection options.
   * The API key must have write permissions to create and index collections.
   */
  serverConfig: ConfigurationOptions;

  /**
   * The base name of the Typesense collection.
   * Note: The plugin creates dedicated localized collections (e.g., `my_docs_en`).
   */
  collectionName: string;

  /**
   * Optional schema overrides. Can be a global settings object or a map keyed by language.
   */
  customCollectionSettings?: CustomCollectionSettingsConfig;

  /**
   * Whether to index code blocks into Typesense.
   * Defaults to `false` to avoid search noise and bloated index sizes.
   */
  indexCodeBlocks?: boolean;

  /**
   * Whether a failed indexing attempt should crash the build process.
   * Defaults to `true`.
   */
  failOnIndexError?: boolean;

  /** Hook to mutate or enrich the record before it gets indexed. */
  transformRecord?: (
    record: DocSearchRecord,
    route: { routePath: string; filePath: string },
  ) => DocSearchRecord;

  /** The output directory to scan for HTML files. Defaults to '.next/server/app' */
  outDir?: string;

  /** Default language if the <html lang="..."> attribute is missing. Defaults to 'en' */
  defaultLang?: string;

  /**
   * Maximum number of files to read and parse concurrently.
   * Prevents "Too many open files" OS errors.
   * @default 10
   */
  concurrencyLimit?: number;

  /**
   * Maximum number of records to accumulate before sending a batch request to Typesense.
   * Lower this if your payloads are extremely large and hitting Typesense payload limits.
   * @default 200
   */
  batchSize?: number;
}

customCollectionSettings

  • Type:
type CustomCollectionSettingsConfig =
  | CustomCollectionSettings
  | Record<string, CustomCollectionSettings>;
  • Default: undefined

Allows you to override the Typesense schema configuration. You can pass a single global configuration, or a map of configurations keyed by language (useful if you need specific token separators for languages like Chinese or Japanese).

Customizing schema and injecting custom data

For advanced use cases like adding custom tags for faceted search or boosting the search ranking of specific pages, you can extend the default schema and mutate records before they are indexed.

To do this:

  1. Use the getDefaultCollectionFields helper in customCollectionSettings to safely append new fields to the collection schema.
  2. Use the transformRecord hook to populate those fields or modify existing weights based on the route.

Here is an example showing how to add a custom category field for filtering, and how to boost the page_rank of "Getting Started" guides:

import {
  indexNextraToTypesense,
  getDefaultCollectionFields,
} from 'typesense-nextra-adapter';

indexNextraToTypesense({
  collectionName: 'my_docs',
  serverConfig: {
    /* ... */
  },

  // 1. Extend the schema to add a custom 'category' field
  customCollectionSettings: {
    en: {
      fields: (params) => [
        ...getDefaultCollectionFields(params),
        { name: 'category', type: 'string', facet: true, optional: true },
      ],
    },
  },

  // 2. Mutate the record before it gets indexed
  transformRecord(record, route) {
    // Example: Inject a custom tag for faceted search
    if (route.routePath.startsWith('/api/')) {
      record.category = 'API Reference';
    }

    // Example: Boost the search priority of important pages
    if (route.routePath.includes('getting-started')) {
      record.weight.page_rank = 100; // Default is 0
    }

    return record;
  },
});

In the frontend, you could now pass typesenseSearchParams: { filter_by: 'category:=API Reference' } to your <Search /> component to restrict results.

indexCodeBlocks

  • Type: boolean
  • Default: false

By default, the plugin only indexes headers (h1-h6), paragraphs, lists and tables. Enabling this will also extract text from inside code blocks.

failOnIndexError

  • Type: boolean
  • Default: true

By default, if the Typesense indexing step fails (e.g., network timeout), the build process will crash. Set this to false if you want your CI/CD deployments to succeed even if search indexing fails.

Search component props (Frontend)

The <Search /> component accepts the following properties:

export type SearchProps = {
  docSearchProps: TypesenseDocSearchProps;
  locales?: Locales;
  collectionName: string;
  lang?: string;
};

docSearchProps

  • Type: TypesenseDocSearchProps
  • Required: Yes (typesenseServerConfig must be provided)

Parameters passed directly to the underlying typesense-docsearch-react modal.

Provide the base collection name (e.g., 'nextra-docs') via the collectionName prop. The component will automatically append the locale to match the indexed collection (e.g., 'nextra-docs_en').

locales

  • Type:
type Locales = Record<
  string,
  { translations: DocSearchProps['translations']; placeholder: string }
>;
  • Default: {}

Allows you to customize the placeholder and modal translations based on the active language. You can see the list of translations provided by the plugin here.

Example:

import { Search } from 'typesense-nextra-adapter/client';

<Search
  collectionName='my_docs'
  docSearchProps={{
    typesenseServerConfig: {
      /* ... */
    },
  }}
  locales={{
    en: {
      placeholder: 'Search documentation',
      translations: {
        button: {
          buttonText: 'Search',
          buttonAriaLabel: 'Search',
        },
      },
    },
    ...ZH_LOCALES,
  }}
/>;

License

Licensed under the Apache 2.0 License, Copyright © Typesense.

See LICENSE for more information.