Skip to content

Next.js

This guide shows how to integrate Butterbase into a Next.js application (static export) using the @butterbase/sdk.

  1. Create a Next.js project

    Terminal window
    npx create-next-app@latest my-app --typescript --app
    cd my-app
  2. Install the SDK

    Terminal window
    npm install @butterbase/sdk
  3. Create a Butterbase client

    src/lib/butterbase.ts
    import { createClient } from '@butterbase/sdk';
    export const butterbase = createClient({
    appId: process.env.NEXT_PUBLIC_BUTTERBASE_APP_ID!,
    apiUrl: process.env.NEXT_PUBLIC_BUTTERBASE_API_URL!,
    });
  4. Set up environment variables

    .env.local
    NEXT_PUBLIC_BUTTERBASE_APP_ID=app_abc123
    NEXT_PUBLIC_BUTTERBASE_API_URL=https://api.butterbase.ai
  5. Build a page with data fetching

    src/app/page.tsx
    'use client';
    import { useEffect, useState } from 'react';
    import { butterbase } from '@/lib/butterbase';
    interface Post {
    id: string;
    title: string;
    body: string;
    created_at: string;
    }
    export default function Home() {
    const [posts, setPosts] = useState<Post[]>([]);
    const [loading, setLoading] = useState(true);
    useEffect(() => {
    async function load() {
    const { data } = await butterbase
    .from<Post>('posts')
    .select('*')
    .eq('published', true)
    .order('created_at', { ascending: false });
    if (data) setPosts(data);
    setLoading(false);
    }
    load();
    }, []);
    if (loading) return <p>Loading...</p>;
    return (
    <main>
    <h1>Posts</h1>
    {posts.map((post) => (
    <article key={post.id}>
    <h2>{post.title}</h2>
    <p>{post.body}</p>
    </article>
    ))}
    </main>
    );
    }
  6. Add authentication

    src/app/login/page.tsx
    'use client';
    import { useState } from 'react';
    import { useRouter } from 'next/navigation';
    import { butterbase } from '@/lib/butterbase';
    export default function LoginPage() {
    const router = useRouter();
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');
    const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const { data, error } = await butterbase.auth.signIn({ email, password });
    if (error) setError(error.message);
    else router.push('/');
    };
    return (
    <form onSubmit={handleSubmit}>
    <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
    <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
    {error && <p style={{ color: 'red' }}>{error}</p>}
    <button type="submit">Sign In</button>
    </form>
    );
    }
  7. Deploy as static export

    Add to next.config.js:

    /** @type {import('next').NextConfig} */
    const nextConfig = {
    output: 'export',
    };
    module.exports = nextConfig;

    Build and deploy:

    Terminal window
    npm run build
    # Zip the out/ folder
    cd out && zip -r ../frontend.zip .

    Then use Butterbase’s frontend deployment tools with framework: "nextjs-static".

For OAuth sign-in, create a callback page:

src/app/auth/callback/page.tsx
'use client';
import { useEffect } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { butterbase } from '@/lib/butterbase';
export default function AuthCallback() {
const router = useRouter();
const searchParams = useSearchParams();
useEffect(() => {
const accessToken = searchParams.get('access_token');
const refreshToken = searchParams.get('refresh_token');
if (accessToken && refreshToken) {
// Store the session — the SDK handles this automatically
// if you parse the tokens from the URL
router.push('/');
}
}, [searchParams, router]);
return <p>Signing in...</p>;
}