> 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