Developer Setup Guide
April 10, 2026 · View on GitHub
This guide explains how to set up the Upload Bucket development environment, run tests, and deploy the application.
Table of Contents
- Prerequisites
- Project Structure
- Environment Variables
- Local Development Setup
- Running the Application
- Running Tests
- Code Quality
- Database Migrations
- Deployment
- Troubleshooting
Prerequisites
Before you begin, ensure you have the following installed:
| Tool | Version | Purpose |
|---|---|---|
| Node.js | v20+ | JavaScript runtime |
| pnpm | v8+ | Package manager |
| Git | Latest | Version control |
You'll also need accounts for:
| Service | Purpose |
|---|---|
| Cloudflare | Workers hosting, R2 storage |
| Neon | PostgreSQL database |
| Google Cloud | OAuth (optional) |
Project Structure
shindig/
├── backend/ # Hono API (Cloudflare Workers)
│ ├── src/
│ │ ├── db/ # Database schema and connection
│ │ ├── lib/ # Utilities (auth, R2, tier limits)
│ │ ├── middleware/ # Hono middleware
│ │ └── routes/ # API route handlers
│ ├── scripts/ # Admin CLI scripts
│ ├── tests/ # Integration tests
│ ├── drizzle/ # Database migrations
│ └── wrangler.jsonc # Cloudflare Workers config
├── frontend/ # Nuxt 4 SPA
│ ├── app/
│ │ ├── components/ # Vue components
│ │ ├── composables/ # Vue composables (state management)
│ │ └── pages/ # Route pages
│ └── test/ # Frontend tests
├── docs/ # Documentation
└── packages/ # Shared packages
Environment Variables
Backend Environment
- Environment variables in
backend/.envare populated with 1pass secret references - Environment variables in
backend/.envare used for development-time only - When running locally,
pnpm run devrunswrangler dev, which reads environment variable data frombackend/.dev.vars - Use environment variables in
backend/.env.productionfor production-time secrets values (these get populated to Cloudflare with deploy scripts)
Create backend/.dev.vars for local development or backend/.env as an alternative.
Normally, we create the backend/.env file that is used for development-time, and we then run pnpm run sync-env coipes over the .env data that has 1pass secret references in it but gets injected to backend/.dev.vars that wrangler reads (happens when running pnpm run dev).
Following is the stock data expected in backend/.env file:
# Database (Neon PostgreSQL)
DATABASE_URL=postgresql://user:password@host.neon.tech/database?sslmode=require
# Better Auth Configuration
BETTER_AUTH_URL=https://myapp.com
BETTER_AUTH_SECRET=your-32-character-secret-key-here
# Cloudflare R2 Storage
CLOUDFLARE_ACCOUNT_ID=your-cloudflare-account-id
R2_ACCESS_KEY_ID=your-r2-access-key-id
R2_SECRET_ACCESS_KEY=your-r2-secret-access-key
# Google OAuth (optional)
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
Getting Credentials
Neon Database:
- Sign up at neon.tech
- Create a new project
- Copy the connection string from the dashboard
Cloudflare R2:
- Log in to Cloudflare Dashboard
- Go to R2 > Manage R2 API Tokens
- Create a new API token with read/write access
- Note your Account ID from the URL or dashboard
Better Auth Secret: Generate a secure random string:
openssl rand -hex 16
Google OAuth:
- Go to Google Cloud Console
- Create a new project or select existing
- Create OAuth 2.0 credentials
- Add authorized redirect URIs:
https://myapp.com/api/auth/callback/googlehttp://localhost:8787/api/auth/callback/google(development)
Feature Flags (Optional)
# Disable email+password authentication (Google OAuth only)
# EMAIL_PASSWORD_AUTH_ENABLED=false
See Deployment Guide - Feature Flags for details on configuring authentication methods.
Frontend Environment
Create frontend/.env:
# API Base URL
NUXT_PUBLIC_API_BASE_URL=http://localhost:8787
For production, use your deployed API URL:
NUXT_PUBLIC_API_BASE_URL=https://api.myapp.com
Local Development Setup
1. Clone and Install Dependencies
git clone <repository-url>
cd shindig
pnpm install
2. Set Up Environment Variables
# Copy example files (if they exist) or create from scratch
cp backend/.dev.vars.example backend/.dev.vars
cp frontend/.env.example frontend/.env
# Edit with your credentials
3. Set Up R2 Bucket
Run the R2 setup script to create the storage bucket:
cd backend
pnpm run setup-r2
4. Sync Environment (Optional)
If you use 1Password for secrets management:
cd backend
pnpm run sync-env
5. Apply Database Migrations
Generate and apply migrations:
cd backend
# Generate migration files from schema
pnpm exec drizzle-kit generate
# Apply migrations to database
pnpm exec drizzle-kit push
6. Generate TypeScript Types
Generate Cloudflare Worker types:
cd backend
pnpm run cf-typegen
Running the Application
Local development with myapp.com (recommended for devcontainer)
To work on the project locally with the app served at https://myapp.com (e.g. from a devcontainer), you need two steps:
-
On your host (outside the devcontainer) — run the Caddy reverse proxy so that requests to
myapp.comare routed to your local frontend and backend:- Ensure
myapp.comresolves to your machine (e.g. add127.0.0.1 myapp.comto/etc/hostson the host). - From your host, go to the local
infra/http-server/directory and run the start script:
cd path/to/shindig/infra/http-server ./start-caddy.shCaddy will serve
myapp.comwith local TLS and proxy:/api/*→ backend atlocalhost:8787- all other requests → frontend at
localhost:3005
- Ensure
-
Inside the devcontainer — from the monorepo root, start both backend and frontend:
pnpm run devThis uses PM2 to run the backend (Wrangler) and frontend (Nuxt) dev servers. Use https://myapp.com in your browser; Caddy on the host will route traffic to the correct local ports.
Requirements: Caddy must be installed on the host where you run start-caddy.sh. See Caddy install.
Using PM2 only (without Caddy)
The project includes a PM2 configuration for running both frontend and backend:
# From project root
pnpm exec pm2 start ecosystem.config.js
# View logs
pnpm run logs:backend
pnpm run logs:frontend
# Restart services
pnpm exec pm2 restart backend
pnpm exec pm2 restart frontend
# Stop all services
pnpm exec pm2 stop all
You can then open the frontend at http://localhost:3005 and the API at http://localhost:8787. For auth and cookie behavior that matches production, use the Caddy setup above so the app is served at https://myapp.com.
Running Individually
Backend:
cd backend
pnpm run dev
The API will be available at http://localhost:8787
Frontend:
cd frontend
pnpm run dev
The frontend will be available at http://localhost:3005
Checking Service Status
# Check if backend is running
pnpm exec pm2 info backend
# Check all services
pnpm exec pm2 status
Running Tests
Backend Tests
cd backend
# Run all tests once
pnpm run test
# Run tests in watch mode
pnpm run test:watch
The backend uses Vitest with an in-memory PGlite database for integration tests.
Frontend Tests
cd frontend
# Run all tests once
pnpm run test
# Run tests in watch mode
pnpm run test:watch
Code Quality
Linting
Run ESLint to check and fix code style:
# Backend
cd backend
pnpm run lint # Check only
pnpm run lint:fix # Check and auto-fix
# Frontend
cd frontend
pnpm run lint # Check only
pnpm run lint:fix # Check and auto-fix
Type Checking
Run TypeScript compiler to check types:
# Backend
cd backend
pnpm run typecheck
# Frontend
cd frontend
pnpm run typecheck
Full Quality Check
Run all checks before committing:
# Backend
cd backend && pnpm run lint:fix && pnpm run typecheck && pnpm run test
# Frontend
cd frontend && pnpm run lint:fix && pnpm run typecheck && pnpm run test
Database Migrations
After Schema Changes
When you modify backend/src/db/schema.ts:
cd backend
# 1. Generate new migration file
pnpm exec drizzle-kit generate
# 2. Review the generated SQL in backend/drizzle/
# 3. Apply migration to database
pnpm exec drizzle-kit push
# 4. Restart backend if running
pnpm exec pm2 restart backend
Viewing Database
Use Drizzle Studio to browse your database:
cd backend
pnpm exec drizzle-kit studio
Migration Files
Migrations are stored in backend/drizzle/:
XXXX_*.sql- Migration SQL filesmeta/- Migration metadata and snapshots
Deployment
Backend Deployment (Cloudflare Workers)
cd backend
# Deploy to production
pnpm run deploy
This runs wrangler deploy --minify which:
- Bundles the application
- Uploads to Cloudflare Workers
- Makes it available at your configured domain
Frontend Deployment
Build the frontend for production:
cd frontend
pnpm run build
Deploy the .output/ directory to your hosting provider (Cloudflare Pages, Vercel, Netlify, etc.).
Environment Variables in Production
Set production environment variables in the Cloudflare Dashboard:
- Go to Workers & Pages > Your Worker
- Settings > Variables
- Add each environment variable
Or use Wrangler:
wrangler secret put DATABASE_URL
wrangler secret put BETTER_AUTH_SECRET
# ... etc
CORS Configuration
Update CORS settings for production:
cd backend
pnpm run update-cors-set-origins
This sets allowed origins to https://myapp.com and https://www.myapp.com.
Troubleshooting
Common Issues
Database connection fails:
- Verify
DATABASE_URLis correct - Ensure Neon project is active (free tier projects pause after inactivity)
- Check that SSL mode is included:
?sslmode=require
R2 uploads fail:
- Verify
R2_ACCESS_KEY_IDandR2_SECRET_ACCESS_KEYare correct - Check that the R2 bucket exists:
pnpm run setup-r2 - Ensure CORS is configured on the bucket
Authentication not working:
- Verify
BETTER_AUTH_URLmatches your domain - Check that
BETTER_AUTH_SECRETis set - For Google OAuth, verify redirect URIs are configured
Types not found:
- Regenerate types:
pnpm run cf-typegen - Run
pnpm installto ensure dependencies are installed
Viewing Logs
# Backend logs (from project root)
pnpm run logs:backend
# Frontend logs (from project root)
pnpm run logs:frontend
# Or directly with PM2
pnpm exec pm2 logs backend
pnpm exec pm2 logs frontend
Resetting Development Environment
# Stop all services
pnpm exec pm2 stop all
# Clear PM2 processes
pnpm exec pm2 delete all
# Reinstall dependencies
rm -rf node_modules backend/node_modules frontend/node_modules
pnpm install
# Restart
pnpm exec pm2 start ecosystem.config.js