Start here
Your first product
The kernel has no customer-facing UI and is not meant to. Your product is a normal web app that drives it over HTTP. The only structural decision you have to get right is this one: the browser never talks to the kernel.
Why the proxy is not optional
A project API key (msk_…) is a machine credential with full access to that project: every task, every approval, every connection, every client. There is no per-user token, no task-scoped JWT, no CORS story that makes it safe in a browser. Ship it to the client and you have handed any visitor the ability to approve their own refund.
Browser ──► your API routes (your auth) ──► Mycel kernel /v1 (private) /api/tasks → POST /v1/tasks /api/tasks/:id/events → SSE proxy, forwards Last-Event-ID /api/approvals/:id/… → approve / reject
The proxy is also where your authorisation lives. Mycel knows about orgs, projects and clients; it does not know that user 41 may only see their own invoices. That check belongs in your route, before the call goes out.
The smallest thing that works
One route, one fetch, your auth check at the top:
// app/api/tasks/route.ts
const KERNEL = process.env.MYCEL_KERNEL_URL ?? "http://localhost:4000";
export async function POST(req: Request) {
// YOUR auth and tenant checks go here, before anything leaves.
const r = await fetch(`${KERNEL}/v1/tasks`, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.MYCEL_API_KEY ?? ""}`,
},
body: await req.text(),
});
return new Response(r.body, {
status: r.status,
headers: { "content-type": "application/json" },
});
}That is a working product backend. Everything after it is the streaming half, which has one rule — do not buffer — and is covered in Integrating a frontend.
The thing you will actually want
Writing the SSE proxy, the approval cards and the task timeline by hand is a day you do not need to spend. The scaffolder writes them:
curl -fsSL https://mycelai.dev/new | node - my-service --theme teal cd my-service && npm i MYCEL_KERNEL_URL=http://localhost:4000 \ MYCEL_API_KEY=<your-key> \ npm run dev
Flags are --theme dark|light|teal and --yes. It generates a Next.js + Tailwind app with:
- proxy routes for tasks, events, cancel and approvals — the browser never sees the key
components/task-workspace.tsx, a live view rendered from the event stream: tool calls, streamed tokens, approval cards, statuswedges/starter/— a task type, a skill and a knowledge file to edit- the
mycel-workspaceskill under.claude/skills/, so your coding agent restyles the workspace to your brand instead of you fighting someone else's components
That last point is the intent behind having no @mycel/react package. The UI is generated against the event contract, so it can look like your company rather than like Mycel.
Two apps, two audiences
Do not conflate these. They authenticate differently and they are for different people.
| Your product | Founder portal | |
|---|---|---|
| For | Your customers | You and your team |
| Auth | Yours, in the proxy routes | Member login → msess_ session token |
| Env | MYCEL_KERNEL_URL + MYCEL_API_KEY | MYCEL_KERNEL_URL only |
| UI | Generated, branded | Shipped console in portal/ |
There is a third surface you may not need yet: the client portal. Mint a single-use magic link with POST /v1/clients/:id/portal-link, exchange it at POST /v1/portal/session, and that client gets their own threads, cases and a filtered event stream — cost and approval events are stripped out, so they see the work without seeing your margin or your internal gate.
Portal links and sessions live in process memory. They do not survive a kernel restart and they do not work across replicas. Fine for a pilot; know it before you email one to a paying customer.
Before you call it working
- Kernel reachable from your app, and from nowhere else
MYCEL_API_KEYonly ever read server-side — grep your client bundle formsk_- Your wedge on disk under
kernel/wedges/<slug>/ - A connection registered for anything that sends or charges (Connections & secrets)
- An approval resolvable from your UI, or from the portal, before you demo to anyone
What to read next
The app works but the agent is generic. Teaching the agent is the difference between a demo and something you can bill for.