Skip to main content
We welcome contributions to the Ceboelha API! This guide will help you get started.

Getting Started

Prerequisites

  • Bun 1.0 or higher
  • MongoDB 7.0 or higher (local or Docker)
  • Git
  • Code editor (VS Code recommended)

Development Setup

1

Clone the Repository

git clone https://github.com/yourusername/ceboelha-api.git
cd ceboelha-api
2

Install Dependencies

bun install
3

Configure Environment

Copy the example environment file:
cp .env.example .env
Update .env with your local configuration:
PORT=3333
NODE_ENV=development
MONGODB_URI=mongodb://localhost:27017/ceboelha
JWT_ACCESS_SECRET=dev-access-secret-at-least-32-chars-long-here
JWT_REFRESH_SECRET=dev-refresh-secret-at-least-32-chars-long-here
CORS_ORIGIN=http://localhost:3000
4

Start MongoDB

Using Docker:
docker run -d \
  --name ceboelha-db \
  -p 27017:27017 \
  mongo:7
Or install and run MongoDB locally.
5

Test Database Connection

bun run test:db
6

Seed Database (Optional)

bun run db:seed
bun run db:seed-foods
7

Start Development Server

bun run dev
The API will be available at:

Code Style

We use Biome for linting and formatting.

Configuration

Biome is configured in biome.json:
{
  "formatter": {
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "semicolons": "asNeeded"
    }
  }
}

Style Guidelines

  • Indentation: 2 spaces (no tabs)
  • Line Width: 100 characters maximum
  • Quotes: Single quotes for strings
  • Semicolons: Only when needed (ASI)
  • Imports: Organized automatically by Biome

Running Linter

# Check for issues
bun run lint

# Format code
bun run format
Run bun run format before committing to ensure consistent code style.

Project Structure

src/
├── app.ts                 # Main application setup
├── index.ts               # Entry point
├── config/                # Configuration
│   ├── env.ts            # Environment variables
│   └── database.ts       # MongoDB connection
├── modules/               # Feature modules
│   ├── auth/             # Authentication
│   ├── users/            # User management
│   ├── foods/            # Food database
│   ├── diary/            # Food diary
│   ├── problematic-foods/
│   ├── insights/
│   ├── news/
│   ├── achievements/
│   └── admin/
├── shared/                # Shared code
│   ├── errors/           # Error handling
│   ├── middlewares/      # Middleware
│   ├── types/            # TypeScript types
│   └── utils/            # Utilities
└── scripts/               # Database seeds, etc.

Development Workflow

Making Changes

1

Create a Branch

git checkout -b feature/your-feature-name
Branch naming conventions:
  • feature/ - New features
  • fix/ - Bug fixes
  • docs/ - Documentation changes
  • refactor/ - Code refactoring
  • test/ - Adding tests
2

Make Your Changes

  • Write clean, readable code
  • Follow the existing code style
  • Add comments for complex logic
  • Update documentation if needed
3

Test Your Changes

# Run the API in development mode
bun run dev

# Test your endpoints using the Swagger docs
# http://localhost:3333/docs

# Or use curl/Postman/etc.
curl http://localhost:3333/health
4

Lint and Format

bun run lint
bun run format
5

Commit Your Changes

Write clear, descriptive commit messages:
git add .
git commit -m "feat: add email verification endpoint"
Commit message format:
  • feat: - New feature
  • fix: - Bug fix
  • docs: - Documentation
  • style: - Formatting
  • refactor: - Code restructuring
  • test: - Adding tests
  • chore: - Maintenance
6

Push and Create PR

git push origin feature/your-feature-name
Then create a Pull Request on GitHub.

Testing

Manual Testing

Use the Swagger documentation at http://localhost:3333/docs to test endpoints interactively.

Writing Tests

The project uses Bun’s built-in test runner. Test files should end with .test.ts.
Example test structure:
import { describe, expect, test } from 'bun:test'
import { app } from '@/app'

describe('Health Check', () => {
  test('GET /health returns 200', async () => {
    const response = await app
      .handle(new Request('http://localhost/health'))
      .then((res) => res.json())

    expect(response.success).toBe(true)
    expect(response.status).toBe('healthy')
  })
})
Run tests:
bun test

Pull Request Guidelines

Before Submitting

  • Code follows project style guidelines
  • Code has been linted and formatted
  • All changes have been tested
  • Documentation has been updated
  • Commit messages are clear and descriptive
  • No sensitive data (secrets, tokens) in commits

PR Description

Include in your PR description:
  1. What: Brief description of changes
  2. Why: Reason for the changes
  3. How: Implementation approach
  4. Testing: How you tested the changes
  5. Screenshots: If applicable (UI changes)
Example:
## What
Adds email verification for new user registrations

## Why
Enhances security by ensuring users own their email addresses

## How
- Added verification token generation
- Created email sending service
- Added verify-email endpoint
- Updated user model with verified flag

## Testing
- Tested registration flow in development
- Verified email sending works
- Tested token validation
- Tested expired token handling

Review Process

  1. Maintainers will review your PR
  2. Address any requested changes
  3. Once approved, a maintainer will merge your PR

Coding Standards

TypeScript

  • Use TypeScript for all code
  • Avoid any type (Biome warns on explicit any)
  • Define interfaces for data structures
  • Use type inference where appropriate

Error Handling

Use the custom error classes:
import { BadRequestError, NotFoundError, UnauthorizedError } from '@/shared/errors'

// Example
if (!user) {
  throw new NotFoundError('User not found')
}

Async/Await

Use async/await instead of promise chains:
// Good
async function getUser(id: string) {
  const user = await User.findById(id)
  return user
}

// Avoid
function getUser(id: string) {
  return User.findById(id).then(user => user)
}

Comments

Add comments for:
  • Complex business logic
  • Non-obvious code
  • API endpoint documentation
  • Function purposes (JSDoc style)
/**
 * Validates and refreshes JWT tokens
 * @param refreshToken - The refresh token to validate
 * @returns New access and refresh token pair
 */
async function refreshTokens(refreshToken: string) {
  // Implementation
}

Module Development

Creating a New Module

1

Create Module Directory

mkdir -p src/modules/your-module
2

Create Module Files

src/modules/your-module/
├── index.ts           # Export controller
├── controller.ts      # Elysia routes
├── service.ts         # Business logic
├── model.ts           # Mongoose schema
├── types.ts           # TypeScript types
└── validation.ts      # Input validation
3

Implement Controller

// controller.ts
import { Elysia } from 'elysia'
import { authMiddleware } from '@/shared/middlewares'

export const yourModuleController = new Elysia({ prefix: '/your-module' })
  .use(authMiddleware)
  .get('/', async () => {
    // Implementation
  })
4

Register in App

// src/app.ts
import { yourModuleController } from '@/modules/your-module'

app.group('/api', (app) =>
  app
    // ... other modules
    .use(yourModuleController)
)

Database Changes

Mongoose Models

  • Use TypeScript interfaces for model types
  • Add indexes for frequently queried fields
  • Include timestamps
  • Add validation
Example:
import mongoose from 'mongoose'

interface IExample {
  name: string
  createdAt: Date
  updatedAt: Date
}

const exampleSchema = new mongoose.Schema<IExample>(
  {
    name: { type: String, required: true, unique: true },
  },
  { timestamps: true }
)

exampleSchema.index({ name: 1 })

export const Example = mongoose.model<IExample>('Example', exampleSchema)

Migrations

If you need to migrate existing data:
  1. Create a script in src/scripts/
  2. Document the migration in your PR
  3. Test on development database first

Documentation

API Documentation

Document endpoints using Elysia’s detail option:
.get('/endpoint', handler, {
  detail: {
    tags: ['YourModule'],
    summary: 'Brief description',
    description: 'Detailed description of what this endpoint does',
  },
})

Code Documentation

  • Add JSDoc comments to functions
  • Document complex algorithms
  • Explain “why” not just “what”

Getting Help

  • Questions: Open a discussion on GitHub
  • Bugs: Open an issue with reproduction steps
  • Features: Open an issue to discuss before implementing
  • Chat: Join our Discord community (if available)

Code of Conduct

Be respectful and constructive:
  • Be welcoming to newcomers
  • Accept constructive criticism gracefully
  • Focus on what’s best for the project
  • Show empathy towards other contributors

License

By contributing, you agree that your contributions will be licensed under the MIT License.

Recognition

Contributors will be recognized in:
  • GitHub contributors page
  • Project README
  • Release notes (for significant contributions)

Build docs developers (and LLMs) love