IntegrationsNextra

Add AI Search & Chat Button to your Nextra docs

What is Nextra

Nextra is a framework for creating content-focused websites using Next.js and markdown.

Get an API key

  1. Go to the Inkeep Dashboard
  2. Select your project under Projects
  3. Go to the Integrations tab
  4. Click on Create integration
  5. Select Web
  6. Provide a Name and URL (optional) for the integration
  7. Click on Create
  8. Click the Example < /> button to get your API key and view suggested settings

Copy and add the apiKey, integrationId and organizationId to your environment variables:

.env
NEXT_PUBLIC_INKEEP_API_KEY="INKEEP_API_KEY"
NEXT_PUBLIC_INKEEP_INTEGRATION_ID="INKEEP_INTEGRATION_ID"
NEXT_PUBLIC_INKEEP_ORGANIZATION_ID="INKEEP_ORGANIZATION_ID"

Install the component library

npm install @inkeep/uikit
bun add @inkeep/uikit
pnpm add @inkeep/uikit
yarn add @inkeep/uikit

Customize your settings

Create a useInkeepSettings.ts file that will contain a hook that will return the configuration for Inkeep component(s).

import { useTheme } from "nextra-theme-docs";
 
const useInkeepSettings = () => {
  const { resolvedTheme } = useTheme();
 
  const baseSettings = {
    apiKey: process.env.NEXT_PUBLIC_INKEEP_API_KEY!,
    integrationId: process.env.NEXT_PUBLIC_INKEEP_INTEGRATION_ID!,
    organizationId: process.env.NEXT_PUBLIC_INKEEP_ORGANIZATION_ID!,
    primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
    organizationDisplayName: "Inkeep",
    // ...optional settings
    colorMode: {
      forcedColorMode: resolvedTheme, // to sync dark mode with the widget
    },
  };
 
  const modalSettings = {
    // optional settings
  };
 
  const searchSettings = {
    // optional settings
  };
 
  const aiChatSettings = {
    // optional settings
    botAvatarSrcUrl: "/img/logo.svg", // use your own bot avatar
    quickQuestions: [
      "Example question 1?",
      "Example question 2?",
      "Example question 3?",
    ],
  };
 
  return { baseSettings, aiChatSettings, searchSettings, modalSettings };
};
 
export default useInkeepSettings;
import type {
  InkeepAIChatSettings,
  InkeepSearchSettings,
  InkeepBaseSettings,
  InkeepModalSettings,
} from "@inkeep/uikit";
import { useTheme } from "nextra-theme-docs";
 
type InkeepSharedSettings = {
  baseSettings: InkeepBaseSettings;
  aiChatSettings: InkeepAIChatSettings;
  searchSettings: InkeepSearchSettings;
  modalSettings: InkeepModalSettings;
};
 
const useInkeepSettings = (): InkeepSharedSettings => {
  const { resolvedTheme } = useTheme();
 
  const baseSettings: InkeepBaseSettings = {
    apiKey: process.env.NEXT_PUBLIC_INKEEP_API_KEY!,
    integrationId: process.env.NEXT_PUBLIC_INKEEP_INTEGRATION_ID!,
    organizationId: process.env.NEXT_PUBLIC_INKEEP_ORGANIZATION_ID!,
    primaryBrandColor: "#26D6FF", // your brand color, widget color scheme is derived from this
    organizationDisplayName: "Inkeep",
    // ...optional settings
    colorMode: {
      forcedColorMode: resolvedTheme, // to sync dark mode with the widget
    },
  };
 
  const modalSettings: InkeepModalSettings = {
    // optional settings
  };
 
  const searchSettings: InkeepSearchSettings = {
    // optional settings
  };
 
  const aiChatSettings: InkeepAIChatSettings = {
    // optional settings
    botAvatarSrcUrl: "/img/logo.svg", // use your own bot avatar
    quickQuestions: [
      "Example question 1?",
      "Example question 2?",
      "Example question 3?",
    ],
  };
 
  return { baseSettings, aiChatSettings, searchSettings, modalSettings };
};
 
export default useInkeepSettings;

Make sure to add your Inkeep identifiers to your environment settings.

Define the components

Next, create component files InkeepChatButton.tsx and InkeepSearchBar.tsx

ChatButton

import React, { useEffect, useState } from "react";
import useInkeepSettings from "@/utils/useInkeepSettings";
 
export default function InkeepChatButton() {
  const [ChatButton, setChatButton] = useState(null);
 
  const { baseSettings, aiChatSettings, searchSettings, modalSettings } =
    useInkeepSettings();
 
  // load the library asynchronously
  useEffect(() => {
    const loadChatButton = async () => {
      try {
        const { InkeepChatButton } = await import("@inkeep/uikit");
        setChatButton(() => InkeepChatButton);
      } catch (error) {
        console.error("Failed to load ChatButton:", error);
      }
    };
 
    loadChatButton();
  }, []);
 
  const chatButtonProps = {
    baseSettings,
    aiChatSettings,
    searchSettings,
    modalSettings,
  };
 
  return ChatButton && <ChatButton {...chatButtonProps} />;
}
import React, { useEffect, useState } from "react";
import useInkeepSettings from "@/utils/useInkeepSettings";
import type { InkeepChatButtonProps } from "@inkeep/uikit";
 
export default function InkeepChatButton() {
  const [ChatButton, setChatButton] =
    useState<(e: InkeepChatButtonProps) => JSX.Element>();
 
  const { baseSettings, aiChatSettings, searchSettings, modalSettings } =
    useInkeepSettings();
 
  // load the library asynchronously
  useEffect(() => {
    const loadChatButton = async () => {
      try {
        const { InkeepChatButton } = await import("@inkeep/uikit");
        setChatButton(() => InkeepChatButton);
      } catch (error) {
        console.error("Failed to load ChatButton:", error);
      }
    };
 
    loadChatButton();
  }, []);
 
  const chatButtonProps: InkeepChatButtonProps = {
    baseSettings,
    aiChatSettings,
    searchSettings,
    modalSettings,
  };
 
  return ChatButton && <ChatButton {...chatButtonProps} />;
}
import React, { useEffect, useState } from "react";
import useInkeepSettings from "@/utils/useInkeepSettings";
 
export default function InkeepSearchBar() {
  const [SearchBar, setSearchBar] = useState(null);
 
  const { baseSettings, aiChatSettings, searchSettings, modalSettings } =
    useInkeepSettings();
 
  // load the library asynchronously
  useEffect(() => {
    const loadSearchBar = async () => {
      try {
        const { InkeepSearchBar } = await import("@inkeep/uikit");
        setSearchBar(() => InkeepSearchBar);
      } catch (error) {
        console.error("Failed to load SearchBar:", error);
      }
    };
 
    loadSearchBar();
  }, []);
 
  const searchBarProps = {
    baseSettings,
    aiChatSettings,
    searchSettings,
    modalSettings,
  };
 
  return SearchBar && <SearchBar {...searchBarProps} />;
}
import React, { useEffect, useState } from "react";
import useInkeepSettings from "@/utils/useInkeepSettings";
import type { InkeepSearchBarProps } from "@inkeep/uikit";
 
export default function InkeepSearchBar() {
  const [SearchBar, setSearchBar] =
    useState<(e: InkeepSearchBarProps) => JSX.Element>();
 
  const { baseSettings, aiChatSettings, searchSettings, modalSettings } =
    useInkeepSettings();
 
  // load the library asynchronously
  useEffect(() => {
    const loadSearchBar = async () => {
      try {
        const { InkeepSearchBar } = await import("@inkeep/uikit");
        setSearchBar(() => InkeepSearchBar);
      } catch (error) {
        console.error("Failed to load SearchBar:", error);
      }
    };
 
    loadSearchBar();
  }, []);
 
  const searchBarProps: InkeepSearchBarProps = {
    baseSettings,
    aiChatSettings,
    searchSettings,
    modalSettings,
  };
 
  return SearchBar && <SearchBar {...searchBarProps} />;
}

Modify theme config

To add widgets to the page, paste the code shown below into the theme.config.tsx file:

theme.config.tsx
//...
footer: {
  component: () => <InkeepChatButton />
},
search: {
  component: () => <InkeepSearchBar />
}

For a full list of customizations, check out the Common Settings.

On this page