This guide walks you through the cleanest way to set up Spacerr: create the required provider accounts, copy the keys into .env.local, install dependencies, prepare the database, and run the app locally.
Project Setup
Prerequisites
Before you can get started, you will need to have the following installed on your machine.
- Bun
1.3.14or higher, or Node.js20.9.0or higher. - Git.
- Stripe CLI for local webhook testing.
- VS Code, Cursor, or another code editor.
The project uses Bun by default. You can switch to a Node package manager later by replacing the Bun commands in package.json.
Clone And Own The Repository
Accept the GitHub invite first, then clone the private repository with either SSH or HTTPS.
Use SSH if your GitHub SSH key is already configured.
git clone git@github.com:spaccerr/spacerr-kit-client.git my-spacerr-app
cd my-spacerr-appUse HTTPS if your terminal is authenticated with the GitHub account that accepted the invite.
git clone https://github.com/spaccerr/spacerr-kit-client.git my-spacerr-app
cd my-spacerr-appAfter cloning, treat the private Spacerr repository as the delivery source, not as the Git remote for your product work.
For a clean product repository, remove the cloned Git history and initialize your own repository.
rm -rf .git
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/your-org/my-spacerr-app.git
git push -u origin mainIf you want to keep a connection to the starter repository for future updates, keep it as upstream and use your own repository as origin.
git remote rename origin upstream
git remote add origin https://github.com/your-org/my-spacerr-app.git
git push -u origin mainIn both cases, your day to day commits and deployments should point at your own repository.
Create The Environment File
Create the local environment file from the example file before setting up providers.
cp .env.example .env.localEvery provider step below fills one block in .env.local. Start with the shared app values.
# Shared
NEXT_PUBLIC_DOMAIN="http://localhost:3000"
# Cron Jobs on Vercel
CRON_SECRET="replace-with-a-long-random-secret"NEXT_PUBLIC_DOMAIN is the base URL used by auth callbacks, Stripe redirects, metadata, and server generated links. Use http://localhost:3000 locally and your production domain after deployment.
CRON_SECRET protects scheduled routes. Run this command, then paste the generated value into that env variable.
openssl rand -base64 48The app validates required environment values and fails fast when a required key is missing.
Set Up Vercel Services
Sign in to Vercel, open your dashboard, choose your team, and create the services the app uses.
- Go to your Vercel project and connect it to the repository.
- Go to Storage and create one private Vercel Blob store for user files.
- Go to Storage and create one public Vercel Blob store for public assets.
- Go to Storage and create a Redis database. Copy the Redis connection URL.
- Go to AI Gateway, open API Keys, create a key, and copy it.
Copy these values into .env.local.
# Vercel
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_private_..."
BLOB_PUBLIC_READ_WRITE_TOKEN="vercel_blob_rw_..."
REDIS_URL="redis://default:password@host:port"
AI_GATEWAY_API_KEY="your-ai-gateway-key"Use BLOB_READ_WRITE_TOKEN for the private Blob store. It stores user owned files such as chat attachments, project sources, generated images, avatars, and the private library.
Use BLOB_PUBLIC_READ_WRITE_TOKEN for the public Blob store. It stores public assets such as blog cover images.
Use REDIS_URL for active stream coordination and fast runtime state.
Use AI_GATEWAY_API_KEY for the Vercel AI Gateway model layer.
Set Up Neon
Sign in to Neon, create a Postgres project, and copy both connection strings. The Database section explains why Neon is the default and how to switch providers later.
- Copy the pooled connection string for
DATABASE_URL. - Copy the direct connection string for
DIRECT_URL.
Paste the values into .env.local.
# Neon
DATABASE_URL="postgresql://user:password@host/database?sslmode=require"
DIRECT_URL="postgresql://user:password@host/database?sslmode=require"Both values are required for the database workflow.
Set Up Better Auth And Google OAuth
Authentication comes with Google OAuth, email and password sign in, magic links, two factor authentication, and passkeys.
Better Auth needs one app secret, one passkey relying party id, and Google OAuth credentials.
Generate a long random secret.
openssl rand -base64 48Add the Better Auth values to .env.local.
# Better Auth
BETTER_AUTH_SECRET="replace-with-a-long-random-secret"
BETTER_AUTH_PASSKEY_RP_ID=localhostUse localhost for BETTER_AUTH_PASSKEY_RP_ID in local development. In production, use your domain without the protocol, for example example.com.
Create Google OAuth credentials in Google Cloud Console.
Open Google Cloud Console → APIs & Services → Credentials → Create Credentials → OAuth client ID → Web application.
In that form, add the authorized JavaScript origins and authorized redirect URIs.
Use this authorized JavaScript origin for local development.
http://localhost:3000Use your application domain for production.
https://your-domain.comUse this redirect URI for local development.
http://localhost:3000/api/auth/callback/googleUse your application domain for production.
https://your-domain.com/api/auth/callback/googleIf you change the Better Auth route base path, update the Google redirect URI to match it. This avoids redirect_uri_mismatch errors.
Copy the Google OAuth values into .env.local.
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"Set Up Resend Email
Sign in to Resend and create an API key for transactional emails.
# Resend Email
RESEND_API_KEY="re_your_key"
RESEND_FROM_EMAIL="Spacerr <hello@yourdomain.com>"
SUPPORT_EMAIL="support@yourdomain.com"RESEND_API_KEY sends transactional emails. RESEND_FROM_EMAIL is the sender shown in inboxes. SUPPORT_EMAIL is the address users see when they need help.
For production, verify your sending domain before sending real email. Follow the Resend domain verification docs.
Set Up Stripe
Sign in to Stripe, use test mode, and copy the required keys into .env.local.
Open Stripe Dashboard → Product Catalog → Create product. Create one recurring monthly price, one recurring yearly price, and a one time payment price. Copy each Stripe Price ID. Price IDs start with price_.
# Stripe
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_PRICE_ID_MONTHLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_YEARLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_ONE_TIME="price_..."Stripe checkout sessions are created on the server, so the default kit needs the server secret key and Price IDs. Use Stripe Price IDs that start with price_, not Stripe Product IDs that start with prod_. STRIPE_PRICE_ID_MONTHLY_SUBSCRIPTION points to your monthly subscription price. STRIPE_PRICE_ID_YEARLY_SUBSCRIPTION points to your yearly subscription price. STRIPE_PRICE_ID_ONE_TIME points to your one time payment price.
For local checkout testing, the app must receive Stripe webhook events. These events confirm purchases, update billing access, and keep local Stripe state in sync with your database.
Install the Stripe CLI if it is not already installed. On macOS with Homebrew, use Stripe's official Homebrew package.
brew install stripe/stripe-cli/stripeFor Windows, Linux, Docker, or direct binary installs, follow the Stripe CLI install docs. After installation, authenticate the Stripe CLI with your Stripe account.
stripe loginThen run the local webhook listener in a separate terminal.
bun stripe:listenThe listener forwards Stripe events to the local Better Auth Stripe webhook endpoint.
localhost:3000/api/auth/stripe/webhookAfter the listener starts, Stripe CLI prints a webhook signing secret that begins with whsec_. Copy that value into .env.local.
STRIPE_WEBHOOK_SECRET="whsec_..."Set Up Pusher Realtime
Sign in to Pusher and create an app for realtime chat updates.
Pusher lets the dashboard update instantly when chats, streams, notifications, and sidebar state change across browser tabs or devices.
# Pusher Realtime
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_SECRET="your-pusher-secret"
NEXT_PUBLIC_PUSHER_KEY="your-pusher-key"
NEXT_PUBLIC_PUSHER_CLUSTER="your-pusher-cluster"PUSHER_APP_ID and PUSHER_SECRET are server values. NEXT_PUBLIC_PUSHER_KEY and NEXT_PUBLIC_PUSHER_CLUSTER are used by the browser to receive realtime updates.
Set Up PostHog Analytics
Sign in to PostHog and create a project for analytics.
# Posthog
NEXT_PUBLIC_ANALYTICS_TRACKING="on"
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN="phc_..."
NEXT_PUBLIC_POSTHOG_HOST="https://us.i.posthog.com"Use NEXT_PUBLIC_ANALYTICS_TRACKING="on" when you want analytics enabled. Use the PostHog host that matches your project region.
Review The Environment File
At this point, your .env.local should be grouped like this.
# Shared
NEXT_PUBLIC_DOMAIN="http://localhost:3000"
# Posthog
NEXT_PUBLIC_ANALYTICS_TRACKING="on"
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN="phc_..."
NEXT_PUBLIC_POSTHOG_HOST="https://us.i.posthog.com"
# Vercel
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_private_..."
BLOB_PUBLIC_READ_WRITE_TOKEN="vercel_blob_rw_..."
REDIS_URL="redis://default:password@host:port"
AI_GATEWAY_API_KEY="your-ai-gateway-key"
# Pusher Realtime
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_SECRET="your-pusher-secret"
NEXT_PUBLIC_PUSHER_KEY="your-pusher-key"
NEXT_PUBLIC_PUSHER_CLUSTER="your-pusher-cluster"
# Neon
DATABASE_URL="postgresql://user:password@host/database?sslmode=require"
DIRECT_URL="postgresql://user:password@host/database?sslmode=require"
# Better Auth
BETTER_AUTH_SECRET="replace-with-a-long-random-secret"
BETTER_AUTH_PASSKEY_RP_ID=localhost
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
# Resend Email
RESEND_API_KEY="re_your_key"
RESEND_FROM_EMAIL="Spacerr <hello@yourdomain.com>"
SUPPORT_EMAIL="support@yourdomain.com"
# Stripe
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
STRIPE_PRICE_ID_MONTHLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_YEARLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_ONE_TIME="price_..."
# Cron Jobs on Vercel
CRON_SECRET="replace-with-a-long-random-secret"Install And Prepare The Database
Install dependencies first.
bun installThen prepare the local database.
bun db:generate
bun db:migrateSee the Database section for the detailed database workflow.
Run The App Locally
Start the Next.js development server.
bun run devOpen the local app.
http://localhost:3000For local billing tests, keep two terminals running.
# Terminal 1
bun stripe:listen
# Terminal 2
bun run devCreate An Admin User
Create a user through the normal sign up flow first. Then promote that user to admin by setting the user's role field to admin in the database. The Database section covers the recommended ways to inspect and edit database records.
The admin dashboard is available at:
http://localhost:3000/dashboard/admin