Skip to content

feat(server): chatcopsNext() catch-all route adapter for Next.js (#574) - #580

Open
Saifjafri212213 wants to merge 4 commits into
codercops:devfrom
Saifjafri212213:feat/server-chatcops-next
Open

Saifjafri212213 wants to merge 4 commits into
codercops:devfrom
Saifjafri212213:feat/server-chatcops-next

Conversation

@Saifjafri212213

@Saifjafri212213 Saifjafri212213 commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

A dedicated Next.js App Router adapter (chatcopsNext()) that serves both the chat and session endpoints from a single catch-all route (app/api/chat/[[...path]]/route.ts), replacing the previous two-file requirement (route.ts and session/route.ts).

Closes #574

Why

Today, Next.js setups need two route files: app/api/chat/route.ts and app/api/chat/session/route.ts (which re-exports POST and OPTIONS). Forgetting the second one quietly breaks session tokens with 404s when the chat tries to initialize.

Next.js optional catch-all routes ([[...path]]) let a single route file handle every subpath under /api/chat. fetchChatResponse() in packages/server/src/http.ts already routes paths ending in /session to the session endpoint via isSessionPath(), so the catch-all works without needing internal routing of its own.

What changed

  • @chatcops/server:
    • packages/server/src/adapters/next.ts: chatcopsNext(config) builds on chatcopsVercelHandler(config) and returns { POST: handler, OPTIONS: handler }, sharing one battle-tested code path for Vercel/Next fetch runtimes.
    • Added "./next" to exports in packages/server/package.json alongside "./vercel", and re-exported chatcopsNext from packages/server/src/index.ts.
  • Docs:
    • Updated the Next.js App Router section in website/src/content/docs/server/fetch-runtimes.mdx explaining the catch-all route, emphasizing that double brackets [[...path]] are required so /api/chat itself does not 404.
    • Updated website/src/content/docs/server/setup.mdx and website/src/content/docs/examples/vercel-full.mdx to direct Next.js users to the single catch-all route instead of two route files.
    • Added chatcopsNext to scripts/check-doc-samples.mjs so pnpm docs:check validates that Next doc samples configure session secrets or allow anonymous access.
  • Changeset & API: Minor changeset for @chatcops/server, and committed the updated API snapshot in api/server.api.md.

Notes for review

  • chatcopsNext returns { POST, OPTIONS }. A GET handler is left for later with visitor handoff (F-10), as noted in the issue.
  • Both POST and OPTIONS point to the single handler, so CORS preflight and chat/session POSTs are handled by fetchChatResponse().

How I Tested This

  • packages/server/tests/adapters/next.test.ts (4 new tests with real Request objects):
    • OPTIONS preflight returning 204 with CORS headers.
    • Session POST to /api/chat/session minting a session token (200).
    • Chat POST to /api/chat without a token returning 401 (session_required).
    • Chat POST with the session Bearer token streaming the SSE reply (200).
  • Coverage: 100% statement, branch, function, and line coverage on src/adapters/next.ts.
  • Fresh Next.js App Verification:
    • Tested in a fresh Next.js 15 app (create-next-app@latest with App Router and TypeScript).
    • Configured app/api/chat/[[...path]]/route.ts with chatcopsNext().
    • Loaded the widget script (chatcops.min.js) via Next.js <Script src="http://localhost:3000/chatcops.min.js" data-api-url="/api/chat" /> in app/layout.tsx.
    • Verified in browser network tab: the widget requested /api/chat/session, received a 200 with JWT token, and subsequent user messages were sent with Authorization: Bearer <token> and successfully streamed assistant replies.
  • Local checks: pnpm docs:check passes (205 blocks checked, 3 skipped), pnpm api:check is up to date, pnpm publint reports all good, pnpm lint has 0 errors, and pnpm -r typecheck passes cleanly.

AI assistance

Written with an AI coding assistant (Google Antigravity / Gemini) for initial route scaffolding, test drafting, and documentation text. I verified every line, tested in the fresh Next.js app, and executed all automated checks above.

@anurag629 anurag629 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Saifjafri212213, this mostly works. Both /api/chat and /api/chat/session go through one handler, the four tests from #574 are there, and so are the changeset and the api/ snapshot. A few things need to change before it can go in:

  1. chatcopsNext at packages/server/src/adapters/next.ts:7-20 is chatcopsVercelHandler (packages/server/src/adapters/vercel.ts:7-13) with a different return. Build it on that instead, so Next and Vercel share one code path:

    import { chatcopsVercelHandler } from './vercel.js';
    import type { ChatCopsServerConfig } from '../config.js';
    
    export function chatcopsNext(config: ChatCopsServerConfig) {
      const handler = chatcopsVercelHandler(config);
      return { POST: handler, OPTIONS: handler };
    }

    The type comes out the same, so api/ doesn't change, and your tests cover it as they are.

  2. Two pages still tell Next.js users to add the second route file, which is the step #574 removes: website/src/content/docs/server/setup.mdx:230 in the session tokens section, and the Next.js part of website/src/content/docs/examples/vercel-full.mdx:58-82. Point both at the catch-all route on the fetch runtimes page. In fetch-runtimes.mdx, also say the double brackets matter: app/api/chat/[...path]/route.ts doesn't match /api/chat itself, so every chat request gets a 404.

  3. The description needs the "AI assistance" section (CONTRIBUTING.md:13), like #545 and #569 had. The issue also asks what you ran in the fresh Next.js app. Please add the Next.js version, how you loaded the widget, and that a message got a reply after its /api/chat/session request.

When you push, merge dev in too. #585 and #587 went in since, with no overlap. I'll review it again then.

@Saifjafri212213

Copy link
Copy Markdown
Collaborator Author

Thanks @anurag629 for the review! I've updated the PR accordingly:

  1. Reused chatcopsVercelHandler:

    • Refactored chatcopsNext in packages/server/src/adapters/next.ts to build directly on chatcopsVercelHandler, sharing the exact same execution path and returning { POST: handler, OPTIONS: handler }.
  2. Documentation:

    • Updated website/src/content/docs/server/setup.mdx:230 and website/src/content/docs/examples/vercel-full.mdx to use the single catch-all route instead of asking for two route files.
    • In website/src/content/docs/server/fetch-runtimes.mdx, added an explanation noting that the double brackets [[...path]] (optional catch-all) are required so that /api/chat itself does not 404.
  3. Description & Verification:

    • Added the AI assistance section specifying the tool and usage.
    • Detailed the fresh Next.js (v15) verification: loaded the widget via <Script> in app/layout.tsx, confirmed /api/chat/session mints the session token, and verified chat streaming works with Bearer auth.
  4. Merged dev:

    • Merged latest origin/dev cleanly into the branch.

@anurag629 anurag629 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Saifjafri212213, nearly there. chatcopsNext now builds on chatcopsVercelHandler, the double-bracket note is in fetch-runtimes.mdx:34, setup.mdx:230 and vercel-full.mdx point at the catch-all route, and the description has the Next.js 15 run and the AI section. All checks pass, including e2e.

Two more places still tell Next.js users to add app/api/chat/session/route.ts, the step #574 removes:

  1. website/src/content/docs/server/security.mdx:68, the comment on the Vercel and Next.js example.
  2. packages/server/README.md:53, under Vercel Edge. That README is what npm shows for @chatcops/server, and people copy from it as often as from the docs.

Point both at the catch-all route the way setup.mdx:230 does now, and keep the second file only for Vercel without Next.js. I'll review it again then.

@Saifjafri212213

Copy link
Copy Markdown
Collaborator Author

Thanks @anurag629! I have updated both places:

  1. website/src/content/docs/server/security.mdx: Updated the comment and section to point to the Next.js catch-all route (app/api/chat/[[...path]]/route.ts), keeping the second file reference only for Vercel without Next.js.
  2. packages/server/README.md: Updated the Vercel Edge section to point Next.js users to the catch-all route with chatcopsNext, keeping the second file reference only for Vercel without Next.js.

@anurag629 anurag629 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Saifjafri212213. security.mdx:67 and packages/server/README.md:53 now send Next.js users to the [[...path]] catch-all with chatcopsNext and keep api/chat/session.ts only for Vercel without Next.js, the same way setup.mdx:230 reads. All checks pass, including e2e.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server: chatcopsNext(), one catch-all route for Next.js

2 participants