Next.js
Wire Crux into a Next.js 16 App Router project — Server Actions, streaming Route Handlers, and the recommended file layout.
This guide gets Crux running in a Next.js 16 App Router project. Crux prompts run on the server — define them in a shared module and call them from Server Actions or Route Handlers.
Crux is in alpha. The install commands below are the intended package set for the first public npm alpha; until that release lands, consume Crux from this repository workspace.
Install
bash npm install @crux/core @crux/ai @ai-sdk/openai zod bash pnpm add @crux/core @crux/ai @ai-sdk/openai zod bash yarn add @crux/core @crux/ai @ai-sdk/openai zod bash bun add @crux/core @crux/ai @ai-sdk/openai zod OPENAI_API_KEY=sk-...The @ai-sdk/openai provider reads OPENAI_API_KEY automatically.
Recommended layout
app/
actions/
summarize.ts ← Server Action that calls generate()
api/
chat/route.ts ← Route Handler with streaming
lib/
ai/
prompts.ts ← Prompt definitions
contexts.ts ← Shared contexts
config.ts ← policy/defaults config (optional)This is a recommendation, not a requirement. Crux has no required project structure — organize however fits your codebase.
Step 1: Define a prompt
Create the prompt module
import { prompt, context } from '@crux/core'
import { z } from 'zod'
const brand = context({
id: 'brand',
priority: 30,
system: 'Use a professional tone. Be concise.',
})
export const summarize = prompt({
id: 'summarize',
use: [brand],
input: z.object({ text: z.string() }),
output: z.object({
summary: z.string(),
keyPoints: z.array(z.string()),
}),
system: 'Summarize the given text.',
prompt: ({ input }) => input.text,
})Call it from a Server Action
'use server'
import { generate } from '@crux/ai'
import { openai } from '@ai-sdk/openai'
import { summarize } from '@/lib/ai/prompts'
export async function summarizeText(text: string) {
const result = await generate(summarize, {
model: openai('gpt-4o-mini'),
input: { text },
})
return result.object
}Use it in a Server Component or Client Component
import { summarizeText } from './actions/summarize'
export default async function Page() {
const result = await summarizeText('Long article text here...')
return (
<article>
<p>{result.summary}</p>
<ul>
{result.keyPoints.map((point) => (
<li key={point}>{point}</li>
))}
</ul>
</article>
)
}Streaming from a Route Handler
For chat or any long-form output, stream from a Route Handler:
import { stream } from '@crux/ai'
import { openai } from '@ai-sdk/openai'
import { chatPrompt } from '@/lib/ai/prompts'
export async function POST(req: Request) {
const { message } = await req.json()
const result = await stream(chatPrompt, {
model: openai('gpt-4o'),
input: { message },
})
return result.toUIMessageStreamResponse()
}The Vercel AI SDK adapter's stream() returns a result compatible with toUIMessageStreamResponse() for seamless
integration with useChat on the client.