The Integration Pattern: Copilot as a Layer, Not a Rewrite
Most SaaS products don't need a new architecture to add an AI copilot they need a retrieval layer over data that already exists, an API route that streams a response, and a UI surface that doesn't compete with the product's existing navigation. We treat the copilot as an additive layer on top of the current Next.js App Router structure, not a rewrite.
export async function POST(req: Request) {
const { question, accountId } = await req.json();
const context = await retrieveAccountContext(accountId, question);
const stream = await claude.messages.stream({
model: "claude-sonnet-5",
max_tokens: 800,
system: "Answer only from the provided account context. Cite the source field for each claim.",
messages: [{ role: "user", content: `Context:\n${context}\n\nQuestion: ${question}` }],
});
return new Response(stream.toReadableStream());
}Scoping the Copilot to Jobs, Not Vibes
The SaaS copilots that get used solve 2-3 specific jobs 'where is this setting', 'why is this number what it is', 'draft this message' grounded in the account's own data. An open-ended chat box without that scoping gets tried once and abandoned.