-
-
Notifications
You must be signed in to change notification settings - Fork 23
Contributing Development
How to build and contribute to Caddy Proxy Manager.
- Getting Started
- Development Environment
- Code Style
- Testing
- Database Changes
- Pull Request Process
- Project Structure
-
Node.js: Version 25+ (check
.nvmrc) - Docker: For running Caddy
- Git: Version control
- Code editor: VS Code recommended
-
Fork the repository on GitHub
-
Clone your fork:
git clone https://github.com/YOUR-USERNAME/caddy-proxy-manager.git cd caddy-proxy-manager -
Add upstream remote:
git remote add upstream https://github.com/fuomag9/caddy-proxy-manager.git
Step 1: Install dependencies
npm installStep 2: Create environment file
cp .env.example .envStep 3: Configure for development
# .env
NODE_ENV=development # Allows default admin/admin credentials
SESSION_SECRET="dev-secret-change-in-production"
ADMIN_USERNAME="admin"
ADMIN_PASSWORD="admin"
CADDY_API_URL="http://localhost:2019"
DATABASE_URL="file:./data/caddy-proxy-manager.db"Step 4: Start Caddy in Docker
docker compose up caddy -dStep 5: Start Next.js dev server
npm run devStep 6: Access application
- Web UI: http://localhost:3000
- Login: admin / admin (development mode)
Working on features:
-
Create feature branch:
git checkout -b feature/your-feature-name
-
Make changes and test locally
-
Run linter:
npm run lint
-
Build to verify:
npm run build
-
Commit changes:
git add . git commit -m "Add feature: description"
-
Push to your fork:
git push origin feature/your-feature-name
-
Open Pull Request on GitHub
Next.js dev server supports hot reload:
- Edit files in
src/ - Changes reflect immediately
- No rebuild needed
Restart required for:
- Environment variable changes
- Database schema changes
- Dependency changes
Strict typing required:
- No
anytypes - Use proper type definitions
- Prefer interfaces over types for objects
Example:
// Good
interface ProxyHost {
id: number;
domain: string;
upstream: string;
}
// Bad
const data: any = fetchData();Use Prettier (configured in .prettierrc):
# Format all files
npm run format
# Check formatting
npm run format:checkVS Code integration:
- Install Prettier extension
- Enable "Format on Save"
Follow existing patterns:
src/
├── app/ # Next.js app directory
│ ├── (dashboard)/ # Dashboard routes
│ ├── login/ # Login page
│ └── api/ # API routes
├── lib/ # Shared utilities
│ ├── actions.ts # Server actions
│ ├── db/ # Database schema
│ └── caddy.ts # Caddy integration
└── components/ # React components
Files:
- Components:
PascalCase.tsx - Utilities:
kebab-case.ts - Pages:
page.tsx
Variables:
- Constants:
UPPER_SNAKE_CASE - Variables:
camelCase - Components:
PascalCase
Functions:
- Regular:
camelCase - Server actions:
camelCase - Async: prefix with
asyncor suffix withAsync
Test checklist:
- Functionality works as expected
- UI renders correctly
- Forms validate properly
- Errors handled gracefully
- Console errors checked
- Different browsers tested (Chrome, Firefox, Safari)
Always test production build:
npm run build
npm run startVerify:
- No build errors
- All pages accessible
- Production mode restrictions work
- Environment validation working
Test Docker builds:
docker compose up --build -d
docker compose logs webVerify:
- Containers start successfully
- Health checks pass
- Production mode enforced
Schema location: src/lib/db/schema.ts
Step 1: Update schema
// src/lib/db/schema.ts
export const proxyHosts = sqliteTable("proxy_hosts", {
id: integer("id").primaryKey({ autoIncrement: true }),
domain: text("domain").notNull(),
upstream: text("upstream").notNull(),
// Add new field
description: text("description"),
});Step 2: Generate migration
npm run db:generateThis creates migration file in drizzle/ directory.
Step 3: Test migration
# Delete dev database
rm -rf data/caddy-proxy-manager.db*
# Restart dev server (runs migrations)
npm run devStep 4: Verify migration
# Check migration applied
sqlite3 data/caddy-proxy-manager.db
.schema proxy_hosts
.exit- Never edit existing migrations - create new ones
- Test on clean database before PR
- Include migration files in commit
- Document breaking changes in PR description
- Code follows project style
- TypeScript types are correct (no
any) - Linting passes:
npm run lint - Build succeeds:
npm run build - Tested locally in development mode
- Tested locally in production mode
- Database migrations included (if schema changed)
- No secrets committed
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Tested in development mode
- [ ] Tested in production build
- [ ] Tested in Docker
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-reviewed code
- [ ] Commented complex logic
- [ ] Updated documentation
- [ ] No console errors
- [ ] Database migrations tested
## Screenshots (if UI changes)
[Add screenshots]- Automated checks run (future: CI/CD)
- Maintainer review code
- Feedback addressed if needed
- Approved and merged
caddy-proxy-manager/
├── src/ # Application source
│ ├── app/ # Next.js App Router
│ │ ├── (dashboard)/ # Dashboard layout & pages
│ │ ├── api/ # API routes
│ │ └── login/ # Login page
│ ├── lib/ # Shared utilities
│ │ ├── actions.ts # Server actions
│ │ ├── auth.ts # Authentication
│ │ ├── caddy.ts # Caddy API client
│ │ ├── config.ts # Config & validation
│ │ ├── db/ # Database
│ │ │ ├── schema.ts # Drizzle schema
│ │ │ └── index.ts # DB connection
│ │ └── models/ # Type-safe models
│ └── components/ # React components
│ └── ui/ # Shadcn/ui components
├── docker/ # Docker configurations
│ ├── caddy/ # Caddy Dockerfile
│ └── web/ # Web Dockerfile
├── drizzle/ # Database migrations
├── public/ # Static assets
└── scripts/ # Build scripts
Configuration:
-
next.config.mjs- Next.js configuration -
drizzle.config.ts- Database configuration -
tsconfig.json- TypeScript configuration -
.env.example- Environment variable template
Docker:
-
docker-compose.yml- Development compose file -
docker/web/Dockerfile- Web application image -
docker/caddy/Dockerfile- Caddy server image
Database:
-
src/lib/db/schema.ts- Database schema (Drizzle) -
src/lib/db/index.ts- Database connection
- Framework: Next.js 16 (App Router)
- Runtime: React 19
- Language: TypeScript
- Database: SQLite with Drizzle ORM
- UI: shadcn/ui with Tailwind CSS
- Forms: React Hook Form
- Authentication: Better Auth
- Proxy Server: Caddy
Server Actions:
- Used for mutations (create, update, delete)
- Defined in
src/lib/actions.ts - Type-safe with Zod validation
Models:
- Type-safe data layer in
src/lib/models/ - Abstracts database operations
- Handles Caddy API integration
Components:
- React Server Components by default
- Client Components when needed (forms, interactivity)
- shadcn/ui + Tailwind CSS for consistent design
- No API tokens
- No passwords
- No SESSION_SECRET values
- No .env files
Use .env.example with placeholder values.
Always validate user input:
import { z } from "zod";
const schema = z.object({
domain: z.string().min(1).regex(/^[a-z0-9.-]+$/),
upstream: z.string().url(),
});Use parameterized queries:
// Good
db.select().from(proxyHosts).where(eq(proxyHosts.id, id));
// Bad (SQL injection)
db.execute(`SELECT * FROM proxy_hosts WHERE id = ${id}`);- Minimize permissions
- Validate authorization
- Use type safety
- Handle errors gracefully
- Next.js Documentation
- Drizzle ORM Documentation
- shadcn/ui Documentation
- Tailwind CSS Documentation
- Caddy Documentation
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Pull Requests: Code review and feedback
- Installation Guide - Setup for users
- Environment Variables Reference - Configuration
- Security Configuration - Security best practices
- Troubleshooting - Common issues
Ready to contribute? See CONTRIBUTING.md in the repository root for quick start guide!