Skip to main content

🧠 psyche

psyche is a drop-in solution for searching documentation, inspired by Algolia’s DocSearch.

  • It looks and feels awesome to use.
  • Searching is fast, accurate and typo-tolerate.
  • It can be included in any static or server-generated documentation website.
  • It doubles as a keyboard-navigable sitemap.
  • It makes registering site-wide, platform-dependent hotkeys simple.
  • It’s mobile-friendly.
  • It supports both light and dark modes.

Check out the notion-enhancer documentation for a live demo.

Warning: psyche is built specifically for searching documentation. It is not built for implementation into other interfaces (e.g. eCommerce) or use with custom data schemes.

Getting started

Generating an index

The psyche client requires a pre-generated index of results to search. This should be an array of Result records (see types.d.ts). Indexes are provided to the client programmatically, but should take the form of an unformatted/minified .json file.

Indexers are plugins/middleware that crawl a site and generate an index, either during a build process or on-the-fly if the site is dynamically served.

Indexers for some documentation generators are provided below. If your generator of choice is not yet supported, either open a feature request or write your own and open a pull request.

🔥 Lume

Add the following to your _config.ts file:

import psyche from 'https://deno.land/x/psyche/indexers/lume.ts';

site.use(psyche());

The indexer can be configured by providing a LumeConfig object as the first argument of the psyche() call (see types.d.ts).

By default:

  • The index will be output to /search.json.
  • Pages without data.section or where data.draft = true will be ignored.
  • Pages will be grouped by data.section_order & sorted by data.order.
  • Page titles are accessed from data.title.
  • Page sections are accessed from data.section.
  • Headings, code blocks, paragraphs and lists within an <article></article> element in a page are indexed according to semantic HTML. Other elements (e.g. <blockquote></blockquote>) are treated as paragraphs. This works best with markdown output.

Read the page data and/or shared data pages of Lume’s documentation to see how to set these properties.

Including the client

The psyche client is written in TypeScript. You can either directly import it if your site’s assets will be bundled by e.g. ESBuild, or import the pre-transpiled and minified JavaScript build.

import psyche from 'https://deno.land/x/psyche/client/mod.ts';
// or
import psyche from 'https://deno.land/x/psyche/client/psyche.min.mjs';

The psyche default export is a function that when provided with a ClientConfig object (see types.d.ts) will return a ClientInstance (see types.d.ts).

Calling .register() on a client instance will insert the component into the document and listen for hotkey presses. The component can then be opened either by calling .open() or by pressing CTRL/⌘ + K.

E.g.

const searchInstance = psyche({
  theme: { scrollbarStyle: 'square' },
  index: await fetch('/search.json').then((res) => res.json()),
});
searchInstance.register();
searchInstance.open();

Registering hotkeys

To add a hotkey to the list in the search modal, add it to the hotkeys array of psyche’s ClientConfig object (see types.d.ts).

For platform-dependent hotkeys, the named export platformModifier will be equivalent to the key on MacOS or the CTRL key on other platforms.

To handle hotkeys, provide a ClientHotkey object (see types.d.ts) to the named export registerHotkey. This is a KeyboardEvent partial with a few additional properties:

  • the platformModifier property is equivalent to metaKey on MacOS or ctrlKey on other platforms.
  • the onkeydown property will be called when the key combination is pressed down, passed the triggered KeyboardEvent as its first argument.
  • the onkeyup property will be called when the key combination is released, passed the triggered KeyboardEvent as its first argument.

E.g.

import psyche, {
  registerHotkey,
  platformModifier,
} from 'https://deno.land/x/psyche/client/psyche.min.mjs';

registerHotkey({
  key: 'l',
  platformModifier: true,
  shiftKey: true,
  onkeydown: (event) => {
    event.preventDefault();
    toggleTheme();
  },
});

const searchInstance = psyche({
  hotkeys: [{ kbd: `${platformModifier} + SHIFT + L`, label: 'to toggle theme' }],
});
searchInstance.register();

Changes to this project are recorded in the CHANGELOG.

This project is licensed under the MIT License.

To support future development of this project, please consider sponsoring the author.