Getting Started

Configuration

A complete reference for every environment variable in your Grit project. All configuration is done through the .env file at the project root.

Environment Files

Every Grit project includes three environment files:

  • .env -- Your actual configuration. This file is gitignored and never committed.
  • .env.example -- Documented template with all variables and sensible defaults. Committed to git.
  • .env.cloud.example -- Template for cloud-only setups (Neon, Upstash, R2) when you do not have Docker.

The Go API loads these variables at startup using godotenv and parses them into a typed Config struct. Environment variables are read once at startup and are available throughout the application.

Application

General application settings that control the server behavior.

.env
# App — General application settings
APP_NAME=myapp              # Application name (used in emails, logs)
APP_ENV=development         # Environment: development, staging, production
APP_PORT=8080               # API server port
APP_URL=http://localhost:8080
APP_NAMEProject name

Used as the application title in email templates, log entries, and the admin panel header. Set to your project name during scaffolding.

APP_ENVdevelopment

Controls logging verbosity, GORM Studio visibility, and error detail level. Set to production in deployed environments to disable debug features.

APP_PORT8080

The port the Go API server listens on. The frontend apps proxy API requests to this port.

APP_URLhttp://localhost:8080

The full URL of the API server. Used for generating absolute URLs in emails and file storage signed URLs.

Database

Grit uses PostgreSQL as its primary database, connected through GORM. The connection string follows the standard PostgreSQL URI format.

.env
# Database — PostgreSQL connection
DATABASE_URL=postgres://grit:grit@localhost:5432/myapp?sslmode=disable
DATABASE_URL

PostgreSQL connection string. Format: postgres://user:password@host:port/database?sslmode=disable

For local development with Docker, the default credentials are grit:grit on port 5432. For cloud databases like Neon, use the connection string provided by your provider and set sslmode=require.

JWT Authentication

Grit uses JWT tokens for authentication with separate access and refresh tokens. The access token is short-lived (15 minutes) and the refresh token lasts 7 days.

.env
# JWT — Authentication tokens
JWT_SECRET=your-super-secret-jwt-key-change-in-production
JWT_ACCESS_EXPIRY=15m        # Access token lifetime
JWT_REFRESH_EXPIRY=168h      # Refresh token lifetime (7 days)
JWT_SECRETRandom string

The secret key used to sign and verify JWT tokens. MUST be changed in production. Use a random string of at least 32 characters. Both access and refresh tokens use this same secret.

JWT_ACCESS_EXPIRY15m

How long access tokens are valid. Uses Go duration format: 15m (15 minutes), 1h (1 hour), etc. Keep short for security. The frontend automatically refreshes expired tokens.

JWT_REFRESH_EXPIRY168h

How long refresh tokens are valid. 168h is 7 days. Users must re-login after this period. Refresh tokens are single-use and rotated on each refresh.

Redis

Redis is used for response caching and background job queues (via Asynq). A single Redis instance handles both use cases.

.env
# Redis — Cache and job queue
REDIS_URL=redis://localhost:6379
REDIS_URLredis://localhost:6379

Redis connection URL. For local Docker, uses port 6379 with no authentication. For cloud Redis (Upstash), use the rediss:// protocol (with double s) and include the password: rediss://default:password@endpoint:6379.

File Storage

Grit supports three S3-compatible storage providers: MinIO (local development), Cloudflare R2, and Backblaze B2. The STORAGE_DRIVER variable controls which provider is active.

.env
# Storage — Active driver: minio, r2, or b2
STORAGE_DRIVER=minio

# MinIO — Local S3-compatible storage (default for development)
MINIO_ENDPOINT=http://localhost:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_BUCKET=myapp-uploads
MINIO_REGION=us-east-1
MINIO_USE_SSL=false

# Cloudflare R2 — S3-compatible object storage
R2_ENDPOINT=https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com
R2_ACCESS_KEY=               # R2 Access Key ID
R2_SECRET_KEY=               # R2 Secret Access Key
R2_BUCKET=myapp-uploads
R2_REGION=auto               # Always "auto" for R2

# Backblaze B2 — S3-compatible object storage
B2_ENDPOINT=https://s3.us-west-004.backblazeb2.com
B2_ACCESS_KEY=               # B2 keyID
B2_SECRET_KEY=               # B2 applicationKey
B2_BUCKET=myapp-uploads
B2_REGION=us-west-004        # Must match your bucket region
STORAGE_DRIVERminio

Which storage provider to use. Options: minio (local dev with Docker), r2 (Cloudflare R2), b2 (Backblaze B2). Only the variables for the active driver need to be set.

MINIO_ENDPOINThttp://localhost:9000

MinIO server URL. The Docker Compose file starts MinIO on port 9000 with a web console on port 9001.

MINIO_ACCESS_KEY / MINIO_SECRET_KEYminioadmin

Default MinIO credentials. These match the Docker Compose configuration. Change in production if running your own MinIO instance.

R2_ENDPOINT(your account)

Your Cloudflare R2 endpoint. Get this from the Cloudflare Dashboard under R2 > Overview. Format: https://ACCOUNT_ID.r2.cloudflarestorage.com

R2_ACCESS_KEY / R2_SECRET_KEY(your keys)

Cloudflare R2 API credentials. Create an API token in the Cloudflare Dashboard under R2 > Manage R2 API Tokens.

B2_ENDPOINT(your region)

Backblaze B2 S3-compatible endpoint. Format depends on your bucket region. Find it in your B2 bucket settings.

Email

Grit uses Resend for transactional emails -- welcome emails, password resets, and notifications. In development, emails are caught by Mailhog (accessible at http://localhost:8025).

.env
# Email — Resend integration
RESEND_API_KEY=re_your_api_key
MAIL_FROM=noreply@myapp.dev
RESEND_API_KEYre_your_api_key

Your Resend API key. Get one at resend.com/api-keys. In development, emails are sent to Mailhog regardless of this key.

MAIL_FROMnoreply@myapp.dev

The sender email address for all outgoing emails. Must be a verified domain in your Resend account for production use.

CORS

Cross-Origin Resource Sharing configuration. The Go API needs to know which frontend origins are allowed to make requests.

.env
# CORS — Allowed frontend origins (comma-separated)
CORS_ORIGINS=http://localhost:3000,http://localhost:3001
CORS_ORIGINShttp://localhost:3000,http://localhost:3001

Comma-separated list of allowed origins. In development, port 3000 is the web app and port 3001 is the admin panel. In production, set this to your actual domain names (e.g., https://myapp.com,https://admin.myapp.com).

GORM Studio

The embedded visual database browser. Accessible at /studio on the API server.

.env
# GORM Studio — Visual database browser
GORM_STUDIO_ENABLED=true
GORM_STUDIO_ENABLEDtrue

Enable or disable GORM Studio. Set to true in development for visual database browsing. Set to false in production to disable the database browser and prevent unauthorized access to your data.

AI Integration

Grit ships with built-in AI support for both Anthropic Claude and OpenAI. The AI service provides text completion and streaming endpoints.

.env
# AI — Text generation (Claude or OpenAI)
AI_PROVIDER=claude           # "claude" or "openai"
AI_API_KEY=                  # Your API key (sk-ant-... or sk-...)
AI_MODEL=claude-sonnet-4-5-20250929
AI_PROVIDERclaude

Which AI provider to use. Options: claude (Anthropic) or openai. The AI service uses the appropriate API format based on this setting.

AI_API_KEY(your key)

Your AI provider API key. For Anthropic, starts with sk-ant-. For OpenAI, starts with sk-. Leave empty if you do not use AI features.

AI_MODELclaude-sonnet-4-5-20250929

The model to use for completions. For Claude: claude-sonnet-4-5-20250929, claude-opus-4-6, etc. For OpenAI: gpt-4o, gpt-4o-mini, etc.

Frontend URLs

The frontend applications run on their own ports in development. These are configured in each app's package.json and referenced in the CORS configuration.

ApplicationDev URLPort
Go APIhttp://localhost:80808080
GORM Studiohttp://localhost:8080/studio8080
Web App (Next.js)http://localhost:30003000
Admin Panel (Next.js)http://localhost:30013001
PostgreSQLlocalhost:54325432
Redislocalhost:63796379
MinIOhttp://localhost:90009000
MinIO Consolehttp://localhost:90019001
Mailhoghttp://localhost:80258025

Complete .env Reference

Here is every environment variable in a single block for quick copy-paste:

.env.example
# App
APP_NAME=myapp
APP_ENV=development
APP_PORT=8080
APP_URL=http://localhost:8080

# Database
DATABASE_URL=postgres://grit:grit@localhost:5432/myapp?sslmode=disable

# JWT
JWT_SECRET=change-me-in-production
JWT_ACCESS_EXPIRY=15m
JWT_REFRESH_EXPIRY=168h

# Redis
REDIS_URL=redis://localhost:6379

# Storage
STORAGE_DRIVER=minio
MINIO_ENDPOINT=http://localhost:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_BUCKET=myapp-uploads
MINIO_REGION=us-east-1
MINIO_USE_SSL=false

# Email
RESEND_API_KEY=re_your_api_key
MAIL_FROM=noreply@myapp.dev

# CORS
CORS_ORIGINS=http://localhost:3000,http://localhost:3001

# GORM Studio
GORM_STUDIO_ENABLED=true

# AI
AI_PROVIDER=claude
AI_API_KEY=
AI_MODEL=claude-sonnet-4-5-20250929

Production Checklist

Before deploying to production, make sure you have addressed these configuration items:

  • Change JWT_SECRET to a strong random string (at least 32 characters)
  • Set APP_ENV=production to disable debug logging and GORM Studio
  • Set GORM_STUDIO_ENABLED=false to disable the database browser
  • Update DATABASE_URL to point to your production database
  • Update CORS_ORIGINS to your production domain names
  • Set STORAGE_DRIVER to r2 or b2 and configure cloud credentials
  • Set RESEND_API_KEY with your production API key and verify your sender domain
  • Update REDIS_URL to your production Redis instance
  • Set APP_URL to your production API domain