This guide covers configuring Tapioca for local development. Development configuration prioritizes ease of setup, fast iteration, and helpful debugging tools over production-grade security and performance.
Quick Start
The fastest way to get started with development:
Complete Development Configuration
Here’s a fully annotated development config.yaml:
# ==============================================================================
# DEVELOPMENT CONFIGURATION
# This configuration is optimized for local development
# ==============================================================================
# Server Configuration
server:
host: "0.0.0.0" # Listen on all interfaces
port: 8080 # Standard development port
read_timeout: "30s"
write_timeout: "30s"
idle_timeout: "120s"
# Database Configuration
database:
# Local PostgreSQL - started with docker-compose
url: "postgres://tapioca:tapioca_dev_password@localhost:5432/tapioca?sslmode=disable"
max_open_conns: 10 # Lower for development
max_idle_conns: 2
conn_max_lifetime: "15m"
conn_max_idle_time: "5m"
# Auto-migrate on startup for convenience
# Saves manual migration steps during development
auto_migrate: true
# Don't force migrations in dirty state
# Prevents accidental data loss
force_migrate: false
# Cache Configuration
cache:
# Use in-memory cache for simplicity
# No Redis required for basic development
# Switch to "redis" when testing real-time features
type: "memory"
# Redis configuration (if type: "redis")
redis:
address: "localhost:6379"
password: ""
db: 0
key_prefix: "tapioca:dev:"
# Shorter TTLs for development
# See changes faster
ttl:
default: "5m"
permissions: "5m"
sessions: "24h"
queries: "1m"
users: "10m"
projects: "10m"
# Disable cache warming for faster startup
warming:
enabled: false
on_startup: false
# Authentication Configuration
auth:
# Development session secret - CHANGE IN PRODUCTION
session_secret: "dev-secret-change-in-production-32b"
session_duration: "720h" # 30 days - stay logged in
token_expiration: "720h"
frontend_url: "http://localhost:5173" # Vite dev server
# Integration encryption key for OAuth tokens
integration_encryption_key: "d22f064a2fd6dded6970d2d49559c4c090c36fd3ca4c5b05e06b1870843f9106"
# Development Authentication - INSTANT LOGIN
# Allows you to log in as any user without password
# Access at: http://localhost:8080/auth/dev/login?user_id=1
dev:
enabled: true # NEVER enable in production
# Local email/password authentication
local:
enabled: true
password_policy:
min_length: 4 # Relaxed for development
require_uppercase: false
require_lowercase: false
require_number: false
require_special: false
# OIDC/SAML disabled for development
# Enable if testing SSO integration
oidc:
enabled: false
saml:
enabled: false
cloudflare_zero:
enabled: false
# SMTP Configuration
smtp:
# Emails are logged to console instead of sent
# Perfect for development - see email content without sending
host: ""
port: 587
username: ""
password: ""
from: "dev@localhost"
from_name: "Tapioca Dev"
tls: false
# Rate Limiting
rate_limit:
# Disabled for development
# No rate limiting while testing
enabled: false
# Jobs Configuration
jobs:
enabled: true
worker_mode: "embedded" # Jobs run in same process
concurrency: 5 # Lower concurrency for dev
# Shorter retention for development
cleanup:
session_retention_days: 1
token_retention_days: 7
audit_log_retention_days: 30
job_history_retention_days: 7
# WebSocket Configuration
websocket:
enabled: true
max_connections_per_user: 10 # Higher for multi-tab development
# Redis pub/sub disabled (single instance)
redis:
enabled: false
# Storage Configuration
storage:
# Local filesystem storage
type: "local"
local:
base_path: "./data/dev/storage"
# Logging Configuration
log:
# Pretty console logging for development
stdout:
enabled: true
level: "debug" # Verbose logging
format: "pretty" # Colored, human-readable
colors: true
timestamps: true
# No file or Loki logging needed
file:
enabled: false
loki:
enabled: false
# Request logging - see all HTTP requests
request:
verbosity: 2 # Detailed request logging
slow_request_threshold: 100 # Lower threshold for dev
skip_health_checks: false # Log everything
log_request_body: false # Enable if debugging API issues
log_response_body: false
# Audit Configuration
audit:
enabled: true
retention_days: 30 # Shorter retention for dev
granularity: "standard" # Less detailed for dev
async_logging: false # Sync for easier debugging
# Performance Configuration
performance:
# Enable profiling for development
profiling:
enabled: true
pprof_enabled: true
pprof_auth: false # No auth required in dev
request_timing: true
detailed_metrics: true
# Disable compression for easier debugging
compression:
enabled: false
# Low slow query threshold
slow_query:
enabled: true
threshold: "50ms" # Catch slow queries early
log_query: true
log_stack_trace: true # See where queries originate
# Public Roadmap (for testing)
public_roadmap:
enabled: false # Enable if testing this feature
# Development Seeding
# Automatically populate database with realistic data
dev_seed:
enabled: true # Enable for realistic test data
url: "https://tapioca.work/api/v1/public/roadmap/dev"
org_name: "BCP Technology"
org_slug: "bcp-technology"
timeout: "30s"
skip_if_exists: true # Only seed once Environment Variables for Development
Create a .env file in the project root for local overrides:
# .env - Local development environment variables
# This file is .gitignored - safe for local config
# Database
TAPIOCA_DATABASE_URL="postgres://tapioca:tapioca_dev_password@localhost:5432/tapioca?sslmode=disable"
# Enable auto-migrations
TAPIOCA_DATABASE_AUTO_MIGRATE=true
# Development auth (instant login)
TAPIOCA_AUTH_DEV_ENABLED=true
# Verbose logging
TAPIOCA_LOG_STDOUT_LEVEL=debug
# Frontend URL (if using different port)
TAPIOCA_AUTH_FRONTEND_URL="http://localhost:5173"
# Disable rate limiting
TAPIOCA_RATE_LIMIT_ENABLED=false
# Optional: Test with Redis instead of memory cache
# TAPIOCA_CACHE_TYPE=redis
# TAPIOCA_CACHE_REDIS_ADDRESS=localhost:6379
# Optional: Enable development seeding
# TAPIOCA_DEV_SEED_ENABLED=true Docker Compose for Dependencies
Use this docker-compose.yml for development dependencies:
# docker-compose.yml
version: '3.8'
services:
# PostgreSQL Database
postgres:
image: postgres:16-alpine
container_name: tapioca-postgres-dev
environment:
POSTGRES_USER: tapioca
POSTGRES_PASSWORD: tapioca_dev_password
POSTGRES_DB: tapioca
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tapioca"]
interval: 5s
timeout: 5s
retries: 5
# Redis Cache (optional - only needed for WebSocket testing)
redis:
image: redis:7-alpine
container_name: tapioca-redis-dev
ports:
- "6379:6379"
command: redis-server --appendonly yes
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
# MailHog - Email testing UI
# View sent emails at http://localhost:8025
mailhog:
image: mailhog/mailhog:latest
container_name: tapioca-mailhog-dev
ports:
- "1025:1025" # SMTP server
- "8025:8025" # Web UI
environment:
MH_STORAGE: maildir
MH_MAILDIR_PATH: /maildir
volumes:
postgres_data:
redis_data: Start dependencies:
# Start all services
docker compose up -d
# Start only PostgreSQL
docker compose up -d postgres
# View logs
docker compose logs -f
# Stop all services
docker compose down
# Reset everything (deletes data!)
docker compose down -v Development Workflow
Starting the Application
# Terminal 1: Start backend
go run ./cmd/tapiocad
# Terminal 2: Start frontend dev server
cd web
npm run dev
# Terminal 3: Watch for file changes and rebuild
# (optional - for automatic backend reloads)
air # or your preferred Go hot-reload tool Common Development Tasks
Reset Database
# Drop and recreate database
docker compose exec postgres psql -U tapioca -c "DROP DATABASE tapioca;"
docker compose exec postgres psql -U tapioca -c "CREATE DATABASE tapioca;"
# Run migrations
go run ./cmd/tapiocad migrate up Run Migrations
# Apply all pending migrations
go run ./cmd/tapiocad migrate up
# Rollback last migration
go run ./cmd/tapiocad migrate down
# Check migration status
go run ./cmd/tapiocad migrate status
# Create new migration
go run ./cmd/tapiocad migrate create add_user_preferences Seed Test Data
# Use development seeding (from config)
# Just start the server with dev_seed.enabled: true
# Or manually seed data
go run ./cmd/tapiocad seed --data=dev Test Email Sending
With MailHog running:
- Update SMTP config to use MailHog:
smtp:
host: "localhost"
port: 1025
from: "dev@localhost"
tls: false - Send a test email through the app
- View it at http://localhost:8025
Clear Cache
# Memory cache: Just restart the server
# Redis cache:
docker compose exec redis redis-cli FLUSHALL
# Or flush only Tapioca keys:
docker compose exec redis redis-cli --scan --pattern "tapioca:*" | xargs redis-cli DEL Development Tools
Debugging
Enable pprof Profiling
Already enabled in development config. Access profiling tools at:
- Heap Profile: http://localhost:8080/debug/pprof/heap
- CPU Profile: http://localhost:8080/debug/pprof/profile?seconds=30
- Goroutines: http://localhost:8080/debug/pprof/goroutine
- All Profiles: http://localhost:8080/debug/pprof/
Use with go tool pprof:
# CPU profile (30 seconds)
go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30
# Heap profile
go tool pprof http://localhost:8080/debug/pprof/heap
# Interactive web UI
go tool pprof -http=:9090 http://localhost:8080/debug/pprof/heap Database Query Logging
Enable verbose query logging:
performance:
slow_query:
enabled: true
threshold: "1ms" # Log ALL queries
log_query: true
log_args: true # Include query parameters
log_stack_trace: true Request Tracing
Enable detailed request logging:
log:
request:
verbosity: 3 # Maximum verbosity
log_request_body: true
log_response_body: true
max_body_size: 8192 Development Browser Extensions
Recommended browser extensions:
- React DevTools - Inspect React component tree
- Redux DevTools - Debug Redux state (if using Redux)
- WebSocket Inspector - Monitor WebSocket connections
- JSON Formatter - Pretty-print API responses
API Testing Tools
Use these tools for API testing:
# cURL
curl http://localhost:8080/api/v1/tasks
-H "Authorization: Bearer your-dev-token"
# HTTPie (prettier output)
http :8080/api/v1/tasks Authorization:"Bearer your-dev-token"
# Or use GUI tools:
# - Postman
# - Insomnia
# - Bruno (open-source) VS Code Configuration
Recommended .vscode/settings.json:
{
"go.testFlags": ["-v"],
"go.testTimeout": "30s",
"go.lintOnSave": "package",
"go.formatTool": "gofmt",
"editor.formatOnSave": true,
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/node_modules": true,
"**/dist": true,
"**/*.exe": true
}
} Recommended .vscode/launch.json for debugging:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Tapiocad",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/tapiocad",
"env": {
"TAPIOCA_LOG_STDOUT_LEVEL": "debug",
"TAPIOCA_AUTH_DEV_ENABLED": "true"
},
"args": []
},
{
"name": "Debug Tests",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}",
"env": {
"TAPIOCA_DATABASE_URL": "postgres://tapioca:tapioca_dev_password@localhost:5432/tapioca_test?sslmode=disable"
}
}
]
} Testing Configuration
Unit Tests
Use in-memory implementations for unit tests:
// tests setup
cfg := &config.Config{
Cache: config.CacheConfig{
Type: "memory", // No Redis needed
},
Log: config.LogConfig{
Stdout: config.LogStdoutConfig{
Level: "error", // Quiet during tests
},
},
} Integration Tests
Use Testcontainers for integration tests:
import (
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/postgres"
)
func setupTestDB(t *testing.T) *postgres.PostgresContainer {
ctx := context.Background()
container, err := postgres.RunContainer(ctx,
testcontainers.WithImage("postgres:16-alpine"),
postgres.WithDatabase("tapioca_test"),
postgres.WithUsername("tapioca"),
postgres.WithPassword("test"),
)
require.NoError(t, err)
return container
} Run integration tests:
# All tests
go test ./...
# Integration tests only
go test -tags=integration ./...
# With coverage
go test -cover ./...
# Verbose output
go test -v ./... Common Development Issues
Port Already in Use
# Find process using port 8080
lsof -i :8080
# Kill process
kill -9 <PID>
# Or use different port
TAPIOCA_SERVER_PORT=8081 go run ./cmd/tapiocad Database Connection Failed
# Check PostgreSQL is running
docker compose ps postgres
# Check connection manually
psql -h localhost -U tapioca -d tapioca
# Restart PostgreSQL
docker compose restart postgres Cache Not Working
# If using memory cache: Restart server
# If using Redis: Check Redis is running
docker compose ps redis
redis-cli ping
# Clear Redis cache
docker compose exec redis redis-cli FLUSHALL Build Fails
# Clean build cache
go clean -cache
# Update dependencies
go mod tidy
go mod download
# Rebuild from scratch
rm -rf bin/
go build ./cmd/tapiocad Next Steps
- Production Configuration - Deploy to production
- Docker Configuration - Container deployment
- Testing Guide - Write and run tests
- Development Guide - Contributing to Tapioca
Tips for Productive Development
Development Best Practices
- Use dev auth for speed - Skip login during development
- Enable auto-migrations - Database updates automatically
- Use MailHog - See all outgoing emails
- Keep dependencies running - docker-compose up -d
- Use verbose logging - Catch issues early
- Profile regularly - Find performance issues before production
- Test with real data - Use dev seeding for realistic scenarios