Next.js

Add an AI support assistant to a Next.js app

Two lines, one component, and no dependency added to your bundle.

  • One component
  • About two minutes
  • One file
app/layout.tsxfile
// app/layout.tsx — inside <body>, after {children}import Script from "next/script"; <Script id="matter-chat" strategy="afterInteractive">  {`window.MatterChat = window.MatterChat || { q: [] }; window.MatterChat.q.push(["init", { id: "bot_your_key" }]);`}</Script><Script src="https://app.matterchat.co/widget.js" strategy="afterInteractive" />
</body>

tsx · paste above the dimmed line

Where the snippet goes

Render it with next/script in your root layout, using the afterInteractive strategy. In the App Router that is app/layout.tsx; in the Pages Router it is pages/_app.tsx. The Script component handles deduplication across client-side navigation, so it initialises once and survives route changes.

next/script, afterInteractive
Loads after hydration, so it never competes with your app becoming interactive.
Root layout, one place
app/layout.tsx covers every route without per-page work.
No npm dependency
Nothing is added to your bundle — it is an external script, not a package.
Survives soft navigation
The Script component does not re-execute on client-side route changes.
!

Use next/script with afterInteractive. A bare script tag re-initialises on client-side navigation; the Script component deduplicates and survives route changes.

Index the docs you already deploy

If your documentation is part of the same app, or is a separate deployed site, the crawler reads it as published. There is no build step to add and no content to duplicate into another system.

Keep it out of the critical path

The script loads asynchronously, so it never blocks parsing or rendering. If you are measuring Core Web Vitals seriously, the afterInteractive strategy is the one that keeps a support widget out of your numbers — the plain async snippet can still fetch inside the critical window.

Checking it actually worked

Four things, in order. The third is the one people skip, and it is the one that tells you whether the answers are grounded.

  1. 1Hard refresh the page — the launcher appears bottom-right.
  2. 2Ask it something your site answers, and check the reply cites a page.
  3. 3Ask it something your site does not cover, and check it declines.
  4. 4Open Conversations in the dashboard; both should be there.

On a different stack?

The snippet is the same everywhere. Only the place you paste it changes.

What developers ask

Short answers. If yours is not here, the assistant on this page will try it — and tell you honestly if it cannot.

Does it work with the App Router?

Yes — render it from app/layout.tsx with next/script. It works the same way in the Pages Router from pages/_app.tsx.

Is there an npm package?

No, and that is intentional. It is a script tag, so nothing enters your bundle and there is no dependency to keep on a version treadmill.

Will it break on client-side navigation?

No. Loading it through next/script means it initialises once and is not re-executed when the router navigates.

From the blog

All posts

Answer honestly. Capture the rest.

Point Matter Chat at your site and see what it can — and can't — answer. It's honest about both.

Start free — chat in your site

No credit card. 2 minute setup.

Every answer cites the source it came from. When there isn't one, it says so — and hands the visitor to you.

Installs on the tools you already run.