> ## 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.

# Contentful

> Add your Invent assistant to Contentful-powered sites

## Overview

Add your Invent AI assistant to websites powered by Contentful. Perfect for headless CMS architectures using React, Next.js, Gatsby, or any other framework.

## Installation Methods

Since Contentful is a headless CMS, the implementation depends on your frontend framework.

### React / Next.js

<Steps>
  <Step title="Create Assistant Component">
    Create a new component for the Invent assistant:

    ```jsx theme={"system"}
    // components/InventAssistant.jsx
    import { useEffect } from 'react';

    export default function InventAssistant() {
      useEffect(() => {
        const script = document.createElement('script');
        script.src = 'https://www.useinvent.com/embed.js';
        script.async = true;
        script.defer = true;
        document.body.appendChild(script);

        return () => {
          document.body.removeChild(script);
        };
      }, []);

      return (
        <invent-assistant assistant-id="ast_YOUR_ASSISTANT_ID" />
      );
    }
    ```
  </Step>

  <Step title="Add to Layout">
    Import and use in your layout component:

    ```jsx theme={"system"}
    // app/layout.jsx or pages/_app.jsx
    import InventAssistant from '@/components/InventAssistant';

    export default function Layout({ children }) {
      return (
        <html>
          <body>
            {children}
            <InventAssistant />
          </body>
        </html>
      );
    }
    ```
  </Step>
</Steps>

### Gatsby

<Steps>
  <Step title="Install React Helmet">
    ```bash theme={"system"}
    npm install react-helmet
    ```
  </Step>

  <Step title="Add to gatsby-browser.js">
    ```javascript theme={"system"}
    // gatsby-browser.js
    export const onRouteUpdate = () => {
      if (typeof window !== 'undefined') {
        const script = document.createElement('script');
        script.src = 'https://www.useinvent.com/embed.js';
        script.async = true;
        script.defer = true;
        document.body.appendChild(script);
      }
    };
    ```
  </Step>

  <Step title="Add Component">
    ```jsx theme={"system"}
    // src/components/layout.jsx
    import { Helmet } from 'react-helmet';

    const Layout = ({ children }) => (
      <>
        <Helmet>
          <invent-assistant assistant-id="ast_YOUR_ASSISTANT_ID" />
        </Helmet>
        {children}
      </>
    );
    ```
  </Step>
</Steps>

### Vue.js / Nuxt

```vue theme={"system"}
<!-- components/InventAssistant.vue -->
<template>
  <div>
    <invent-assistant :assistant-id="assistantId" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      assistantId: 'ast_YOUR_ASSISTANT_ID'
    }
  },
  mounted() {
    const script = document.createElement('script');
    script.src = 'https://www.useinvent.com/embed.js';
    script.async = true;
    script.defer = true;
    document.body.appendChild(script);
  }
}
</script>
```

### Static HTML

For static site generators that output HTML:

```html theme={"system"}
<!-- Add to your template file -->
<invent-assistant assistant-id="ast_YOUR_ASSISTANT_ID" />
<script type="text/javascript" src="https://www.useinvent.com/embed.js" async defer></script>
```

## Passing Contentful Data

You can pass Contentful content data to provide context to your assistant:

```jsx theme={"system"}
import { useEffect } from 'react';

export default function ContentfulPage({ entry }) {
  useEffect(() => {
    if (typeof window !== 'undefined') {
      window.inventContext = {
        contentType: entry.sys.contentType.sys.id,
        entryId: entry.sys.id,
        title: entry.fields.title,
        // Add relevant fields
      };
    }
  }, [entry]);

  return (
    <div>
      <h1>{entry.fields.title}</h1>
      {/* Your content */}
    </div>
  );
}
```

## Environment Variables

Store your assistant ID in environment variables:

```bash theme={"system"}
# .env.local
NEXT_PUBLIC_INVENT_ASSISTANT_ID=ast_YOUR_ASSISTANT_ID
```

```jsx theme={"system"}
<invent-assistant
  assistant-id={process.env.NEXT_PUBLIC_INVENT_ASSISTANT_ID}
/>
```

## User Authentication

<Warning>
  **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 or generate the hash in frontend code.
</Warning>

To authenticate users from your application and provide personalized experiences:

1. Generate a secret key in your assistant settings
2. On your backend, generate an HMAC-SHA256 hash of the user ID
3. Pass the hash along with user information to the assistant

See the [Widget Authentication](/assistants/widget#user-authentication-optional) guide for complete authentication details.

## Framework-Specific Tips

<CardGroup cols={2}>
  <Card title="Next.js" icon="react">
    Use in \_app.jsx or layout.tsx for global availability
  </Card>

  <Card title="Gatsby" icon="gatsby">
    Add to gatsby-browser.js for all pages
  </Card>

  <Card title="Nuxt" icon="vuejs">
    Create as a plugin in plugins/ directory
  </Card>

  <Card title="SvelteKit" icon="svelte">
    Add to root +layout.svelte
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Component not rendering in React">
    **Solutions:**

    * Ensure script loads after component mounts
    * Check for hydration issues in SSR
    * Verify custom element support in your build
  </Accordion>

  <Accordion title="SSR/SSG issues">
    **Solutions:**

    * Load script only on client side
    * Use useEffect or mounted lifecycle
    * Check for window object availability
  </Accordion>
</AccordionGroup>
