Add an assistant to a Next.js app
In this tutorial you sign up on Super Assist, create an agent and a project, and put the project’s assistant beside an Orders page in a new Next.js app. The assistant replies from Super Assist, answers from what the page shows, and ships an order when you ask. You write no backend.
You need Node.js and npm.
An agent answers on your organization’s AI spend. The Pro plan includes some every month; the Free plan runs agents only on credits bought in Billing. This tutorial uses Pro.
1. Sign up
Section titled “1. Sign up”- Open superassist.app/app/sign-up, fill in your name, email and password, and press Sign up.
- Open the verification link Super Assist emails you.
- Name your organization and press Create organization.
- In the sidebar, open Billing and press Upgrade to Pro.
2. Create an agent
Section titled “2. Create an agent”The agent is the assistant that answers in your app: its instructions, its model, and the skills, databases and knowledge bases it may use.
- Open Agents and press New agent.
- Name it
shop-assistant. - Above Instructions, press Start from a template and pick General assistant.
- Press Create agent.
For a support agent with its skills ready, press Install a template instead and pick saas-support. Templates says what to replace before it goes live.
3. Create a project and copy its publishable key
Section titled “3. Create a project and copy its publishable key”The project is your app on Super Assist. It holds the publishable key your pages connect with, the origins it accepts, and the agent that answers.
- Open Projects and press New project.
- Name it
My shop. Default agent already showsshop-assistant, your only agent. Press Create. - On the project’s page, press Copy beside Publishable key. It starts with
pk_.
The key is safe to ship in your app’s bundle: it only opens threads with the project’s agent. Allowed origins lists http://localhost:3000, where your app is about to run.
4. Create the app
Section titled “4. Create the app”Create a Next.js app with the default setup, TypeScript, Tailwind and the App Router, and install the library:
npx create-next-app@latest my-shop --yescd my-shopnpm install @super-assist/reactThat one package brings the panel, its styles and the runtime.
Put the publishable key in .env.local:
NEXT_PUBLIC_SUPER_ASSIST_KEY=pk_...5. Mount the panel
Section titled “5. Mount the panel”Create app/assistant.tsx. It imports the panel’s styles, connects to your project with useAssistedRuntime, and renders the panel inside AssistedProvider:
"use client";
import type { ReactNode } from "react";import { AssistedPanel, AssistedProvider, useAssistedRuntime } from "@super-assist/react";import "@super-assist/react/styles.css";
export function Assistant({ children }: { children: ReactNode }) { const runtime = useAssistedRuntime({ key: process.env.NEXT_PUBLIC_SUPER_ASSIST_KEY! }); return ( <AssistedProvider runtime={runtime}> <main className="min-h-dvh p-6">{children}</main> <AssistedPanel mode="floating" threads /> </AssistedProvider> );}threads adds a menu of your threads to the panel’s header. Super Assist keeps them.
In app/layout.tsx, wrap the children in Assistant. Keep the scaffold’s fonts and metadata, and change only the body:
import { Assistant } from "./assistant";<body> <Assistant>{children}</Assistant></body>6. See a reply
Section titled “6. See a reply”Replace app/page.tsx with a plain Orders page. Its orders live in state, so shipping one changes the page:
"use client";
import { useState } from "react";
type Order = { id: string; customer: string; status: "to ship" | "shipped" };
const seed: Order[] = [ { id: "1042", customer: "Acme", status: "to ship" }, { id: "1043", customer: "Globex", status: "to ship" }, { id: "1045", customer: "Initech", status: "shipped" },];
export default function Orders() { const [orders, setOrders] = useState(seed); const ship = (id: string) => setOrders((all) => all.map((order) => (order.id === id ? { ...order, status: "shipped" } : order)), ); return ( <ul className="flex flex-col gap-2"> {orders.map((order) => ( <li key={order.id} className="flex items-center gap-4"> #{order.id} {order.customer}, {order.status} {order.status === "to ship" && ( <button className="rounded border px-2 py-1 text-sm" onClick={() => ship(order.id)}> Ship </button> )} </li> ))} </ul> );}Start the app:
npm run devOpen http://localhost:3000. The three orders show, and an Assistant button sits in the bottom-right corner. Press it and the panel opens. Ask “What can you do?”.
Your agent replies from Super Assist. It can’t see the orders yet, because the page hasn’t introduced itself.
7. Let the assistant read and act
Section titled “7. Let the assistant read and act”Wrap the page in AssistedPage, which gives it a name, instructions for working there, and its content. The content is a function, read only when the assistant asks for it. Then wrap each Ship button in AssistedAction. Every row uses the name ship_order with its own id, so the assistant sees one action that picks a row by id:
"use client";
import { AssistedAction, AssistedPage } from "@super-assist/react";import { useState } from "react";
type Order = { id: string; customer: string; status: "to ship" | "shipped" };
const seed: Order[] = [ { id: "1042", customer: "Acme", status: "to ship" }, { id: "1043", customer: "Globex", status: "to ship" }, { id: "1045", customer: "Initech", status: "shipped" },];
export default function Orders() { const [orders, setOrders] = useState(seed); const ship = (id: string) => setOrders((all) => all.map((order) => (order.id === id ? { ...order, status: "shipped" } : order)), ); return ( <AssistedPage name="Orders" instructions="Every order of the shop. Ship an order that is waiting to ship by its id." content={() => orders} > <ul className="flex flex-col gap-2"> {orders.map((order) => ( <li key={order.id} className="flex items-center gap-4"> #{order.id} {order.customer}, {order.status} {order.status === "to ship" && ( <AssistedAction name="ship_order" id={order.id} label={`Ship ${order.customer}'s order #${order.id}`} > <button className="rounded border px-2 py-1 text-sm" onClick={() => ship(order.id)}> Ship </button> </AssistedAction> )} </li> ))} </ul> </AssistedPage> );}The panel’s header now reads “On Orders”. Ask “Which orders are waiting to ship?”.
The assistant calls get_page_content first, and its answer names Acme’s #1042 and Globex’s #1043.
Ask “Ship Globex’s order.”
The assistant calls ship_order with the id 1043, which presses Globex’s Ship button. The row now reads “shipped”, its button is gone, and the assistant tells you the order shipped.
What you built
Section titled “What you built”A Next.js app whose assistant runs on Super Assist. The project’s agent answers, the Orders page introduces itself and lends its content on demand, and each row lends an action the agent presses by id.
Next:
- Make an action consequential, so the user presses it or approves it.
- Lend a form’s fields, so the assistant fills them.
- Add
go_to_pageonce the app has more than one page. - Place the panel as a sheet or embedded, and rearrange its parts.
- Mount the devtools to see what the page lends.
- Use the hosted runtime to name your signed-in users, and to accept your production origin before you deploy.
- How a turn is answered, from the project and its agent to what the page lends.