Skip to main content
In this tutorial, you build a small Next.js app with a login page, a dashboard and an assistant. Each customer who logs in gets answers on their own rows only. You will:
  • open a session on your server with @concatflow/node,
  • show the assistant with <ConcatflowAssistant>,
  • renew the session when it expires,
  • check that two customers never see each other’s data.
The finished app adds seven files to a new Next.js project.

Before you start

You need Node 20.9 or later, for Next.js 16. In the Concatflow dashboard, open your assistant and check four things:
  • Isolation is signed on customer_id. If your isolation uses another key, use that key wherever this tutorial says customer_id.
  • In Doors, the per-user door is on.
  • In Doors → Allowed origins, http://localhost:3000 is listed.
  • The assistant is published.
You also need your API key and assistant ID, and two customer IDs from your database whose data differs.

1. Create the app

--yes picks the defaults: TypeScript, the App Router and the @/* import alias. This tutorial relies on all three.

2. Add your keys

Create .env.local at the root of the project:
.env.local
Neither name starts with NEXT_PUBLIC_, so Next.js never sends them to the browser. The project’s .gitignore already leaves .env* files out of git.

3. Add a stand-in login

The assistant needs to know who is logged in. Your app already has a login. For this tutorial, a cookie holding the customer ID stands in for it.
lib/auth.ts
app/login/actions.ts
app/login/page.tsx
Anyone can type any customer ID into this page. That is fine on your laptop, never in production. What matters is the rule the rest of the tutorial follows: the customer comes from auth(), on the server, never from the request body.

4. Open a session on the server

One function opens a Concatflow session for one customer. server-only makes the build fail if a client component ever imports it, so your API key cannot reach the browser.
lib/concatflow.ts
It resolves to { token, expiresAt }. The token is opaque and lasts 15 minutes. The keys of partitions must be exactly the keys of the isolation: a missing or extra key fails with 403 partition_keys_mismatch.

5. Add the renewal route

When a token expires, the assistant asks your page for a new one. Your page asks this route.
app/api/concatflow/session/route.ts
The route answers 401 to a visitor who is not logged in. It never passes Concatflow’s error body to the browser: it logs the status and only returns the code.

6. Show the assistant

The dashboard is a server component. It opens the first session while it renders, so the assistant gets its token without a round trip.
app/dashboard/page.tsx
create-next-app turns on Cache Components. With them, code that reads the request, such as cookies() in auth(), must render inside <Suspense>. Without it, next build fails on this page. The assistant itself is a client component. It renews its token through the route from step 5.
app/dashboard/assistant.tsx
key={customerId} gives each customer a fresh assistant. When the customer logs out, the component unmounts and the assistant is destroyed.

7. Run it

Open http://localhost:3000/login and log in with your first customer ID.
A login form with a customer ID field and a Log in button

The stand-in login.

The search bar appears under the heading. Ask a question that only this customer’s data can answer, such as “What are my account balances?”.
The dashboard of customer 4712 with an answer listing two accounts and their balances

Customer 4712 sees their two accounts.

No bar? Open the browser console. Concatflow: … names the problem. A 502 from /api/concatflow/session means Concatflow refused the session: the server log shows the status and code. See Errors.

8. Check the renewal

You do not have to wait 15 minutes. In app/dashboard/assistant.tsx, hand the assistant a token Concatflow will refuse:
app/dashboard/assistant.tsx
Reload the dashboard and ask a question. In the Network tab of your browser’s developer tools, you see one POST /api/concatflow/session, and the assistant answers. That is what happens 15 minutes after each page load. Put session={initialToken} back.

9. Check the isolation

  1. Note the answer the first customer got.
  2. Click Log out, then log in with the second customer ID.
  3. Ask the same question.
The dashboard of customer 4713 with an answer listing one account

Customer 4713 asks the same question and sees only their own account.

The second customer must see neither the first customer’s rows nor their questions. Log in with the first customer ID again: their conversation is still there. Concatflow keeps one conversation per assistant and per customer.

What you built

The browser only ever holds the token. Your API key, and the customer ID Concatflow filters on, stay on your server.

Next steps

Go live

Production origins, caps and the last checks.

Erase a customer's conversations

Call conversations.erase when a customer deletes their account.

Appearance

Accent colour, theme and placeholder.

Bar or bubble

Choose where the assistant lives on the page.