Environment Variables

Shipkit uses T3 Env for type-safe environment variable validation, ensuring runtime safety and excellent TypeScript integration.

!info Shipkit processes environment variables at build time. You may need to stop and start your dev server if hot module reloading isn't working. !

Quick Setup

  1. Copy the example environment file:
cp .env.example .env.local
  1. Generate required secrets:
# Generate AUTH_SECRET
openssl rand -base64 32

Required Variables

Core Authentication

# Base URL for authentication
# In production, this will be automatically set to VERCEL_URL
AUTH_URL="http://localhost:3000"

# JWT secret for session management
# Generate with: openssl rand -base64 32
AUTH_SECRET=""

OAuth Providers (Optional)

# GitHub OAuth
AUTH_GITHUB_ID=""
AUTH_GITHUB_SECRET=""

# Discord OAuth
AUTH_DISCORD_ID=""
AUTH_DISCORD_SECRET=""

# Google OAuth
AUTH_GOOGLE_ID=""
AUTH_GOOGLE_SECRET=""

Database

# PostgreSQL connection string
DATABASE_URL="postgresql://postgres:password@localhost:5432/shipkit"

# Database prefix (defaults to "db")
DB_PREFIX="db"

External Services (Optional)

GitHub Integration

# GitHub access token for repo operations
GITHUB_ACCESS_TOKEN=""

Google Services

# Google service account credentials
GOOGLE_CLIENT_EMAIL=""
GOOGLE_PRIVATE_KEY=""

AI Services

# OpenAI API key
OPENAI_API_KEY=""

# Anthropic API key
ANTHROPIC_API_KEY=""

Payments

# LemonSqueezy credentials
LEMONSQUEEZY_API_KEY=""
LEMONSQUEEZY_STORE_ID=""

Node Environment

# Node environment (defaults to "development")
# Values: development, test, production
NODE_ENV="development"

Type Safety

Environment variables are validated using T3 Env and Zod schemas:

// src/env.ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url().optional(),
    DB_PREFIX: z.string().default("db"),
    NODE_ENV: z.enum(["development", "test", "production"]).default("development"),

    // Auth
    AUTH_SECRET: z.string().optional(),
    AUTH_URL: z.preprocess(
      (str) => process.env.VERCEL_URL ?? str,
      process.env.VERCEL ? z.string().optional() : z.string().url().optional(),
    ),
    AUTH_DISCORD_ID: z.string().optional(),
    AUTH_DISCORD_SECRET: z.string().optional(),
    AUTH_GITHUB_ID: z.string().optional(),
    AUTH_GITHUB_SECRET: z.string().optional(),
    AUTH_GOOGLE_ID: z.string().optional(),
    AUTH_GOOGLE_SECRET: z.string().optional(),

    // GitHub
    GITHUB_ACCESS_TOKEN: z.string().optional(),

    // Google
    GOOGLE_CLIENT_EMAIL: z.string().optional(),
    GOOGLE_PRIVATE_KEY: z.string().optional(),

    // AI Services
    OPENAI_API_KEY: z.string().optional(),
    ANTHROPIC_API_KEY: z.string().optional(),

    // Payments
    LEMONSQUEEZY_API_KEY: z.string().optional(),
    LEMONSQUEEZY_STORE_ID: z.string().optional(),
  },
});

Environment Management

Local Development

  1. Copy the example environment file:
cp .env.example .env.local
  1. Update variables in .env.local

Production (Vercel)

  1. Add variables through the Vercel dashboard or CLI:
vercel env add MY_VAR
  1. After adding variables, redeploy your application:
vercel --prod

Public Env Mirroring

Certain public environment variables can be set without the NEXT_PUBLIC_ prefix. During build, Shipkit mirrors these to their NEXT_PUBLIC_* equivalents so they are available on the client. For example:

STRIPE_PUBLISHABLE_KEY=pk_test_your_key
# becomes available to the client as
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_key

Supported base keys:

  • BUILDER_API_KEY → NEXT_PUBLIC_BUILDER_API_KEY
  • CLERK_PUBLISHABLE_KEY → NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
  • SUPABASE_URL → NEXT_PUBLIC_SUPABASE_URL
  • SUPABASE_ANON_KEY → NEXT_PUBLIC_SUPABASE_ANON_KEY
  • STRIPE_PUBLISHABLE_KEY → NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
  • POSTHOG_KEY → NEXT_PUBLIC_POSTHOG_KEY
  • UMAMI_WEBSITE_ID → NEXT_PUBLIC_UMAMI_WEBSITE_ID
  • STATSIG_CLIENT_KEY → NEXT_PUBLIC_STATSIG_CLIENT_KEY
  • GOOGLE_ANALYTICS_ID → NEXT_PUBLIC_GOOGLE_ANALYTICS_ID
  • GOOGLE_GTM_ID → NEXT_PUBLIC_GOOGLE_GTM_ID
  • C15T_URL → NEXT_PUBLIC_C15T_URL

Notes:

  • If you explicitly set a NEXT_PUBLIC_* value, it takes precedence.
  • The non-prefixed names are not exposed to the client; only the generated NEXT_PUBLIC_* values are.