OvenLovin

Self-Hosting Guide

Environment Variables

OvenLovin requires the following environment variables to function. Set these in your hosting platform or .env.local file for local development.

VariableRequiredDescriptionWhere to Get
DATABASE_URLYesPostgreSQL connection stringNeon Console or your database provider
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYYesClerk publishable key for authenticationClerk Dashboard → API Keys
CLERK_SECRET_KEYYesClerk secret key for server-side authClerk Dashboard → API Keys
BLOB_READ_WRITE_TOKENYesVercel Blob storage token for recipe photos and OCRVercel Storage → Create Blob Store
AI_GATEWAY_API_KEYNoOptional API key for local or non-Vercel hosts. On Vercel, AI Gateway authenticates with OIDC (VERCEL_OIDC_TOKEN)Vercel AI Gateway
USDA_FDC_API_KEYNoReserved for FoodData Central nutrition (not read today). Not required to deployFoodData Central
NEXT_PUBLIC_INSTANCE_NAMENoName shown on the landing page (defaults to Your OvenLovin)Set this so the deployed site feels like yours
OVENLOVIN_VERCEL_TEAM_SLUGNoVercel team/account slug for landing-page dashboard links. This is not the GitHub owner (tbarho vs ty-barho)Vercel dashboard URL: vercel.com/<team-slug>/...
OVENLOVIN_VERCEL_PROJECT_SLUGNoVercel project slug if it differs from the git repo nameVercel project settings
VERCEL_TOKEN / OVENLOVIN_VERCEL_TOKENNoOptional token to resolve team/project slugs from VERCEL_PROJECT_ID when the overrides are unset. Without slugs or a token, links fall back to https://vercel.com/dashboardVercel account tokens
RK_MODEL_DEFAULTNoPaste-import model (default: deepseek/deepseek-v4.1-flash)N/A - set custom model
RK_MODEL_VISIONNoPhoto-import vision model (default: deepseek/deepseek-v4.1-flash)N/A - set custom model
RK_MODEL_EXTRACTNoURL-import text model after JSON-LD/HTML miss. Falls back to RK_MODEL_DEFAULT, then DeepSeek. DeepSeek failures retry openai/gpt-6-lunaN/A - set custom model
RECIPE_IMPORT_CACHE_FALLBACKNoSet 0 to skip public copies (Google Translate, then Jina Reader). Default on. No API keyN/A

Getting API Keys

Neon (Database)

  1. Sign up at console.neon.tech
  2. Create a new project
  3. Copy the connection string (starts with postgresql://)
  4. Set as DATABASE_URL

Clerk (Authentication)

  1. Sign up at dashboard.clerk.com
  2. Create a new application
  3. Go to API Keys in the sidebar
  4. Copy:
    • Publishable Key → NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
    • Secret Key → CLERK_SECRET_KEY

Vercel Blob (Storage)

  1. Go to vercel.com/dashboard/stores
  2. Click Create Database → Blob
  3. Name your store (e.g., ovenlovin-uploads)
  4. Copy the Read Write Token → BLOB_READ_WRITE_TOKEN

Vercel AI Gateway

On a Vercel deployment, AI Gateway authenticates with OIDC automatically. You do not need AI_GATEWAY_API_KEY.

For local development or a non-Vercel host:

  1. Follow the Vercel AI Gateway setup guide
  2. Create a key, or run vercel env pull to get VERCEL_OIDC_TOKEN
  3. Set AI_GATEWAY_API_KEY only if you are not using OIDC

USDA FoodData Central

  1. Go to fdc.nal.usda.gov/api-key-signup.html
  2. Sign up for a free API key
  3. Set as USDA_FDC_API_KEY

Deploy to Vercel

The fastest way to deploy OvenLovin is using Vercel's one-click deployment.

One-Click Deploy

Deploy with Vercel

The one-click deploy will:

  1. Fork the repository to your GitHub account
  2. Create a new Vercel project
  3. Provision Neon Postgres, Vercel Blob, and Clerk (auto-configures DATABASE_URL, the blob token, and Clerk keys)
  4. Prompt for optional NEXT_PUBLIC_INSTANCE_NAME (USDA is optional; AI Gateway uses OIDC on Vercel)
  5. Run database migrations during the build
  6. Deploy the Next.js application

If the Clerk store is not offered in the clone flow, set NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY in the Vercel project.

Manual Vercel Deploy

If you prefer to deploy manually:

# Clone the repository
git clone https://github.com/tbarho/ovenlovin.git
cd ovenlovin
 
# Install Vercel CLI
pnpm add -g vercel
 
# Link to Vercel project
vercel link
 
# Set environment variables
vercel env add DATABASE_URL
vercel env add NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
vercel env add CLERK_SECRET_KEY
vercel env add BLOB_READ_WRITE_TOKEN
vercel env add USDA_FDC_API_KEY
# AI_GATEWAY_API_KEY is optional - Vercel OIDC covers the gateway
 
# Deploy
vercel --prod

Neon Database Setup

OvenLovin uses Neon as the recommended PostgreSQL provider for serverless deployments.

Create Database

  1. Sign up at console.neon.tech
  2. Click Create Project
  3. Choose:
    • Name: ovenlovin
    • Region: closest to your users
    • PostgreSQL Version: 16 or later
  4. Click Create Project

Get Connection String

After project creation:

  1. Go to Dashboard → Connection Details
  2. Copy the connection string:
    postgresql://user:password@ep-xyz.region.aws.neon.tech/neondb
  3. Add to your environment variables as DATABASE_URL

For automatic configuration:

  1. In Vercel project settings, go to Integrations
  2. Add Neon integration
  3. Authorize and connect your Neon project
  4. DATABASE_URL will be automatically configured

Clerk Organizations Setup

OvenLovin uses Clerk Organizations to represent households. Each household is a Clerk Organization.

Enable Organizations

  1. Go to dashboard.clerk.com
  2. Select your application
  3. Go to Configure → Organizations
  4. Toggle Enable Organizations
  5. Configure:
    • Organization Name: Required
    • Roles: Keep default (admin, member)
    • Permissions: Default settings work well

Organization Settings

Recommended settings:

  • Maximum organizations per user: 5 (one person can be in multiple households)
  • Allow members to leave: Yes
  • Require admin approval for new members: No (family invitations)
  • Delete organization when last admin leaves: Yes

Domain Restrictions

For families, you typically want:

  • Domains: None (allow any email)
  • Verified domains: Not required

Going to production with Clerk

Clerk development instances (pk_test_...) rely on a cross-site handshake that can loop forever in browsers that block third-party cookies (Safari tracking prevention, private tabs, in-app browsers). Use a production instance (pk_live_...) for real users. See Clerk's production deployment guide.

  1. Create the production instance in the Clerk Dashboard. It needs a custom domain you own - not *.vercel.app.
  2. Add every DNS record shown on the Clerk Domains page: the clerk., accounts., clkmail., clk._domainkey., and clk2._domainkey. CNAMEs. On Cloudflare, set them to DNS only (not proxied).
  3. Configure social providers (for example Google) with your own OAuth credentials. Production does not use Clerk's shared dev credentials.
  4. In Vercel Production env vars, replace NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY with the production keys, then redeploy.

Paths settings do not copy over from development. OvenLovin sends sign-in and sign-up to its own /sign-in and /sign-up pages by default, so nothing to configure there. Override with NEXT_PUBLIC_CLERK_SIGN_IN_URL / NEXT_PUBLIC_CLERK_SIGN_UP_URL if needed.

Carry existing kitchens over

Users and sessions do not carry over from development - everyone signs up again and gets a new Clerk user id. OvenLovin keys user rows by Clerk user id (user.clerk_user_id), so remap each existing person before they first sign in on production. Otherwise a new, empty kitchen is created for them.

UPDATE "user" SET clerk_user_id = '<prod user id>' WHERE clerk_user_id = '<dev user id>';

Create the production user first (Clerk Dashboard → Users) to get the new id.

Database Migrations

On Vercel, migrations run automatically at the end of the web app build (pnpm --filter @ovenlovin/db db:migrate:deploy). The script prefers a direct (non-pooled) Neon URL when one is available.

If the database already has tables - for example from an earlier drizzle-kit push - and Drizzle has no migration history, the deploy script baselines drizzle.__drizzle_migrations so the initial migration is not re-applied.

Local / manual

# Install dependencies
pnpm install
 
# Run migrations (Drizzle Kit)
pnpm --filter @ovenlovin/db db:migrate
 
# Or the same deploy script used on Vercel
pnpm --filter @ovenlovin/db db:migrate:deploy

Migration Location

Migrations are in packages/db/drizzle/. History lives in the drizzle schema (drizzle.__drizzle_migrations), not in public. The initial migration 0000_yellow_shooting_star.sql creates household, person, recipe, meal-plan, and shopping-list tables.

Verify Deployment

After deployment and database setup:

Check Health

curl https://your-app.vercel.app/api/v1/health

Should return:

{
  "status": "ok",
  "version": "0.1.0",
  "timestamp": "2026-10-21T12:00:00Z"
}

Test Authentication

  1. Visit your deployed URL
  2. Click Sign In
  3. Create an account
  4. Should redirect to dashboard

Test Database

  1. Sign in
  2. Go to Settings → Household
  3. Create a household (Clerk Organization)
  4. Add a person with dietary rules
  5. Data should persist on refresh

Troubleshooting

Database Connection Errors

Error: ENOTFOUND or connection refused

  • Verify DATABASE_URL is correct
  • Check Neon project is not paused (free tier auto-pauses)
  • Ensure IP allowlist includes Vercel IPs (if configured)

Clerk Authentication Errors

Error: Invalid publishable key

  • Verify NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY starts with pk_
  • Ensure key matches your Clerk environment (development vs production)

Error: Organizations not enabled

  • Go to Clerk Dashboard → Organizations → Enable Organizations
  • Redeploy after enabling

Blob Storage Errors

Error: Unauthorized or invalid token

  • Verify BLOB_READ_WRITE_TOKEN is set correctly
  • Check token has read/write permissions
  • Ensure Blob store is in the same Vercel team/project

Migration Errors

Error: relation already exists

  • You may have run drizzle-kit push before migrations
  • Re-run pnpm --filter @ovenlovin/db db:migrate:deploy - it baselines drizzle.__drizzle_migrations when the household table already exists and no history is recorded

Error: Cannot connect to database

  • Verify DATABASE_URL environment variable
  • Run migrations from a location with database access
  • For serverless: use Vercel's environment with vercel env pull

Next Steps