Skip to content

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. Open superassist.app/app/sign-up, fill in your name, email and password, and press Sign up.
  2. Open the verification link Super Assist emails you.
  3. Name your organization and press Create organization.
  4. In the sidebar, open Billing and press Upgrade to Pro.

The agent is the assistant that answers in your app: its instructions, its model, and the skills, databases and knowledge bases it may use.

  1. Open Agents and press New agent.
  2. Name it shop-assistant.
  3. Above Instructions, press Start from a template and pick General assistant.
  4. 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.

  1. Open Projects and press New project.
  2. Name it My shop. Default agent already shows shop-assistant, your only agent. Press Create.
  3. 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.

Create a Next.js app with the default setup, TypeScript, Tailwind and the App Router, and install the library:

Terminal window
npx create-next-app@latest my-shop --yes
cd my-shop
npm install @super-assist/react

That one package brings the panel, its styles and the runtime.

Put the publishable key in .env.local:

my-shop/.env.local
NEXT_PUBLIC_SUPER_ASSIST_KEY=pk_...

Create app/assistant.tsx. It imports the panel’s styles, connects to your project with useAssistedRuntime, and renders the panel inside AssistedProvider:

my-shop/app/assistant.tsx
"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:

my-shop/app/layout.tsx
import { Assistant } from "./assistant";
my-shop/app/layout.tsx
<body>
<Assistant>{children}</Assistant>
</body>

Replace app/page.tsx with a plain Orders page. Its orders live in state, so shipping one changes the page:

my-shop/app/page.tsx
"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:

Terminal window
npm run dev

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

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:

my-shop/app/page.tsx
"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.

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: