Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.useinvent.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Add your Invent AI assistant to any Gatsby site. Perfect for static websites built with React and GraphQL.

Installation

1

Install React Helmet

npm install react-helmet gatsby-plugin-react-helmet
2

Configure gatsby-config.js

Add the plugin to your gatsby-config.js:
module.exports = {
  plugins: [
    'gatsby-plugin-react-helmet',
    // ... other plugins
  ],
};
3

Create Assistant Component

// src/components/InventAssistant.tsx
import React from 'react';

interface InventAssistantProps {
  assistantId: string;
  themeAppearance?: 'auto' | 'light' | 'dark';
  themeButtonBackgroundColor?: string;
  themeButtonColor?: string;
  userId?: string;
  userName?: string;
  userHash?: string;
  userAvatar?: string;
}

const InventAssistant: React.FC<InventAssistantProps> = ({
  assistantId,
  themeAppearance = 'auto',
  themeButtonBackgroundColor,
  themeButtonColor,
  userId,
  userName,
  userHash,
  userAvatar,
}) => {
  return (
    <>
      <invent-assistant
        assistant-id={assistantId}
        theme-appearance={themeAppearance}
        {...(themeButtonBackgroundColor && {
          'theme-button-background-color': themeButtonBackgroundColor,
        })}
        {...(themeButtonColor && {
          'theme-button-color': themeButtonColor,
        })}
        {...(userId && { 'user-id': userId })}
        {...(userName && { 'user-name': userName })}
        {...(userHash && { 'user-hash': userHash })}
        {...(userAvatar && { 'user-avatar': userAvatar })}
      />
      <script
        type="text/javascript"
        src="https://www.useinvent.com/button.js"
        async
        defer
      />
    </>
  );
};

export default InventAssistant;
4

Add to Layout

// src/components/layout.tsx
import React from 'react';
import InventAssistant from './InventAssistant';

const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  return (
    <>
      <main>{children}</main>
      <InventAssistant assistantId={process.env.GATSBY_INVENT_ASSISTANT_ID!} />
    </>
  );
};

export default Layout;
5

Add Environment Variable

Create .env.development and .env.production:
GATSBY_INVENT_ASSISTANT_ID=ast_YOUR_ASSISTANT_ID

User Authentication

Security Requirement: When using any user-* attributes (user-id, user-name, user-avatar), you must also provide user-hash. Both user-id and user-hash must be provided together, or neither should be provided. The user-hash must be generated on your backend using HMAC-SHA256 with your assistant’s secret key. Never expose the secret key to the client.

Using Gatsby Functions (Serverless)

Gatsby Functions allow you to generate the hash server-side:
// src/api/user-hash.ts
import type { GatsbyFunctionRequest, GatsbyFunctionResponse } from 'gatsby';
import crypto from 'crypto';

export default function handler(
  req: GatsbyFunctionRequest,
  res: GatsbyFunctionResponse
) {
  // Get user from your auth system
  const userId = req.headers['x-user-id'];

  if (!userId) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const secretKey = process.env.INVENT_SECRET_KEY!;

  const userHash = crypto
    .createHmac('sha256', secretKey)
    .update(userId as string)
    .digest('hex');

  return res.json({
    userId,
    userHash,
  });
}

Fetching User Data

// src/components/InventAssistantWrapper.tsx
import React, { useEffect, useState } from 'react';
import InventAssistant from './InventAssistant';

const InventAssistantWrapper: React.FC = () => {
  const [userData, setUserData] = useState<{
    userId?: string;
    userName?: string;
    userHash?: string;
    userAvatar?: string;
  } | null>(null);

  useEffect(() => {
    fetch('/api/user-hash')
      .then((res) => res.json())
      .then(setUserData)
      .catch(console.error);
  }, []);

  return (
    <InventAssistant
      assistantId={process.env.GATSBY_INVENT_ASSISTANT_ID!}
      {...userData}
    />
  );
};

export default InventAssistantWrapper;

GraphQL Integration

Pass content data to provide context:
// src/templates/blog-post.tsx
import React, { useEffect } from 'react';
import { graphql } from 'gatsby';
import Layout from '../components/layout';

const BlogPost: React.FC<{ data: any }> = ({ data }) => {
  const post = data.markdownRemark;

  useEffect(() => {
    if (typeof window !== 'undefined') {
      window.inventContext = {
        pageType: 'blog-post',
        title: post.frontmatter.title,
        author: post.frontmatter.author,
        category: post.frontmatter.category,
      };
    }
  }, [post]);

  return (
    <Layout>
      <article>
        <h1>{post.frontmatter.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.html }} />
      </article>
    </Layout>
  );
};

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
        author
        category
      }
    }
  }
`;

export default BlogPost;

TypeScript Support

Add type declarations:
// src/types/invent-assistant.d.ts
declare namespace JSX {
  interface IntrinsicElements {
    'invent-assistant': {
      'assistant-id': string;
      'theme-appearance'?: 'auto' | 'light' | 'dark';
      'theme-button-background-color'?: string;
      'theme-button-color'?: string;
      'user-id'?: string;
      'user-name'?: string;
      'user-hash'?: string;
      'user-avatar'?: string;
    };
  }
}

interface Window {
  inventContext?: Record<string, any>;
}

Tips for Gatsby

Serverless Functions

Use Gatsby Functions for hash generation

GraphQL Context

Pass content data for better context

Static & Dynamic

Works with SSG and DSG builds

Plugin Ecosystem

Integrates with Gatsby plugins

Troubleshooting

Solutions:
  • Check gatsby-browser.js for duplicate script logic
  • Use conditional to prevent duplicate loads
  • Clear .cache and public folders: gatsby clean
Solutions:
  • Prefix public variables with GATSBY_
  • Restart development server
  • Check .env files exist
  • Verify gatsby-config.js is reading variables
Solutions:
  • Ensure typeof window checks for SSR
  • Use dynamic imports if needed
  • Check all dependencies are installed
  • Clear cache: gatsby clean

Best Practices

  • Use Gatsby Functions for server-side operations
  • Always check for window before accessing it
  • Store secret keys in .env files (never commit)
  • Use GATSBY_ prefix only for public variables
  • Test both development and production builds