Configuration

Set up sign-in and payments

Create the Google, GitHub, and Polar credentials your project needs, and put each half in the right place.

apps/web signs users in with Google and GitHub, and charges them through Polar. Each provider gives you two things: a public identifier that goes into Git, and a secret that goes into your secret store.

Every key below is required, so apps/web doesn't start until each one holds a value. If you aren't using a provider yet, put REPLACE_ME in its keys and come back later. The product starts, and only that provider's feature fails when you first use it.

Where each value goes

KeyNeeded forGoes in
GOOGLE_CLIENT_IDGoogle sign-in (@app/layer-auth)apps/web/.env.<context>, in Git
GOOGLE_CLIENT_SECRETGoogle sign-in (@app/layer-auth)Your secret store
GITHUB_CLIENT_IDGitHub sign-in (@app/layer-auth)apps/web/.env.<context>, in Git
GITHUB_CLIENT_SECRETGitHub sign-in (@app/layer-auth)Your secret store
POLAR_ACCESS_TOKENPayments (@app/layer-payments)Your secret store
NUXT_WEBHOOK_POLAR_SECRET_KEYPayments (@app/layer-payments)Your secret store

POLAR_SERVER picks the Polar environment. It's already set in every value file, so it needs nothing from you until you go live.

Set up your secret store covers which folder the secrets go in. Environment values explains why the client IDs are committed instead.

Register these callback URLs

Create a separate OAuth application and a separate Polar organization for each context you deploy. Each one has a different origin, and a callback URL is registered per exact URL.

For local development, the origin is http://localhost:3000. For a deployed context, it's the NUXT_PUBLIC_APP_BASE_URL you wrote into that context's apps/web/.env.<context>Project identity explains the shape each one takes.

A pull request preview gets a different origin per pull request, so no callback URL can be registered for it in advance. Social sign-in fails on a preview, and that's expected.
ProviderCallback URL
Google<origin>/api/auth/callback/google
GitHub<origin>/api/auth/callback/github
Polar<origin>/api/webhooks/polar (webhook endpoint)

Google

Create an OAuth 2.0 client ID of type Web application in the Google Cloud console, under APIs & Services > Credentials. Add http://localhost:3000/api/auth/callback/google as an authorized redirect URI.

Google's OAuth 2.0 setup guide covers the consent screen and publishing.

The console gives you a client ID and a client secret. Put the ID in apps/web/.env.development and the secret in your secret store.

GitHub

Create an OAuth app under Settings > Developer settings > OAuth Apps, and set the authorization callback URL to http://localhost:3000/api/auth/callback/github. See GitHub's guide to creating an OAuth app.

GitHub shows the client ID immediately and generates the client secret on request. The secret is shown once.

Polar

Use the Polar sandbox for everything except production. A token issued by one Polar environment doesn't work against the other, and the mismatch surfaces at the first API call rather than at startup — so check which dashboard you're in before copying a token.

The two credentials come from two different pages:

  1. POLAR_ACCESS_TOKEN — create an organization access token under Settings > Developer. See Polar authentication.
  2. NUXT_WEBHOOK_POLAR_SECRET_KEY — add a webhook pointing at <origin>/api/webhooks/polar, then copy the signing secret from that webhook's own settings page. It isn't the access token, and the developer settings page doesn't show it.

Requests whose signature doesn't verify against the webhook secret are rejected, so a wrong value looks like Polar events silently never arriving.

A webhook needs a URL Polar can reach, and http://localhost:3000 isn't one. To receive events locally, expose your dev server through a tunnel and set NUXT_DEV_TUNNEL_HOST in apps/web/.env.local to the tunnel's hostname, so the dev server accepts the requests. Everything except webhook delivery works without one.

Next steps

Copyright © 2026