BoilerplateHub

Nuxt + Supabase + Better Auth + Polar

Nuxt with Supabase, Better Auth and Polar keeps the application simple by keeping money out of it. Nitro handles checkout creation and webhooks, Better Auth handles identity inside Supabase Postgres, and Polar handles tax and invoicing. It suits a small Vue product selling digital access across borders.

Nuxt SupabaseBetter AuthPolar

Database

Supabase

With Polar as merchant of record the Supabase Postgres carries no money, only the consequences of it. Store the Polar customer ID beside the Better Auth user plus a benefits table refreshed by webhook, and let Nitro routes read it. Supabase Storage in the same project is a natural home for whatever a benefit unlocks, served through a server route that checks the benefit rather than through a public bucket URL anyone can share.

Authentication

Better Auth

Better Auth's Nuxt module surfaces the session in server middleware, which is where the entitlement lookup belongs so pages and API routes cannot disagree. Because the library owns its schema inside Supabase, adding a Polar customer column is a migration rather than a synchronisation problem. Use the Better Auth user ID as the external reference so a customer created during a checkout you did not initiate still resolves to a real account.

Payments

Polar

Polar's API-first design pairs well with Nitro, where creating a checkout and handling its webhook are two small event handlers. Tax, invoicing and the payer relationship all move across, which is a large amount of compliance removed for a percentage. Because your app never sees a card or a charge, any revenue reporting you build reads Polar's API rather than your own tables, and the two will not always agree at the same instant.

What to watch out for

useRuntimeConfig is the whole risk surface here. An access token or webhook secret placed under runtimeConfig.public is readable by anyone who opens the page source, and nothing in the framework warns you. The second issue is preset drift: a handler that receives a raw body on a Node server may not receive one on an edge preset, which breaks signature verification only after the deploy that changed the target.

Boilerplates close to this stack

Matched on Nuxt plus the parts of this stack our catalog tags. Each card shows which pieces actually line up, so you can see how much you would still wire yourself.

A CLAUDE.md for this stack

The rules that matter for this combination specifically, including who owns entitlement state. Adapt the commands to your repository before committing it.

CLAUDE.md
# CLAUDE.md

This project is a Nuxt SaaS on Supabase, Better Auth and Polar.

## Stack

- Framework: Nuxt
- Database: Supabase
- Auth: Better Auth
- Payments: Polar

## Boundaries

- Never edit a migration that has already run. Write a new one.
- Never hardcode Polar price or product identifiers in components. They belong in config.
- Never trust a client-supplied user id. Read the session from Better Auth on the server.
- Treat webhook handlers as idempotent. The same event will arrive twice.

## Entitlements

- Polar is the source of truth for what a customer paid for.
- The database mirrors that state; it never decides it.
- Any check for "can this user do X" reads the mirrored entitlement, not a live API call.

## Before you say a change is done

- The app builds.
- Tests pass.
- No secret, key or webhook signing secret appears in a committed file.

Related stacks