Corsair
Integrations

Next.js

Integrate Corsair with Next.js App Router and Pages Router

Next.js

Corsair integrates seamlessly with Next.js App Router and Pages Router.

Installation

npm install corsair
npx corsair init --framework next

App Router Setup

API Route

Create the Corsair API route:

app/api/corsair/route.ts
import { corsair } from '@/lib/corsair'

export async function POST(req: Request) {
  return corsair.handle(req)
}

export const runtime = 'nodejs'

Client Setup

Configure the client provider:

app/providers.tsx
'use client'

import { CorsairProvider, createCorsairClient } from 'corsair/client'

const corsairClient = createCorsairClient({
  apiUrl: '/api/corsair',
})

export function Providers({ children }: { children: React.ReactNode }) {
  return <CorsairProvider client={corsairClient}>{children}</CorsairProvider>
}

Wrap your app:

app/layout.tsx
import { Providers } from './providers'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

Server Components

Use Corsair in Server Components:

app/posts/page.tsx
import { corsair } from '@/lib/corsair'

export default async function PostsPage() {
  const posts = await corsair.query('all published posts with authors')

  return (
    <div>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>By {post.author.name}</p>
        </article>
      ))}
    </div>
  )
}

Client Components

Use hooks in Client Components:

app/posts/create-post.tsx
'use client'

import { useCorsairMutation } from 'corsair/client'

export function CreatePost() {
  const { mutate: createPost, isPending } = useCorsairMutation('create post')

  return (
    <form
      onSubmit={e => {
        e.preventDefault()
        const formData = new FormData(e.currentTarget)
        createPost({
          title: formData.get('title'),
          content: formData.get('content'),
        })
      }}
    >
      <input name="title" />
      <textarea name="content" />
      <button disabled={isPending}>Create</button>
    </form>
  )
}

Server Actions

Use Corsair with Server Actions:

app/posts/actions.ts
'use server'

import { corsair } from '@/lib/corsair'
import { revalidatePath } from 'next/cache'

export async function createPost(formData: FormData) {
  const post = await corsair.mutate('create post', {
    title: formData.get('title'),
    content: formData.get('content'),
  })

  revalidatePath('/posts')
  return post
}

Use in components:

app/posts/create-post.tsx
import { createPost } from './actions'

export function CreatePost() {
  return (
    <form action={createPost}>
      <input name="title" />
      <textarea name="content" />
      <button>Create</button>
    </form>
  )
}

Streaming

Stream data with Suspense:

app/posts/page.tsx
import { Suspense } from 'react'
import { corsair } from '@/lib/corsair'

async function Posts() {
  const posts = await corsair.query('all posts')
  return <PostList posts={posts} />
}

export default function PostsPage() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Posts />
    </Suspense>
  )
}

Middleware

Add authentication middleware:

middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/api/corsair')) {
    const session = request.cookies.get('session')

    if (!session) {
      return new NextResponse('Unauthorized', { status: 401 })
    }
  }

  return NextResponse.next()
}

Environment Variables

.env.local
DATABASE_URL="postgresql://..."
NEXT_PUBLIC_API_URL="/api/corsair"

Pages Router (Legacy)

For Pages Router, set up similarly:

pages/api/corsair.ts
import { corsair } from '@/lib/corsair'
import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' })
  }

  return corsair.handle(req, res)
}