Back to Blog
technology7 min read

Building AI SaaS with Next.js and Supabase: What Actually Works

A practical, no-fluff tutorial for developers on building and launching an AI SaaS. I'll show you the exact stack, code patterns, and tools I use, from server actions to vector embeddings with pgvector.

AI Opportunity FinderJune 13, 2026

The fastest way to ship an AI SaaS is by ruthlessly avoiding complexity. For solo developers or small teams, the modern default stack is Next.js and Supabase for a reason: it gets you from idea to paying customers faster than anything else I've tried. You can focus on the product and the AI, not on managing a fleet of microservices or wrestling with DevOps.

I've seen too many developers get bogged down trying to stitch together five different services before they've even validated their idea. This stack prevents that. It’s a monolith, and for a startup, that’s a feature, not a bug.

The Core Stack: Next.js App Router and Supabase

Your foundation should be simple and powerful. Forget about separate backends, frontends, and databases in different repos. Combine them.

Next.js with the App Router is the clear winner for the frontend and server logic. Server Components are the key here. They let you run async code, like fetching data or calling an AI model, directly inside your component file without shipping that logic to the client. This means your API keys stay secret and your app feels faster because you're not making client-side request waterfalls.

Supabase is your backend-in-a-box. It's not just a Postgres database. It’s authentication, file storage, and serverless functions (Edge Functions) rolled into one cohesive package. Their free tier is more than enough to build your MVP and get your first users. I ran my first project for months on the free tier before needing to upgrade to the Pro plan ($25/month).

Getting started is straightforward. No complex Docker setups needed.

  1. Initialize your Next.js app:
    npx create-next-app@latest my-ai-saas
    
  2. Set up Supabase: Create a project on supabase.com. Then, install the required packages in your Next.js project.
    npm install @supabase/supabase-js @supabase/ssr
    
  3. Connect them: Use the @supabase/ssr package to create a client that works in both client and server components. You'll create this in a lib/supabase/server.ts file, for example. The official Supabase docs have a fantastic guide on this that I follow for every new project.

This setup gives you a full-stack application with a database and auth in about 15 minutes.

Handling AI Logic: Server Actions vs. Edge Functions

Your core AI logic needs a place to live. You have two excellent options within this stack, and choosing the right one matters.

Next.js Server Actions should be your default. They are functions you define on the server but can call from client components as if they were regular functions. This massively simplifies state management and eliminates the need for manual API endpoint creation.

For an AI SaaS, this is perfect. A user clicks a button, a Server Action runs, calls the OpenAI (or Anthropic, or Cohere) API, and streams the response back to the UI. It's one logical flow.

Here’s a simplified Server Action for summarizing text:

// app/actions.ts
'use server'

import OpenAI from 'openai';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export async function summarizeText(text: string) {
  if (!text) return { error: 'Text is required.' };

  try {
    const response = await openai.chat.completions.create({
      model: 'gpt-4o',
      messages: [
        { role: 'system', content: 'You are a helpful assistant that summarizes text.' },
        { role: 'user', content: `Summarize the following text: ${text}` },
      ],
    });
    return { summary: response.choices[0].message.content };
  } catch (error) {
    console.error(error);
    return { error: 'Failed to summarize text.' };
  }
}

Supabase Edge Functions are better for two things: database-intensive webhooks and long-running background jobs. Since Edge Functions run physically close to your database, they have extremely low latency for DB queries. A great example is a tool like pdf.ai, which needs to process an uploaded PDF, chunk it, generate embeddings, and store them. This is a perfect job for a Supabase Edge Function triggered by a file upload to Supabase Storage.

Running your AI model calls from a server-side environment (Vercel's servers are in us-east-1, same as OpenAI's) can also reduce latency. I've seen round-trip times drop by over 300ms just by moving the API call from the client (in Europe) to the server (in US East).

Database and Vector Embeddings: pgvector is All You Need

Many AI apps need to implement Retrieval-Augmented Generation (RAG) for custom data Q&A. This requires a vector database to store embeddings. New founders often think they need a specialized service like Pinecone from day one. You don't.

Supabase includes the pgvector extension for Postgres. It's incredibly capable and will easily handle your first few million vectors without breaking a sweat. This keeps your architecture simple and your costs down.

Here’s the workflow:

  1. Enable the extension: In your Supabase SQL Editor, run CREATE EXTENSION vector;
  2. Create a table:
    CREATE TABLE documents (
      id bigserial PRIMARY KEY,
      content text,
      embedding vector(1536) -- 1536 for OpenAI's text-embedding-ada-002
    );
    
  3. Generate and store embeddings: Use a Supabase Edge Function or a Next.js Server Action to take text, call the OpenAI Embeddings API, and save the resulting vector to your documents table.
  4. Query for similar documents: Create a database function to perform a cosine similarity search.
    -- Create a function to search for documents
    create function match_documents (query_embedding vector(1536), match_threshold float, match_count int)
    returns table (id bigint, content text, similarity float)
    language sql stable
    as $$
      select
        documents.id,
        documents.content,
        1 - (documents.embedding <=> query_embedding) as similarity
      from documents
      where 1 - (documents.embedding <=> query_embedding) > match_threshold
      order by similarity desc
      limit match_count;
    $$;
    

Now you can call this function from your app using Supabase's client library to find relevant context before calling the chat model. I use this exact pattern for oppfinder.app to find similar business ideas based on semantic meaning, and it scales perfectly well.

Authentication, Subscriptions, and Deployment

An AI tool isn't a SaaS until you can charge for it.

Authentication: Supabase Auth is the only answer here. It’s built-in, supports social logins, and has helper libraries that make protecting pages in Next.js trivial. Use the middleware pattern to protect routes.

Subscriptions: Don't build your own billing logic. Use Stripe. You can trigger Stripe Checkout from a Server Action. To sync subscription status back to your database, use Stripe webhooks. You can create a simple Next.js API route or a Supabase Edge Function to act as the webhook endpoint. It receives an event from Stripe (e.g., checkout.session.completed) and updates the user's profile in your Supabase table (UPDATE public.profiles SET plan = 'pro' WHERE ...). For an even simpler solution, check out Lemon Squeezy, which is popular with solo developers for its handling of global sales tax.

Deployment: Vercel for the Next.js app. Supabase for the backend. It's the path of least resistance. Vercel's free tier is great for testing, and the Pro plan ($20/month) is all you need to handle a real product. The git push to deploy workflow is undefeated.

This entire stack lets you operate like a much larger team. Your goal is to ship a product that solves a problem, not to build a perfectly distributed system. Start with this simple, powerful monolith. You can always break it apart later if you're lucky enough to have that problem.

Your takeaway: Build a 'YouTube Video Summarizer' this weekend. Use Supabase Auth to protect the page. Create a form that takes a YouTube URL. Use a Server Action to fetch the transcript, send it to an LLM for summarization, and display the result. You'll be surprised how much you can build in a few hours with this stack.


Related Resources:

nextjssupabaseai-saastutorialpgvector