Skip to main content

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