---
title: Development
description: Development setup, workflow, and contribution guidelines for Jan Server.
---

## Development Setup

### Prerequisites

- **Go**: 1.24.6 or later
- **Docker**: For containerization
- **minikube**: Local Kubernetes development
- **Helm**: Package management
- **Make**: Build automation

### Initial Setup


1. **Clone Repository**
   ```bash
   git clone https://github.com/menloresearch/jan-server
   cd jan-server
   ```

2. **Install Development Tools**
   ```bash
   cd apps/jan-api-gateway/application
   make install
   ```

3. **Generate Code**
   ```bash
   make setup
   ```

4. **Start Development Environment**
   ```bash
   # From project root
   ./scripts/run.sh
   ```

## API Gateway Development

### Project Structure

```
apps/jan-api-gateway/application/
├── cmd/server/              # Entry point and dependency injection
│   ├── server.go           # Main server setup
│   ├── wire.go             # DI configuration
│   └── wire_gen.go         # Generated DI code
├── app/                     # Core application logic
│   ├── domain/             # Business entities
│   ├── repository/         # Data access layer
│   ├── service/            # Business logic
│   └── handler/            # HTTP handlers
├── config/                  # Configuration management
└── docs/                   # Generated API documentation
```

### Build Commands

```bash
# Install development dependencies
make install

# Generate API documentation
make doc

# Generate dependency injection code  
make wire

# Complete setup (doc + wire)
make setup

# Build application
go build -o jan-api-gateway ./cmd/server
```

### Code Generation

Jan Server uses code generation for several components:

**Swagger Documentation:**
```bash
# Generates docs/swagger.json and docs/swagger.yaml
swag init --parseDependency -g cmd/server/server.go -o docs
```

**Dependency Injection:**
```bash
# Generates wire_gen.go from wire.go providers
wire ./cmd/server
```

**Database Models:**
```bash
# Generate GORM models (when schema changes)
go run cmd/codegen/gorm/gorm.go
```

### Local Development

#### Running API Gateway Locally

```bash
cd apps/jan-api-gateway/application

# Set environment variables
export JAN_INFERENCE_MODEL_URL=http://localhost:8101
export JWT_SECRET=your-jwt-secret
export DB_POSTGRESQL_WRITE_DSN="host=localhost user=jan-user password=jan-password dbname=jan port=5432 sslmode=disable"

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

#### Database Setup

For local development, you can run PostgreSQL directly:

```bash
# Using Docker
docker run -d \
  --name jan-postgres \
  -e POSTGRES_DB=jan \
  -e POSTGRES_USER=jan-user \
  -e POSTGRES_PASSWORD=jan-password \
  -p 5432:5432 \
  postgres:14
```

## Testing

### Running Tests

```bash
# Run all tests
go test ./...

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

# Run specific test package
go test ./app/service/...
```

### Test Structure

```
app/
├── service/
│   ├── auth_service.go
│   ├── auth_service_test.go
│   ├── conversation_service.go
│   └── conversation_service_test.go
└── handler/
    ├── auth_handler.go
    ├── auth_handler_test.go
    ├── chat_handler.go
    └── chat_handler_test.go
```

### Writing Tests

Example service test:

```go
func TestAuthService_ValidateToken(t *testing.T) {
    // Setup
    service := NewAuthService(mockRepo, mockConfig)
    
    // Test cases
    tests := []struct {
        name        string
        token       string
        expectValid bool
        expectError bool
    }{
        {"valid token", "valid.jwt.token", true, false},
        {"invalid token", "invalid.token", false, true},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            valid, err := service.ValidateToken(tt.token)
            assert.Equal(t, tt.expectValid, valid)
            assert.Equal(t, tt.expectError, err != nil)
        })
    }
}
```

## Docker Development

### Building Images

```bash
# Build API gateway
docker build -t jan-api-gateway:dev ./apps/jan-api-gateway

# Build inference model
docker build -t jan-inference-model:dev ./apps/jan-inference-model
```

### Development Compose

For local development without Kubernetes:

```yaml
# docker-compose.dev.yml
version: '3.8'
services:
  postgres:
    image: postgres:14
    environment:
      POSTGRES_DB: jan
      POSTGRES_USER: jan-user
      POSTGRES_PASSWORD: jan-password
    ports:
      - "5432:5432"
      
  api-gateway:
    build: ./apps/jan-api-gateway
    ports:
      - "8080:8080"
    environment:
      - JAN_INFERENCE_MODEL_URL=http://inference-model:8101
      - DB_POSTGRESQL_WRITE_DSN=host=postgres user=jan-user password=jan-password dbname=jan port=5432 sslmode=disable
    depends_on:
      - postgres
      
  inference-model:
    build: ./apps/jan-inference-model
    ports:
      - "8101:8101"
```

## Debugging

### Go Debugging

For VS Code debugging, add to `.vscode/launch.json`:

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Jan API Gateway",
      "type": "go",
      "request": "launch",
      "mode": "auto",
      "program": "${workspaceFolder}/apps/jan-api-gateway/application/cmd/server",
      "env": {
        "JAN_INFERENCE_MODEL_URL": "http://localhost:8101",
        "JWT_SECRET": "development-secret"
      }
    }
  ]
}
```

### Application Logs

```bash
# View API gateway logs
kubectl logs deployment/jan-server-jan-api-gateway -f

# View inference model logs
kubectl logs deployment/jan-server-jan-inference-model -f

# View PostgreSQL logs
kubectl logs statefulset/jan-server-postgresql -f
```

### Log Levels

Set log level via environment variable:

```bash
export LOG_LEVEL=debug  # debug, info, warn, error
```

## Code Style and Standards

### Go Standards

- Follow [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments)
- Use `gofmt` for formatting
- Run `go vet` for static analysis
- Use meaningful variable and function names

### API Standards

- RESTful endpoint design
- OpenAPI/Swagger annotations for all endpoints
- Consistent error response format
- Proper HTTP status codes

### Git Workflow

```bash
# Create feature branch
git checkout -b feature/your-feature-name

# Make changes and commit
git add .
git commit -m "feat: add new authentication endpoint"

# Push and create PR
git push origin feature/your-feature-name
```

### Commit Message Format

Follow conventional commits:

```
feat: add new feature
fix: resolve bug in authentication  
docs: update API documentation
test: add unit tests for service layer
refactor: improve error handling
```

## Performance Testing

### Load Testing

Use [k6](https://k6.io) for API load testing:

```javascript
// load-test.js
import http from 'k6/http';

export default function () {
  const response = http.post('http://localhost:8080/api/v1/chat/completions', {
    model: 'jan-v1-4b',
    messages: [
      { role: 'user', content: 'Hello!' }
    ]
  }, {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer your-token'
    }
  });
  
  check(response, {
    'status is 200': (r) => r.status === 200,
    'response time < 5000ms': (r) => r.timings.duration < 5000,
  });
}
```

Run load test:
```bash
k6 run --vus 10 --duration 30s load-test.js
```

### Memory Profiling

Enable Go profiling endpoints:

```go
import _ "net/http/pprof"

// In main.go
go func() {
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()
```

Profile memory usage:
```bash
go tool pprof http://localhost:6060/debug/pprof/heap
```

## Contributing

### Pull Request Process

1. **Fork the repository**
2. **Create feature branch** from `main`
3. **Make changes** following code standards
4. **Add tests** for new functionality
5. **Update documentation** if needed
6. **Submit pull request** with clear description

### Code Review Checklist

- [ ] Code follows Go standards
- [ ] Tests added for new features
- [ ] Documentation updated
- [ ] API endpoints have Swagger annotations
- [ ] No breaking changes without version bump
- [ ] Security considerations addressed

### Issues and Bug Reports

When reporting bugs, include:

- **Environment**: OS, Go version, minikube version
- **Steps to reproduce**: Clear, minimal reproduction steps  
- **Expected behavior**: What should happen
- **Actual behavior**: What actually happens
- **Logs**: Relevant error messages or logs

For security issues, please report privately to the maintainers instead of creating public issues.

## Release Process

### Version Management

Jan Server uses semantic versioning (semver):

- **Major**: Breaking changes
- **Minor**: New features, backward compatible
- **Patch**: Bug fixes, backward compatible

### Building Releases

```bash
# Tag release
git tag -a v1.2.3 -m "Release v1.2.3"

# Build release images
docker build -t jan-api-gateway:v1.2.3 ./apps/jan-api-gateway
docker build -t jan-inference-model:v1.2.3 ./apps/jan-inference-model

# Push tags
git push origin v1.2.3
```

### Deployment

Production deployments follow the same Helm chart structure:

```bash
# Deploy specific version
helm install jan-server ./charts/umbrella-chart \
  --set jan-api-gateway.image.tag=v1.2.3 \
  --set jan-inference-model.image.tag=v1.2.3
```
