Founding price: $35, then $79.99 after 23:59 UTC on 4 November, then $79.99
Get ProPro starter app. Needs a tealmac UI Pro licence. Set it up once on /pro/login, see Install Pro.
Cortex is a finished AI assistant interface. It is not a chat box: it is the whole product around one, so you can connect a model and ship. See it running at /templates/cortex.
Eight pages share one layout with a searchable chat history sidebar, a command menu on ⌘K and a drawer on phones.
/templates/cortex): a streaming message list, model picker,
attachments, web search toggle, token meter, reasoning disclosures, tool
call cards, inline citations with a sources panel, and a canvas that opens
documents and components from a reply./c/quarterly-report): a long thread with a failed and a
retried tool call, a model switch and a chart component in the canvas./new): a greeting, starter suggestions and the composer./prompts): search, categories, starring, sorting and a
create and edit dialog. Use opens a new chat with the prompt in the
composer./prompts/weekly-update): variables as form fields, a live
preview, version history and usage./files): uploads with indexing progress, failed files with
retry, collections and a storage meter./usage): tokens, requests and spend with trends, a chart per
day and model, plan limits and a per-member breakdown, with CSV export./settings): model defaults, custom instructions and memory,
data controls, and the provider connection.Every list page has empty, loading and error states. Add ?state=empty,
?state=loading or ?state=error to a page URL to preview them.
It is built from tealmac UI components: ai-chat, ai-message,
prompt-input, model-picker, sources-list, citation,
reasoning-disclosure, tool-call-card, artifact-panel, token-meter,
chat-attachment, streaming-text, suggestion-chips, state-view,
usage-meter, file-dropzone and api-key-field, plus shadcn/ui primitives
and the chart component.
Add your key to .env.local:
TEALMAC_UI_LICENSE_KEY=your-licence-keyRegister the namespace once in components.json:
{
"registries": {
"@tealmac-pro": {
"url": "https://ui.tealmac.com/r/pro/{name}.json",
"headers": {
"Authorization": "Bearer ${TEALMAC_UI_LICENSE_KEY}"
}
}
}
}The CLI installs the free components and packages Cortex needs, such as
recharts, motion and sonner.
Cortex shows toasts. If you have not yet, render <Toaster /> from
@/components/ui/sonner once in your root layout.
components/tealmac-pro/cortex/
cortex-shell.tsx sidebar, top bar, command menu
cortex-chat-view.tsx the chat workspace, canvas and sources panel
cortex-ai-sdk.ts adapter from AI SDK messages
cortex-data.ts demo data: models, chats, prompts, files, usage
cortex-*.tsx one file per page
app/templates/cortex/
page.tsx chat
c/quarterly-report/page.tsx
new/page.tsx
prompts/page.tsx
prompts/weekly-update/page.tsx
files/page.tsx
usage/page.tsx
settings/page.tsxPages link to each other under /templates/cortex. To serve the app from
another path, move the app/templates/cortex folder and search for the old
prefix in the cortex-*.tsx files.
Cortex keeps its demo conversations in the message shape the Vercel AI SDK
uses, a UIMessage with parts, and renders everything through
toCortexMessages(). In cortex-chat-view.tsx the simulated hook
useSimulatedChat returns the same fields as useChat(), so connecting a
model means replacing one line. No keys and no extra dependency are added by
the install.
npm i ai @ai-sdk/reactimport { useChat } from "@ai-sdk/react"
// before: const chat = useSimulatedChat(convo?.messages ?? [])
const chat = useChat({ messages: convo?.messages })
// These two lines stay the same.
const view = toCortexMessages(chat.messages, chat.status, sourceDetails)
const promptStatus = toPromptStatus(chat.status)useChat returns messages, sendMessage, status and stop. Cortex calls
chat.sendMessage({ text, files }), chat.stop() and chat.regenerate().
Pass real files as FileList or file parts, as the SDK documents.
import { convertToModelMessages, streamText, type UIMessage } from "ai"
export const maxDuration = 60
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json()
const result = streamText({
// A "provider/model" string for the AI Gateway, or a provider instance.
model: process.env.CORTEX_MODEL ?? "provider/model-name",
system: "You are Cortex, a careful assistant for the Northbeam team.",
messages: convertToModelMessages(messages),
})
return result.toUIMessageStreamResponse({
sendReasoning: true,
sendSources: true,
})
}Put the provider key in your host's environment (for example
CORTEX_PROVIDER_API_KEY), never in client code.
| AI SDK part | Cortex renders |
|---|---|
text | Message text with **bold**, lists, [1] |
reasoning | A reasoning disclosure |
tool-*, dynamic-tool | A tool call card with input and result |
source-url | A citation and an entry in the sources list |
file | An attachment chip |
data-artifact | An artifact card that opens the canvas |
data-artifact is Cortex's own data part. Send it from a tool or the stream
writer with { title, kind, filename, language, code } and the canvas shows it.
step-start and unknown parts are ignored. The streaming caret, the
Stop button and the thinking indicator follow status.
cortex-data.ts holds the models, history, prompts, files and usage numbers.
Replace each with a query: chats and prompts from your database, files from
your index, usage from your billing events. Shapes are exported as TypeScript
types, and every list page already handles empty, loading and error states
through the StateView component.
Cortex uses semantic tokens only: background, card, primary, muted,
accent, border and chart-1 to chart-5. It follows light and dark mode
and every theme preset with no extra CSS. See Theming.
main and navigation regions,
and one h1.role="log" region with a polite live announcement and
a scroll-to-latest button; the composer has a visible label.prefers-reduced-motion, and animations
are switched off.