> Version notice: This site documents BAML v0, the legacy DSL. BAML v1 is a separate, fully featured programming language in public beta. If the user intends to use BAML v1, ignore this site's content and use the BAML v1 documentation instead. If the intended version is unclear, clarify it before using this page. > For clean Markdown of any page, append .md to the page URL. For the complete documentation index, see https://docs.boundaryml.com/llms.txt. For MCP access, connect to https://docs.boundaryml.com/_mcp/server. # React/Next.js Setup This guide walks you through setting up BAML with React/Next.js, leveraging Server Actions and React Server Components for optimal performance. > **Note** > > **Requirements:** This integration requires **Next.js 15 or higher**. ## Example Usage BAML automatically generates a server action and React hook for your BAML functions, with built-in support for both streaming and non-streaming modes. For details on the generated hooks, see [Generated Hooks](/ref/baml_client/react-next-js/use-function-name-hook). **`baml_src/prompt.baml`** ```baml title="baml_src/prompt.baml" class Story { title string @stream.not_null content string @stream.not_null } function WriteMeAStory(input: string) -> Story { client "openai/gpt-5" prompt #" Tell me a story {{ ctx.output_format() }} {{ _.role("user") }} Topic: {{input}} "# } ``` **`Generate BAML client`** ```bash title="Generate BAML client" npx baml-cli generate pnpm exec baml-cli generate yarn baml-cli generate bun baml-cli generate deno run --unstable-sloppy-imports -A npm:@boundaryml/baml/baml-cli generate ``` **`app/components/story-form.tsx`** ```tsx title="app/components/story-form.tsx" {8,10,15-16} 'use client' // ✅ Automatically generates a server action and React hook import { useWriteMeAStory } from "../../../baml_client/react/hooks"; export function StoryForm() { const writeMeAStory = useWriteMeAStory(); return (

{writeMeAStory.data?.title}

{writeMeAStory.data?.content}

{writeMeAStory.error &&
Error: {writeMeAStory.error.message}
}
); } ``` ## Quick Start Follow the step-by-step instructions below to set up BAML in a new or existing Next.js project. ### Create a New Next.js Project First, create a new Next.js project with the App Router: **`npm`** ```bash npm npx create-next-app@latest my-baml-app ``` **`pnpm`** ```bash pnpm pnpm create next-app my-baml-app ``` **`yarn`** ```bash yarn yarn create next-app my-baml-app ``` **`bun`** ```bash bun bun create next-app my-baml-app ``` **`deno`** ```bash deno deno create next-app my-baml-app ``` When prompted, make sure to: * Select **Yes** for "Would you like to use TypeScript?" * Select **Yes** for "Would you like to use the App Router? (recommended)" * Configure other options as needed for your project ### Install Dependencies Next, install BAML and its dependencies: **`npm`** ```bash npm npm install @boundaryml/baml @boundaryml/baml-nextjs-plugin ``` **`pnpm`** ```bash pnpm pnpm add @boundaryml/baml @boundaryml/baml-nextjs-plugin ``` **`yarn`** ```bash yarn yarn add @boundaryml/baml @boundaryml/baml-nextjs-plugin ``` **`bun`** ```bash bun bun add @boundaryml/baml @boundaryml/baml-nextjs-plugin ``` **`deno`** ```bash deno deno add @boundaryml/baml @boundaryml/baml-nextjs-plugin ``` ### Configure Next.js Update your `next.config.mjs`: **`next.config.ts`** ```typescript title="next.config.ts" {1,8} import { withBaml } from '@boundaryml/baml-nextjs-plugin'; import type { NextConfig } from 'next'; const nextConfig: NextConfig = { // ... existing config }; export default withBaml()(nextConfig); ``` **`next.config.mjs`** ```javascript title="next.config.mjs" {1,8} import { withBaml } from '@boundaryml/baml-nextjs-plugin'; import type { NextConfig } from 'next'; const nextConfig: NextConfig = { // ... existing config }; export default withBaml()(nextConfig); ``` **`next.config.js`** ```javascript title="next.config.js" {1,8} const { withBaml } = require('@boundaryml/baml-nextjs-plugin'); /** @type {import('next').NextConfig} */ const nextConfig = { // ... existing config } module.exports = withBaml()(nextConfig) ``` ### Initialize BAML Create a new BAML project in your Next.js application: **`npm`** ```bash npm npx baml-cli init ``` **`pnpm`** ```bash pnpm pnpm exec baml-cli init ``` **`yarn`** ```bash yarn yarn baml-cli init ``` **`bun`** ```bash bun bun baml-cli init ``` **`deno`** ```bash deno deno run --unstable-sloppy-imports -A npm:@boundaryml/baml/baml-cli init ``` This will create a `baml_src` directory with starter code. ### Setup Environment Variables Setup provider specific API Keys. **`.env.local`** ```.env .env.local OPENAI_API_KEY=sk-... ``` #### (Optional) BAML Observability To enable observability with BAML, you'll first need to sign up for a [Boundary Studio](https://studio.boundaryml.com) account. **`.env.local`** ```.env .env.local BOUNDARY_API_KEY=your_api_key_here OPENAI_API_KEY=sk-... ``` ### Setup BAML Next.js Generator Update the `baml_src/generators.baml` file to use the React/Next.js generator. **`baml_src/generators.baml`** ```diff title="baml_src/generators.baml" generator typescript { - output_type "typescript" + output_type "typescript/react" output_dir "../" version "0.76.2" } ``` ### Generate BAML Client **`npm`** ```bash npm npx baml-cli generate ``` **`pnpm`** ```bash pnpm pnpm exec baml-cli generate ``` **`yarn`** ```bash yarn yarn baml-cli generate ``` **`bun`** ```bash bun bun baml-cli generate ``` **`deno`** ```bash deno deno run --unstable-sloppy-imports -A npm:@boundaryml/baml/baml-cli generate ``` > **Note** > > If you need baml\_client to be 'ESM' compatible, you can add the following `generator` configuration to your `.baml` file: > > ```baml > generator typescript { > ... > module_format "esm" // the default is "cjs" for CommonJS > } > ``` ### Generated React Hooks BAML automatically generates type-safe Next.js server actions and React hooks for your BAML functions. **`baml_src/prompt.baml`** ```baml title="baml_src/prompt.baml" class Story { title string @stream.not_null content string @stream.not_null } function WriteMeAStory(input: string) -> Story { client "openai/gpt-5" prompt #" Tell me a story {{ ctx.output_format() }} {{ _.role("user") }} Topic: {{input}} "# } ``` **`Non-Streaming Example`** ```tsx title="Non-Streaming Example" 'use client' import { useWriteMeAStory } from "../../../baml_client/react/hooks"; import type { Story } from "@/baml_client/types"; export function StoryForm() { const writeMeAStory = useWriteMeAStory({ stream: false }); return (
{writeMeAStory.data && (

{writeMeAStory.data.title}

{writeMeAStory.data.content}

)} {writeMeAStory.error &&
Error: {writeMeAStory.error.message}
}
); } ``` **`Streaming Example`** ```tsx title="Streaming Example" 'use client' import { useWriteMeAStory } from "../../../baml_client/react/hooks"; import type { Story } from "@/baml_client/types"; export function StreamingStoryForm() { const writeMeAStory = useWriteMeAStory({ onStreamData: (partial) => { // Handle real-time updates console.log('Story in progress:', partial); }, onFinalData: (final) => { // Handle completed story console.log('Story completed:', final); } }); return (
{writeMeAStory.data && (

{writeMeAStory.data.title}

{writeMeAStory.data.content}

)} {writeMeAStory.error &&
Error: {writeMeAStory.error.message}
}
); } ``` ### Update Package Scripts Update your `package.json` scripts: ```json {3,4} { "scripts": { "prebuild": "npm run generate", "generate": "baml-cli generate", "dev": "next dev", "build": "next build", "start": "next start", } } ``` ## Reference Documentation For complete API documentation of the React/Next.js integration, see: ### Core Concepts * [Generated Hooks](/ref/baml_client/react-next-js/use-function-name-hook) - Auto-generated hooks for each BAML function ### Hook Configuration * [HookInput](/ref/baml_client/react-next-js/hook-input) - Configuration options for hooks * [HookOutput](/ref/baml_client/react-next-js/hook-output) - Return value types and states * [Error Types](/ref/baml_client/errors/overview) - Error handling and types ## Next Steps * Check out the [BAML Examples](https://github.com/BoundaryML/baml-examples/tree/main/nextjs-starter) for more use cases