Serverless Functions
ChatPage runs using Next.js, and supports Server Actions and Serverless Functions. Files marked with route.tsx will execute serverless functions, while files with the 'use server' directive enable Server Actions. Both allow you to execute code using sensitive keys to specified third party services, such as stripe.com, openai.com, and other whitelisted domains.
Available Data
Section titled “Available Data”Your functions have access to:
- process.env: Environment variables from your project
- params: URL parameters from dynamic routes
- query: Query string parameters from the request URL
- body: Request body data (for POST, PUT, PATCH requests)
Use Cases
Section titled “Use Cases”Streaming AI Responses with Vercel AI SDK
Section titled “Streaming AI Responses with Vercel AI SDK”Use the Vercel AI SDK to create streaming responses for real-time AI interactions.
import { streamText, convertToModelMessages, stepCountIs } from 'ai';import { createOpenRouter } from '@openrouter/ai-sdk-provider';import { tools } from '@/chat.config';import { DEFAULT_MODEL_ID, getModelById } from '@/lib/llm-models';import { insertMessages } from '@/actions/supabase/messages';
const openrouter = createOpenRouter({ apiKey: process.env.CHATPAGE_API_KEY!, baseURL: 'https://cloud.frontend.co/api/v1',});
export async function POST(request: Request) { try { const chatId = request.headers.get('x-chat-id'); const { messages, modelId } = await request.json();
const selectedModel = getModelById(modelId) ? modelId : DEFAULT_MODEL_ID; const model = openrouter(selectedModel);
const systemMessage = { role: 'system', parts: [{ type: 'text', text: 'You are an AI assistant.' }], }; const allMessages = [systemMessage, ...messages]; const convertedMessages = await convertToModelMessages(allMessages);
// Get the last user message for persistence const lastUserMessage = [...messages].reverse().find((m: { role: string }) => m.role === 'user');
const result = await streamText({ model, messages: convertedMessages, tools, stopWhen: stepCountIs(20), providerOptions: { openrouter: { reasoning: { enabled: true } } }, onFinish: async ({ text }) => { if (!chatId) return;
const messagesToInsert = [];
if (lastUserMessage) { messagesToInsert.push({ chat_id: chatId, role: 'user', parts: lastUserMessage.parts, }); }
if (text) { messagesToInsert.push({ chat_id: chatId, role: 'assistant', parts: [{ type: 'text', text }], }); }
if (messagesToInsert.length > 0) { try { await insertMessages(messagesToInsert); } catch (error) { console.error('Failed to persist messages:', error); } } }, });
return result.toUIMessageStreamResponse({ sendReasoning: true }) } catch (error) { console.error('Chat API error:', error); return new Response( JSON.stringify({ error: 'Failed to process chat request' }), { status: 500, headers: { 'Content-Type': 'application/json' }, } ); }}Querying a Database with Neon
Section titled “Querying a Database with Neon”Connect to a Neon Postgres database to run SQL queries.
import { NextRequest, NextResponse } from 'next/server';import { neon } from '@neondatabase/serverless';
const connectionString = `postgresql://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}/${process.env.DB_TABLE}`;
export async function GET(request: NextRequest) { const sql = neon(connectionString);
const users = await sql`SELECT id, name, email FROM users LIMIT 10`;
return NextResponse.json({ users });}
export async function POST(request: NextRequest) { const sql = neon(connectionString); const { name, email } = await request.json();
const result = await sql` INSERT INTO users (name, email) VALUES (${name}, ${email}) RETURNING id, name, email `;
return NextResponse.json({ user: result[0] });}Server Actions
Section titled “Server Actions”Use Server Actions to execute server-side code directly from your components without creating API routes.
'use server';
import { neon } from '@neondatabase/serverless';
const connectionString = `postgresql://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}/${process.env.DB_TABLE}`;
export async function executeQuery(query: string) { try { const sql = neon(connectionString); const result = await sql`${query}`; return { data: result }; } catch (error: any) { console.error('Database query error:', error); return { error: error.message || 'Failed to execute query' }; }}
export async function getUsers() { const sql = neon(connectionString); const users = await sql`SELECT id, name, email FROM users LIMIT 10`; return { users };}
export async function createUser(name: string, email: string) { const sql = neon(connectionString); const result = await sql` INSERT INTO users (name, email) VALUES (${name}, ${email}) RETURNING id, name, email `; return { user: result[0] };}