Skip to content

Built-in Indexing

The plugin can index your documentation into Typesense at the end of astro build, so you don’t need to run the typesense-docsearch-scraper.

The built-in indexer reads the HTML generated by Starlight, extracts the page titles, headings, and text using the same record format as the scraper, and uploads them to Typesense. Compared to the scraper, it:

  • Indexes exactly the pages Starlight built: no crawling, no Docker, and no start_urls to keep up to date.
  • Creates one collection per language with the matching Typesense locale, so each language is tokenized correctly and search results always match the language of the current page.
  • Uses the sidebar group of each page as the top-level category of its results.
  • Skips the 404 page and pages excluded from search with pagefind: false in their frontmatter.
  • Replaces the collection without downtime: records are indexed into a new collection, then the collection alias is switched to it, keeping your synonyms and curations.
  1. Create an API key allowed to manage collections, aliases, and documents, and expose it to your build as an environment variable, e.g. TYPESENSE_ADMIN_API_KEY.

  2. Add the indexing option to the plugin configuration.

    astro.config.mjs
    import starlight from '@astrojs/starlight';
    import { defineConfig } from 'astro/config';
    import starlightDocSearchTypesense from 'starlight-docsearch-typesense';
    import { loadEnv } from 'vite';
    const { TYPESENSE_ADMIN_API_KEY } = loadEnv(
    process.env.NODE_ENV ?? 'development',
    process.cwd(),
    '',
    );
    export default defineConfig({
    integrations: [
    starlight({
    title: 'My Docs',
    plugins: [
    starlightDocSearchTypesense({
    typesenseCollectionName: 'docs',
    typesenseServerConfig: {
    nodes: [{ url: 'https://xxx.typesense.net' }],
    apiKey: 'SEARCH_ONLY_API_KEY',
    },
    indexing: {
    // Skip indexing in builds without an admin key, e.g. local builds.
    enabled: Boolean(TYPESENSE_ADMIN_API_KEY),
    typesenseServerConfig: {
    nodes: [{ url: 'https://xxx.typesense.net' }],
    apiKey: TYPESENSE_ADMIN_API_KEY ?? '',
    },
    },
    }),
    ],
    }),
    ],
    });
  3. Build your site. The plugin logs the number of records indexed for each language:

    Terminal window
    npm run build
    [starlight-docsearch-typesense] Indexing docs_en (4 pages)
    [starlight-docsearch-typesense] ✔ /configuration/ ......................... 75 records
    [starlight-docsearch-typesense] ✔ /getting-started/ ....................... 9 records
    [starlight-docsearch-typesense] ✔ /guides/built-in-indexing/ .............. 49 records
    [starlight-docsearch-typesense] ✔ /guides/typesense-docsearch-scraper/ .... 23 records
    [starlight-docsearch-typesense] ✔ Indexed 156 records into docs_en (collection docs_en_1700000000000)
    [starlight-docsearch-typesense] Indexing docs_vi (4 pages)
    [starlight-docsearch-typesense] ✔ /vi/configuration/ ......................... 75 records
    [starlight-docsearch-typesense] ✔ /vi/getting-started/ ....................... 9 records
    [starlight-docsearch-typesense] ✔ /vi/guides/built-in-indexing/ .............. 49 records
    [starlight-docsearch-typesense] ✔ /vi/guides/typesense-docsearch-scraper/ .... 23 records
    [starlight-docsearch-typesense] ✔ Indexed 156 records into docs_vi (collection docs_vi_1700000000000)

If indexing fails, the build fails and the current collections are left untouched, so search keeps working.

For each language of your site, the plugin creates a collection alias named <collectionName>_<lang>, e.g. docs_en and docs_fr, where <lang> is the lowercase lang of the locale. Each alias points to a collection named <collectionName>_<lang>_<timestamp>, replaced on every build.

The search bar automatically searches the collection matching the language of the current page. Pages that are not translated yet use Starlight’s fallback content and are indexed in the collection of the language they are displayed in.

OptionTypeDescription
typesenseServerConfig RequiredobjectConnection to Typesense, with an API key allowed to manage collections and aliases. Same options as the search server config.
enabled default: truebooleanWhether to index the site at the end of astro build.
collectionNamestringBase name of the indexed collections. Defaults to typesenseCollectionName. Required when using clientOptionsModule.
indexCodeBlocks default: falsebooleanWhether to index code blocks. They are ranked below text.
customCollectionSettingsobjectOverrides of the collection schema (fields, token_separators, symbols_to_index, enable_nested_fields), for all languages or keyed by language, e.g. { en: {...}, 'zh-cn': {...} }.
transformRecord(record, page) => record | nullMutates or enriches a record before it is indexed. Return null to skip it.

Use transformRecord to add custom fields or skip records. The second argument describes the page the record comes from (pathname, url, and lang). Add your custom fields to the collection schema with customCollectionSettings:

import starlightDocSearchTypesense, {
getDefaultCollectionFields,
} from 'starlight-docsearch-typesense';
starlightDocSearchTypesense({
// ...
indexing: {
typesenseServerConfig: {
/* ... */
},
transformRecord(record, page) {
// Skip the changelog.
if (page.pathname.startsWith('changelog/')) return null;
return { ...record, section: page.pathname.split('/')[0] };
},
customCollectionSettings: {
fields: (params) => [
...getDefaultCollectionFields(params),
{ name: 'section', type: 'string', facet: true, optional: true },
],
},
},
});

Synonyms and curations are kept when the collection is replaced:

  • Typesense v30 and later: the synonym and curation sets linked to the current collection are linked to the new one.
  • Before Typesense v30: the collection synonyms and overrides are copied to the new collection.

English text is indexed with Typesense’s default tokenizer, so synonyms without a locale apply to it. For other languages, set the locale of your synonyms to the language of the collection, e.g. fr.

Indexing runs wherever your site is built. Set TYPESENSE_ADMIN_API_KEY as a secret in the environment that builds your production site (e.g. your hosting provider or GitHub Actions), so the index is updated on every deployment.