Neocortex
IntegrationsWeb SDK

Quick Start

Put a Neocortex character on a website or browser game without exposing your API key

@neocortex-link/web has three entry points:

  • @neocortex-link/web/server: a proxy that holds your API key and checks every request.
  • @neocortex-link/web/client: smart characters, group chat, quizzes, mic input and streamed speech.
  • @neocortex-link/web/ui: Web Components such as <neocortex-chat> and <neocortex-quiz>, for any framework or none.
Browser                         Your server                      Neocortex
<neocortex-chat> ──fetch──▶  createNeocortexHandler()  ──x-api-key──▶  api.neocortex.link/v3
                 ◀─────────  (auth, allowlist, limits)  ◀────────────

The browser never sees your key. Source: neocortex-link/neocortex-web-sdk (Apache-2.0).

Requirements

Setup

Install

npm install @neocortex-link/web

Add the proxy

authorize returns the signed-in visitor as { id }, or null to refuse. The id becomes the Neocortex playerId.

app/api/neocortex/[...path]/route.ts
import { createNeocortexHandler } from "@neocortex-link/web/server";
import { auth } from "@/auth";

const handler = createNeocortexHandler({
  apiKey: process.env.NEOCORTEX_API_KEY!,
  characters: ["your-character-id"],
  authorize: async () => {
    const session = await auth();
    return session?.user ? { id: session.user.id } : null;
  },
});

export { handler as GET, handler as POST, handler as OPTIONS };
server.ts
import express from "express";
import { createNeocortexHandler, toNodeHandler } from "@neocortex-link/web/server";

const app = express();
const handler = createNeocortexHandler({
  apiKey: process.env.NEOCORTEX_API_KEY!,
  characters: ["your-character-id"],
  authorize: (request) => {
    const user = getUserFromCookie(request.headers.get("cookie"));
    return user ? { id: user.id } : null;
  },
});

app.use("/api/neocortex", toNodeHandler(handler));

toNodeHandler also works with Connect and node:http.

worker.ts
import { createNeocortexHandler } from "@neocortex-link/web/server";

let handler: ((request: Request) => Promise<Response>) | undefined;

export default {
  fetch(request: Request, env: { NEOCORTEX_API_KEY: string }) {
    handler ??= createNeocortexHandler({
      apiKey: env.NEOCORTEX_API_KEY,
      basePath: "",
      characters: ["your-character-id"],
      authorize: async (request) => {
        const user = await getUserFromRequest(request);
        return user ? { id: user.id } : null;
      },
    });
    return handler(request);
  },
};

The same handler mounts in Hono, Bun and Deno. For a rate limit shared across instances, see Serverless hosts.

Add a chat

import "@neocortex-link/web/ui/auto";

Or without a bundler:

<script type="module" src="https://cdn.jsdelivr.net/npm/@neocortex-link/web@0.2/dist/ui/auto.js"></script>

Then:

<neocortex-chat endpoint="/api/neocortex" character-id="your-character-id" voice></neocortex-chat>

Handle actions

const chat = document.querySelector("neocortex-chat");
chat.agent.registerAction("OPEN_DOOR", (action) => door.open(action.targetId));

No login?

authorize still needs a stable id per visitor. Issue one in a signed, httpOnly cookie, see Anonymous visitors.

Self-hosting the UI bundle

<script type="importmap">
  { "imports": { "@neocortex-link/web/ui/auto": "/vendor/neocortex/ui/auto.js" } }
</script>
<script type="module">
  import "@neocortex-link/web/ui/auto";
</script>

/vendor/neocortex/ serves the package's dist folder.

Example

examples/quickstart: one HTML page and a node:http server, with anonymous visitor cookies and buildContext.

Next

On this page