Hoppa till innehåll
Vercel AI SDK · Supabase · Anthropic Claude · Tutorial

Vercel AI SDK + Supabase + Claude - fullstack AI-app på 4 timmar

En arbetsmodell för att bygga en produktionsklar AI-app med chat, lagrad historik, autentisering och realtidsstreaming på en eftermiddag. Stack: Next.js 16, Vercel AI SDK, Supabase, Claude.

~11 min läsningUppdaterad 2026Simon Axelsson
01

Varför just denna stack

Stacken är vald för en specifik egenskap: minimal overhead för produktionsklara AI-appar. Vercel AI SDK abstraherar streaming och multi-modell-stöd. Supabase löser auth, databas och realtid utan egen backend. Claude (eller GPT-4 - SDK:t är agnostiskt) ger modellen.

Räkna med 4 timmar för en MVP, 2 dagar för en putsad version, 2 veckor för en produktionsklar app med evals och övervakning.

02

Vad ska byggas

En chatbaserad AI-app med:

  • • Inloggning (Supabase Auth - magic links)
  • • Persisterad chatthistorik per användare (Supabase Postgres)
  • • Realtidsstreaming av AI-svar (Vercel AI SDK useChat)
  • • Anthropic Claude som modell
  • • Deploy på Vercel
03

Steg 1: Skapa projektet (10 min)

pnpm create next-app@latest siax-chat --typescript --tailwind --app
cd siax-chat
pnpm add ai @ai-sdk/anthropic @supabase/ssr @supabase/supabase-js

Skapa Vercel-projekt + Supabase-projekt. Kopiera Supabase URL och anon key till .env.local. Lägg ANTHROPIC_API_KEY där också.

04

Steg 2: Databas-schema (15 min)

-- I Supabase SQL editor:
create table conversations (
  id uuid primary key default gen_random_uuid(),
  user_id uuid references auth.users(id) not null,
  title text,
  created_at timestamptz default now()
);

create table messages (
  id uuid primary key default gen_random_uuid(),
  conversation_id uuid references conversations(id) on delete cascade,
  role text check (role in ('user', 'assistant')),
  content text not null,
  created_at timestamptz default now()
);

-- Row-level security: en användare ser bara sina egna konversationer
alter table conversations enable row level security;
create policy "own conversations" on conversations
  for all using (auth.uid() = user_id);

alter table messages enable row level security;
create policy "messages via own conversations" on messages
  for all using (
    conversation_id in (
      select id from conversations where user_id = auth.uid()
    )
  );
05

Steg 3: Auth (30 min)

Supabase Auth med magic link. Skapa app/login/page.tsx med en input + submit-knapp som anropar supabase.auth.signInWithOtp. Lägg middleware.ts som kollar session och redirectar till /login om inte inloggad.

Officiell Supabase Next.js App Router-mall finns och tar 15 minuter att integrera.

06

Steg 4: AI route handler (45 min)

// app/api/chat/route.ts
import { streamText } from 'ai'
import { anthropic } from '@ai-sdk/anthropic'
import { createClient } from '@/lib/supabase/server'

export async function POST(req: Request) {
  const supabase = await createClient()
  const { data: { user } } = await supabase.auth.getUser()
  if (!user) return new Response('Unauthorized', { status: 401 })

  const { messages, conversationId } = await req.json()

  const result = streamText({
    model: anthropic('claude-3-5-sonnet-20241022'),
    system: 'Du är en hjälpsam svensk teknisk assistent.',
    messages,
    onFinish: async ({ text }) => {
      // Persistera båda meddelandena i Supabase
      const lastUser = messages.at(-1)
      await supabase.from('messages').insert([
        { conversation_id: conversationId, role: 'user', content: lastUser.content },
        { conversation_id: conversationId, role: 'assistant', content: text },
      ])
    },
  })

  return result.toDataStreamResponse()
}
07

Steg 5: UI-komponent (45 min)

// app/chat/[id]/page.tsx
'use client'
import { useChat } from 'ai/react'

export default function Chat({ params }: { params: { id: string }}) {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: '/api/chat',
    body: { conversationId: params.id },
  })

  return (
    <div className="max-w-2xl mx-auto p-6">
      <div className="space-y-4 mb-6">
        {messages.map((m) => (
          <div key={m.id} className="flex gap-3">
            <span className="font-mono text-xs text-muted-foreground">
              {m.role === 'user' ? 'Du' : 'AI'}
            </span>
            <p className="text-sm">{m.content}</p>
          </div>
        ))}
      </div>
      <form onSubmit={handleSubmit} className="flex gap-2">
        <input value={input} onChange={handleInputChange}
               className="flex-1 border px-3 py-2" />
        <button className="border px-4 py-2">Skicka</button>
      </form>
    </div>
  )
}

useChat hanterar streaming, optimistisk UI och felhantering automatiskt. För produktion lägg till markdown-rendering, kopiera-knappar och felmeddelanden.

08

Steg 6: Deploy (10 min)

vercel deploy --prod

Lägg env-vars i Vercel-projektinställningar. Klart. Realtidschat live på er Vercel-domän.

09

Vad behöver mer för produktion

  • • Rate-limiting per användare (Upstash Redis eller Supabase Edge Functions)
  • • Felhantering - vad händer när Claude-API:t är nere?
  • • Token-tracking och kostnadsmonitorering
  • • Evals - testa output-kvalitet mot en golden dataset
  • • Multi-modell-fallback (Claude → GPT-4 vid rate-limit)
  • • Streaming-felhantering på klientsidan
FAQ

Vanliga frågor

Nästa steg

Behöver ni hjälp att ta er AI-app till produktion?

Tjänsten AI Engineering bygger appar enligt den här stacken och tar dem hela vägen till produktion - med evals, observability och guardrails.
Läs om tjänsten