Contributing
Thank you for your interest in contributing to BunnyDB! This guide will help you set up a development environment, understand the codebase, and submit contributions.
Development Setup
Get BunnyDB running locally for development.
Clone the repository
git clone https://github.com/yourusername/bunnyDB.git
cd bunnyDBStart the development environment
docker compose up -dThis starts:
- Catalog PostgreSQL database
- Temporal server and UI
- BunnyDB API (port 8112)
- BunnyDB worker
- UI development server (if configured)
Verify everything is running
docker compose psAll services should be in the “Up” state.
Access the services
- API: http://localhost:8112
- Temporal UI: http://localhost:8085
- UI: http://localhost:3000 (if running)
- Docs: http://localhost:3001 (if running)
The default admin credentials are admin:admin. The catalog database uses postgres:bunnydb.
Project Structure
BunnyDB is organized into several main directories:
bunnyDB/
├── flow/ # Go backend (API + Worker)
│ ├── api/ # HTTP API handlers and routes
│ ├── activities/ # Temporal activities (snapshot, CDC)
│ ├── workflows/ # Temporal workflows (mirror orchestration)
│ ├── model/ # Database models and schema
│ ├── shared/ # Shared utilities and types
│ ├── connectors/ # PostgreSQL connection management
│ └── catalog/ # Catalog database operations
├── ui/ # Next.js frontend
│ ├── app/ # Next.js app router pages
│ ├── components/ # React components
│ └── lib/ # Frontend utilities and API client
├── docs/ # Documentation site (Nextra)
│ └── pages/ # Documentation pages (MDX)
└── volumes/ # Docker volume configurations
├── postgres/ # PostgreSQL init scripts
└── temporal/ # Temporal configurationFlow (Backend)
The flow/ directory contains the Go backend.
Key Directories
api/ - HTTP API
routes.go: API route definitionshandlers/: HTTP request handlersauth/: JWT authentication middleware- Serves the REST API on port 8112
activities/ - Temporal Activities
snapshot.go: Initial table snapshot logiccdc.go: Change data capture activitiesschema.go: Schema synchronization- Long-running operations executed by workers
workflows/ - Temporal Workflows
mirror.go: Main mirror replication workflow- Orchestrates snapshot, CDC, and control signals
- Handles retries and error recovery
model/ - Database Models
peer.go: Peer database configurationmirror.go: Mirror metadatauser.go: User accountslog.go: Structured logs- Uses GORM for ORM
shared/ - Shared Code
config.go: Environment variable configurationpostgres.go: PostgreSQL utilitiestemporal.go: Temporal client setuptypes.go: Common types and constants
connectors/ - Database Connectors
postgres_connector.go: PostgreSQL connection poolingreplication.go: Logical replication protocol- Manages connections to peers and catalog
catalog/ - Catalog Operations
migrations/: Database migrationsqueries.go: Catalog database queries- Stores BunnyDB metadata
UI (Frontend)
The ui/ directory contains the Next.js web interface.
Key Directories
app/ - Next.js Pages
page.tsx: Dashboardmirrors/: Mirror management pagespeers/: Peer management pagesusers/: User management pages- Uses Next.js 13+ app router
components/ - React Components
MirrorCard.tsx: Mirror status displayPeerForm.tsx: Peer creation/edit formLogViewer.tsx: Log display component- Reusable UI components
lib/ - Frontend Utilities
api.ts: API client (fetch wrapper)auth.ts: Authentication helpersutils.ts: Common utilities
Docs (Documentation)
The docs/ directory contains this documentation site built with Nextra.
pages/ - Documentation Pages
- Written in MDX (Markdown + JSX)
- Organized by topic (guides, API reference, etc.)
- Auto-generated navigation from
_meta.jsonfiles
Building the Project
Building the Backend
Build and run with Docker Compose:
docker compose build bunny-api bunny-worker
docker compose up -d bunny-api bunny-workerBuilding the Frontend
docker compose build ui
docker compose up -d uiBuilding the Documentation
cd docs
# Install dependencies
npm install
# Development mode
npm run dev
# Production build
npm run buildTesting
Backend Tests
cd flow
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run tests for specific package
go test ./activities
# Run with verbose output
go test -v ./...Frontend Tests
cd ui
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watchIntegration Tests
# Ensure dev environment is running
docker compose up -d
# Run integration tests
cd flow
go test -tags=integration ./tests/integrationIntegration tests require a running BunnyDB environment with Temporal and catalog database.
Making Changes
Code Style
Go
- Follow Effective Go guidelines
- Use
gofmtfor formatting:go fmt ./... - Use
golintfor linting:golint ./... - Write descriptive comments for exported functions
TypeScript/React
- Use ESLint and Prettier (configured in
ui/) - Run linter:
npm run lint - Format code:
npm run format
Adding a New API Endpoint
Define the route
In flow/api/routes.go:
func SetupRoutes(r *gin.Engine) {
api := r.Group("/v1")
// Add your route
api.GET("/my-endpoint", handlers.MyHandler)
}Create the handler
In flow/api/handlers/my_handler.go:
package handlers
import (
"github.com/gin-gonic/gin"
"net/http"
)
func MyHandler(c *gin.Context) {
// Handler logic
c.JSON(http.StatusOK, gin.H{
"message": "Success",
})
}Add tests
In flow/api/handlers/my_handler_test.go:
package handlers
import (
"testing"
"net/http/httptest"
"github.com/stretchr/testify/assert"
)
func TestMyHandler(t *testing.T) {
// Test implementation
}Document the endpoint
Add to the appropriate API reference page in docs/pages/api-reference/.
Adding a New Temporal Activity
Define the activity
In flow/activities/my_activity.go:
package activities
import (
"context"
"go.temporal.io/sdk/activity"
)
type MyActivityInput struct {
Param1 string
}
type MyActivityOutput struct {
Result string
}
func MyActivity(ctx context.Context, input MyActivityInput) (*MyActivityOutput, error) {
// Send heartbeats for long operations
activity.RecordHeartbeat(ctx, "progress")
// Activity logic
return &MyActivityOutput{
Result: "success",
}, nil
}Register the activity
In flow/cmd/worker/main.go:
w.RegisterActivity(activities.MyActivity)Use in workflow
In flow/workflows/mirror.go:
var result activities.MyActivityOutput
err := workflow.ExecuteActivity(ctx, activities.MyActivity, activities.MyActivityInput{
Param1: "value",
}).Get(ctx, &result)Adding a Database Migration
Create migration file
In flow/catalog/migrations/:
package migrations
func init() {
Migrations = append(Migrations, Migration{
Version: "003_add_my_table",
Up: `
CREATE TABLE my_table (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
`,
Down: `
DROP TABLE my_table;
`,
})
}Run migration
Migrations run automatically on API startup, or manually:
cd flow
go run ./cmd/migratePull Request Guidelines
Branch Naming
Use descriptive branch names with prefixes:
feature/- New featuresfix/- Bug fixesdocs/- Documentation changesrefactor/- Code refactoringtest/- Test additions/changes
Examples:
feature/add-mirror-filtersfix/replication-slot-leakdocs/update-api-reference
Commit Messages
Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]Types:
feat: New featurefix: Bug fixdocs: Documentation changesrefactor: Code refactoringtest: Test changeschore: Build/tooling changes
Examples:
feat(api): add filter parameter to mirrors endpoint
Add support for filtering mirrors by status in GET /v1/mirrors.
Allows clients to query only running or error mirrors.fix(worker): prevent heartbeat timeout during large snapshots
Add heartbeats in snapshot partition loop to prevent Temporal
activity timeout on tables with millions of rows.
Fixes #123Pull Request Process
Create a feature branch
git checkout -b feature/my-featureMake your changes
Write code, tests, and documentation.
Test your changes
# Backend tests
cd flow && go test ./...
# Frontend tests
cd ui && npm test
# Manual testing
docker compose up -dCommit your changes
git add .
git commit -m "feat(api): add my feature"Push and create PR
git push origin feature/my-featureOpen a pull request on GitHub.
Include in your PR
- Description: What does this PR do and why?
- Testing: How did you test the changes?
- Screenshots: For UI changes
- Breaking changes: Note any breaking changes
- Related issues: Link to related issues
PR Checklist
Before submitting, ensure:
- Code follows project style guidelines
- Tests added for new functionality
- All tests pass
- Documentation updated (API docs, guides, etc.)
- Commit messages follow Conventional Commits
- No unnecessary files committed (build artifacts, IDE files)
- PR description is clear and complete
PRs are reviewed by maintainers. Be responsive to feedback and make requested changes promptly.
Running Pre-commit Checks
Install pre-commit hooks to catch issues before committing:
# Install pre-commit (if not already installed)
pip install pre-commit
# Install hooks
pre-commit install
# Run manually
pre-commit run --all-filesPre-commit hooks run:
- Go fmt and lint
- TypeScript/React ESLint and Prettier
- Markdown linting
- File size checks
- Trailing whitespace removal
Development Tips
Hot Reload
Backend: Use air for hot reload:
cd flow
# Install air
go install github.com/cosmtrek/air@latest
# Run with hot reload
airFrontend: Next.js has built-in hot reload:
cd ui
npm run devDebugging
Backend:
- Use
fmt.Println()or proper logging - Use Delve debugger:
dlv debug ./cmd/api - Check Docker logs:
docker compose logs -f bunny-worker
Frontend:
- Use browser DevTools
- React DevTools extension
console.log()debugging
Temporal:
- Use Temporal UI: http://localhost:8085
- View workflow history and activity logs
- Inspect workflow inputs/outputs
Common Development Tasks
Reset catalog database:
docker compose down -v
docker compose up -d catalogView logs:
# All services
docker compose logs -f
# Specific service
docker compose logs -f bunny-worker
# Last 100 lines
docker compose logs --tail=100 bunny-apiConnect to catalog database:
docker compose exec catalog psql -U postgres -d bunnydbRestart a service:
docker compose restart bunny-apiGetting Help
- Documentation: Read this documentation thoroughly
- GitHub Issues: Search for existing issues or open a new one
- GitHub Discussions: Ask questions and discuss ideas
- Code Comments: Read inline code comments for context
Contributor License Agreement (CLA)
By submitting a pull request or otherwise contributing to BunnyDB, you agree to the following terms:
-
Copyright Assignment: You assign all copyright and intellectual property rights in your contribution to BunnyDB.
-
License Grant: You grant BunnyDB a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license to use, reproduce, modify, distribute, sublicense, and otherwise exploit your contribution in any form.
-
Original Work: You represent that your contribution is your original work and you have the right to assign the rights granted above.
-
No Warranty: You provide your contribution “as is” without any warranty.
This CLA allows BunnyDB to maintain full control over the project’s licensing and ensures contributions can be included in both open source and commercial offerings.
By submitting a contribution, you acknowledge that you have read and agree to this Contributor License Agreement.
License
BunnyDB is licensed under the Elastic License 2.0 (ELv2). By contributing, you agree that your contributions will be licensed under the same terms.
Thank you for contributing to BunnyDB! Your contributions help make PostgreSQL replication more accessible and reliable.