> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xem.email/llms.txt
> Use this file to discover all available pages before exploring further.

# Contributing Guide

> How to contribute to the Posthoot backend project

# Contributing Guide

Thank you for your interest in contributing to the Posthoot backend! This guide will help you get started with the development process.

## Table of Contents

* [Code of Conduct](#code-of-conduct)
* [Getting Started](#getting-started)
* [Development Setup](#development-setup)
* [Project Structure](#project-structure)
* [Development Workflow](#development-workflow)
* [Coding Standards](#coding-standards)
* [Testing](#testing)
* [Documentation](#documentation)
* [Submitting Changes](#submitting-changes)
* [Release Process](#release-process)

## Code of Conduct

This project adheres to the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/). By participating, you are expected to uphold this code.

## Getting Started

### Prerequisites

* **Go 1.21+** - [Download here](https://golang.org/dl/)
* **PostgreSQL 14+** - [Download here](https://www.postgresql.org/download/)
* **Redis 6+** - [Download here](https://redis.io/download)
* **Git** - [Download here](https://git-scm.com/downloads)
* **Docker** (optional) - [Download here](https://www.docker.com/products/docker-desktop)

### Fork and Clone

1. **Fork the repository** on GitHub
2. **Clone your fork** locally:

```bash theme={"dark"}
git clone https://github.com/YOUR_USERNAME/posthoot-backend.git
cd posthoot-backend
```

3. **Add the upstream remote**:

```bash theme={"dark"}
git remote add upstream https://github.com/posthoot/posthoot-backend.go.git
```

## Development Setup

### 1. Environment Configuration

Create a development environment file:

```bash theme={"dark"}
cp .env.example .env.dev
```

Edit `.env.dev` with your development settings:

```env theme={"dark"}
# Development Configuration
SERVER_HOST=localhost
SERVER_PORT=8080
PUBLIC_URL=http://localhost:8080

# Database Configuration
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=posthoot_dev
POSTGRES_PASSWORD=dev_password
POSTGRES_DB=posthoot_dev
POSTGRES_SSLMODE=disable

# JWT Configuration
JWT_SECRET=dev_jwt_secret_key_for_development_only

# Redis Configuration
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=1

# Super Admin Configuration
SUPERADMIN_EMAIL=dev@example.com
SUPERADMIN_PASSWORD=dev_password
SUPERADMIN_NAME=Dev Admin

# Storage Configuration
STORAGE_PROVIDER=local
STORAGE_BASE_PATH=./storage/dev

# Worker Configuration
WORKER_CONCURRENCY=2
WORKER_QUEUE_SIZE=50

# Development Features
GIN_MODE=debug
LOG_LEVEL=debug
```

### 2. Database Setup

Create a development database:

```bash theme={"dark"}
# Connect to PostgreSQL
sudo -u postgres psql

# Create development database
CREATE DATABASE posthoot_dev;
CREATE USER posthoot_dev WITH PASSWORD 'dev_password';
GRANT ALL PRIVILEGES ON DATABASE posthoot_dev TO posthoot_dev;
\q
```

### 3. Install Dependencies

```bash theme={"dark"}
go mod download
go mod tidy
```

### 4. Run the Application

```bash theme={"dark"}
# Load development environment
export $(cat .env.dev | xargs)

# Run the server
go run cmd/server/main.go
```

### 5. Using Docker for Development

Create a `docker-compose.dev.yml` file:

```yaml theme={"dark"}
version: '3.8'

services:
  posthoot-backend-dev:
    build: .
    ports:
      - "8080:8080"
    environment:
      - POSTGRES_HOST=postgres-dev
      - REDIS_HOST=redis-dev
    depends_on:
      - postgres-dev
      - redis-dev
    volumes:
      - .:/app
      - ./storage/dev:/app/storage
    command: go run cmd/server/main.go
    env_file:
      - .env.dev

  postgres-dev:
    image: postgres:14
    environment:
      - POSTGRES_DB=posthoot_dev
      - POSTGRES_USER=posthoot_dev
      - POSTGRES_PASSWORD=dev_password
    ports:
      - "5432:5432"
    volumes:
      - postgres_dev_data:/var/lib/postgresql/data

  redis-dev:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_dev_data:/data

volumes:
  postgres_dev_data:
  redis_dev_data:
```

Run the development environment:

```bash theme={"dark"}
docker-compose -f docker-compose.dev.yml up -d
```

## Project Structure

```
📦 posthoot-backend
 ┣ 📂 cmd                     # Application entry points
 ┃ ┗ 📂 server               # Main server binary
 ┃   ┗ 📜 main.go           # Server entry point
 ┣ 📂 internal               # Private application code
 ┃ ┣ 📂 api                 # API layer
 ┃ ┃ ┣ 📂 middleware        # Custom middlewares
 ┃ ┃ ┃ ┣ 📜 auth.go        # Authentication middleware
 ┃ ┃ ┃ ┣ 📜 permissions.go  # Permission middleware
 ┃ ┃ ┃ ┗ 📜 ratelimit.go   # Rate limiting middleware
 ┃ ┃ ┣ 📂 validator         # Request validators
 ┃ ┃ ┣ 📂 controllers       # API controllers
 ┃ ┃ ┣ 📜 routes.go        # Route definitions
 ┃ ┃ ┗ 📜 server.go        # Server setup
 ┃ ┣ 📂 config              # Configuration management
 ┃ ┃ ┣ 📜 config.go        # Configuration structs
 ┃ ┃ ┗ 📜 loader.go        # Environment loading
 ┃ ┣ 📂 events              # Event bus system
 ┃ ┃ ┣ 📜 bus.go           # Event bus implementation
 ┃ ┃ ┗ 📜 handlers.go      # Event handlers
 ┃ ┣ 📂 handlers            # HTTP request handlers
 ┃ ┃ ┣ 📜 auth.go          # Authentication handlers
 ┃ ┃ ┣ 📜 campaigns.go     # Campaign handlers
 ┃ ┃ ┣ 📜 users.go         # User handlers
 ┃ ┃ ┗ 📜 webhooks.go      # Webhook handlers
 ┃ ┣ 📂 models              # Database models
 ┃ ┃ ┣ 📜 user.go          # User model
 ┃ ┃ ┣ 📜 campaign.go      # Campaign model
 ┃ ┃ ┣ 📜 team.go          # Team model
 ┃ ┃ ┣ 📜 permissions.go   # Permission model
 ┃ ┃ ┗ 📜 seed.go          # Database seeding
 ┃ ┣ 📂 routes              # Route definitions
 ┃ ┃ ┣ 📜 auth.go          # Auth routes
 ┃ ┃ ┣ 📜 campaigns.go     # Campaign routes
 ┃ ┃ ┗ 📜 api.go           # API route groups
 ┃ ┣ 📂 services            # Business logic layer
 ┃ ┃ ┣ 📜 email.go         # Email service
 ┃ ┃ ┣ 📜 auth.go          # Authentication service
 ┃ ┃ ┗ 📜 campaign.go      # Campaign service
 ┃ ┣ 📂 tasks               # Background tasks
 ┃ ┃ ┣ 📜 email.go         # Email sending tasks
 ┃ ┃ ┗ 📜 cleanup.go       # Cleanup tasks
 ┃ ┗ 📂 utils               # Utility functions
 ┃   ┣ 📜 logger.go        # Logging utilities
 ┃   ┣ 📜 redis.go         # Redis utilities
 ┃   ┗ 📜 validator.go     # Validation utilities
 ┣ 📂 migrations            # Database migrations
 ┣ 📂 storage               # Local storage
 ┣ 📂 docs                  # Documentation
 ┣ 📂 scripts               # Build and deployment scripts
 ┣ 📜 .env.example         # Environment template
 ┣ 📜 .gitignore           # Git ignore rules
 ┣ 📜 Dockerfile           # Docker configuration
 ┣ 📜 docker-compose.yml   # Docker Compose config
 ┣ 📜 go.mod               # Go module definition
 ┣ 📜 go.sum               # Go module checksums
 ┣ 📜 Makefile             # Build automation
 ┗ 📜 README.md            # Project documentation
```

## Development Workflow

### 1. Branch Strategy

We use a feature branch workflow:

```bash theme={"dark"}
# Create a new feature branch
git checkout -b feature/your-feature-name

# Or for bug fixes
git checkout -b fix/your-bug-description

# Or for documentation
git checkout -b docs/your-doc-update
```

### 2. Making Changes

1. **Create a feature branch** from `main`
2. **Make your changes** following the coding standards
3. **Write tests** for new functionality
4. **Update documentation** as needed
5. **Commit your changes** with clear messages

### 3. Commit Message Format

Use conventional commit format:

```
type(scope): description

[optional body]

[optional footer]
```

Examples:

```
feat(auth): add Google OAuth support
fix(api): resolve rate limiting issue
docs(readme): update installation instructions
test(handlers): add unit tests for user creation
refactor(models): simplify permission structure
```

### 4. Keeping Your Branch Updated

```bash theme={"dark"}
# Fetch latest changes
git fetch upstream

# Rebase your branch on main
git rebase upstream/main
```

## Coding Standards

### 1. Go Code Style

Follow the [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments):

* Use `gofmt` for code formatting
* Follow naming conventions
* Use meaningful variable names
* Keep functions small and focused
* Add comments for exported functions

### 2. Code Organization

* **Package structure**: Follow standard Go package layout
* **File naming**: Use descriptive names (e.g., `user_handler.go`)
* **Function organization**: Group related functions together
* **Import organization**: Use standard library, third-party, then local imports

### 3. Error Handling

```go theme={"dark"}
// Good: Handle errors explicitly
if err != nil {
    return fmt.Errorf("failed to create user: %w", err)
}

// Good: Use custom error types for specific errors
var ErrUserNotFound = errors.New("user not found")

// Good: Log errors with context
log.Error("failed to process email", "error", err, "user_id", userID)
```

### 4. Database Operations

```go theme={"dark"}
// Good: Use transactions for related operations
func (s *Service) CreateUserWithTeam(ctx context.Context, user *User, team *Team) error {
    return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
        if err := tx.Create(team).Error; err != nil {
            return err
        }
        user.TeamID = team.ID
        return tx.Create(user).Error
    })
}

// Good: Use proper indexing
// Add indexes in migrations for frequently queried columns
```

### 5. API Design

```go theme={"dark"}
// Good: Consistent response structure
type APIResponse struct {
    Success bool        `json:"success"`
    Data    interface{} `json:"data,omitempty"`
    Error   string      `json:"error,omitempty"`
    Meta    *Meta       `json:"meta,omitempty"`
}

// Good: Use proper HTTP status codes
func (h *Handler) CreateUser(c echo.Context) error {
    user := &models.User{}
    if err := c.Bind(user); err != nil {
        return echo.NewHTTPError(http.StatusBadRequest, "invalid request body")
    }
    
    if err := h.service.CreateUser(c.Request().Context(), user); err != nil {
        return echo.NewHTTPError(http.StatusInternalServerError, "failed to create user")
    }
    
    return c.JSON(http.StatusCreated, APIResponse{
        Success: true,
        Data:    user,
    })
}
```

## Testing

### 1. Unit Tests

Create tests for all new functionality:

```go theme={"dark"}
// handlers/user_test.go
package handlers

import (
    "testing"
    "net/http"
    "net/http/httptest"
    "strings"
    
    "github.com/labstack/echo/v4"
    "github.com/stretchr/testify/assert"
)

func TestCreateUser(t *testing.T) {
    // Setup
    e := echo.New()
    req := httptest.NewRequest(http.MethodPost, "/users", strings.NewReader(`{
        "email": "test@example.com",
        "password": "password123",
        "first_name": "Test",
        "last_name": "User"
    }`))
    req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
    rec := httptest.NewRecorder()
    c := e.NewContext(req, rec)
    
    // Test
    handler := &UserHandler{}
    err := handler.CreateUser(c)
    
    // Assertions
    assert.NoError(t, err)
    assert.Equal(t, http.StatusCreated, rec.Code)
}
```

### 2. Integration Tests

Test API endpoints with a real database:

```go theme={"dark"}
// integration/user_test.go
package integration

import (
    "testing"
    "net/http"
    
    "github.com/stretchr/testify/suite"
)

type UserTestSuite struct {
    suite.Suite
    app *TestApp
}

func (suite *UserTestSuite) SetupSuite() {
    suite.app = NewTestApp()
}

func (suite *UserTestSuite) TearDownSuite() {
    suite.app.Cleanup()
}

func (suite *UserTestSuite) TestUserRegistration() {
    // Test user registration flow
    resp, err := suite.app.Post("/api/v1/auth/register", map[string]interface{}{
        "email": "test@example.com",
        "password": "password123",
        "first_name": "Test",
        "last_name": "User",
    })
    
    suite.NoError(err)
    suite.Equal(http.StatusCreated, resp.Code)
}

func TestUserTestSuite(t *testing.T) {
    suite.Run(t, new(UserTestSuite))
}
```

### 3. Running Tests

```bash theme={"dark"}
# Run all tests
go test ./...

# Run tests with coverage
go test -cover ./...

# Run tests with verbose output
go test -v ./...

# Run specific test
go test -v ./internal/handlers -run TestCreateUser

# Run integration tests
go test -v ./integration/...
```

### 4. Test Database

Use a separate test database:

```go theme={"dark"}
// testutils/db.go
package testutils

import (
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

func NewTestDB() *gorm.DB {
    dsn := "host=localhost user=posthoot_test password=test_password dbname=posthoot_test port=5432 sslmode=disable"
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }
    
    // Run migrations
    // AutoMigrate(&models.User{}, &models.Team{}, ...)
    
    return db
}
```

## Documentation

### 1. Code Documentation

Document all exported functions and types:

```go theme={"dark"}
// User represents a user in the system
type User struct {
    ID        uint      `json:"id" gorm:"primaryKey"`
    Email     string    `json:"email" gorm:"uniqueIndex;not null"`
    Password  string    `json:"-" gorm:"not null"`
    FirstName string    `json:"first_name" gorm:"not null"`
    LastName  string    `json:"last_name" gorm:"not null"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
}

// CreateUser creates a new user in the database
// It validates the user data and hashes the password before saving
func (s *UserService) CreateUser(ctx context.Context, user *User) error {
    // Implementation...
}
```

### 2. API Documentation

Update Swagger documentation for new endpoints:

```go theme={"dark"}
// @Summary Create a new user
// @Description Create a new user account with the provided information
// @Tags users
// @Accept json
// @Produce json
// @Param user body CreateUserRequest true "User information"
// @Success 201 {object} APIResponse{data=User}
// @Failure 400 {object} APIResponse{error=string}
// @Failure 500 {object} APIResponse{error=string}
// @Router /api/v1/users [post]
func (h *UserHandler) CreateUser(c echo.Context) error {
    // Implementation...
}
```

### 3. README Updates

Update relevant documentation when adding new features:

* **README.md**: Update feature list and installation instructions
* **API Documentation**: Add new endpoint documentation
* **Self-hosting guide**: Update configuration options

## Submitting Changes

### 1. Pre-submission Checklist

Before submitting a pull request, ensure:

* [ ] **Code compiles** without errors
* [ ] **Tests pass** (unit and integration)
* [ ] **Code is formatted** (`gofmt -w .`)
* [ ] **Linting passes** (`golangci-lint run`)
* [ ] **Documentation is updated**
* [ ] **Commit messages** follow conventional format
* [ ] **Branch is up to date** with main

### 2. Creating a Pull Request

1. **Push your branch** to your fork:

```bash theme={"dark"}
git push origin feature/your-feature-name
```

2. **Create a pull request** on GitHub with:
   * Clear title describing the change
   * Detailed description of what was changed
   * Reference to any related issues
   * Screenshots (if UI changes)

3. **Template for PR description**:

```markdown theme={"dark"}
## Description
Brief description of the changes made.

## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing completed

## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No breaking changes (or documented)

## Related Issues
Closes #123
```

### 3. Code Review Process

1. **Automated checks** will run on your PR
2. **Reviewers** will be assigned automatically
3. **Address feedback** by pushing additional commits
4. **Maintainers** will merge when approved

## Release Process

### 1. Version Management

We use semantic versioning (SemVer):

* **MAJOR.MINOR.PATCH** (e.g., 1.2.3)
* **MAJOR**: Breaking changes
* **MINOR**: New features (backward compatible)
* **PATCH**: Bug fixes (backward compatible)

### 2. Release Checklist

Before a release:

* [ ] **All tests pass**
* [ ] **Documentation is updated**
* [ ] **Changelog is updated**
* [ ] **Version is bumped**
* [ ] **Release notes are prepared**

### 3. Creating a Release

1. **Create a release branch**:

```bash theme={"dark"}
git checkout -b release/v1.2.0
```

2. **Update version** in relevant files
3. **Update changelog** with new features/fixes
4. **Create a PR** for the release
5. **Tag the release** after merge:

```bash theme={"dark"}
git tag v1.2.0
git push origin v1.2.0
```

## Getting Help

### 1. Questions and Discussions

* **GitHub Discussions**: For general questions and feature discussions
* **GitHub Issues**: For bug reports and feature requests
* **Discord**: For real-time discussions (if available)

### 2. Issue Templates

Use the appropriate issue template:

* **Bug Report**: For reporting bugs
* **Feature Request**: For suggesting new features
* **Documentation**: For documentation improvements

### 3. Community Guidelines

* Be respectful and inclusive
* Provide context when asking questions
* Help others when you can
* Follow the code of conduct

## Recognition

Contributors are recognized in several ways:

* **Contributors list** on GitHub
* **Release notes** for significant contributions
* **Special thanks** in documentation
* **Contributor badges** for regular contributors

Thank you for contributing to the Posthoot backend project! Your contributions help make this project better for everyone.
