Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/IvanchoDev89/maleku-system/llms.txt

Use this file to discover all available pages before exploring further.

Thank you for taking the time to contribute to Maleku System! Every contribution — whether it is a bug fix, a new feature, improved documentation, or a failing test — makes the project better for everyone. Maleku System is released under the MIT License, which means your contributions will always remain open and freely available to the community.

Branching Strategy

Maleku System follows Git Flow. The develop branch is the integration target for all in-progress work; main always reflects production-ready code. Use the branch naming patterns below so that CI, reviewers, and release tooling can identify the intent of a branch at a glance:
Branch / PrefixPurposeBased onMerges into
mainProduction code
developDevelopment integrationmain
feature/*New functionalitydevelopdevelop
bugfix/*Bug correctionsdevelopdevelop
hotfix/*Urgent production fixesmainmain + develop
release/*Release preparationdevelopmain
# Make sure your local develop is up to date before branching
git checkout develop
git pull upstream develop

# Create and switch to a new feature branch
git checkout -b feature/amazing
Keep branches short-lived and focused on a single concern. Long-running branches diverge quickly from develop and create difficult merge conflicts. Open a draft PR early if you want feedback before the work is complete.

Commit Conventions

Maleku System follows the Conventional Commits specification. Every commit message must start with a type, an optional scope in parentheses, and a concise imperative description.
<type>(<scope>): <description>

[optional body]

[optional footer]

Commit Types

TypeWhen to use
featIntroduces a new feature
fixCorrects a bug
docsDocumentation-only changes
choreMaintenance tasks (deps, tooling, CI config)
refactorCode restructuring with no functional change
testAdding or updating tests
perfPerformance improvements
styleFormatting changes with no logic change
ciCI/CD pipeline changes
securitySecurity-related fixes

Examples from the Project’s Own History

# Features
git commit -m "feat(auth): add password reset flow"
git commit -m "feat(trip-planner): add Trip Planner API (/trip_planner/plans)"
git commit -m "feat(superadmin): add endpoints for users, vendors, bookings, tours, audit, content"
git commit -m "feat(monitoring): add Prometheus metrics, structured logging, GZip compression"

# Bug fixes
git commit -m "fix(properties): correct price calculation in booking"
git commit -m "fix(search): correct tours endpoint query params (q, destination, min_duration, sort)"
git commit -m "fix(auth): redirect clients to / instead of /dashboard after login"

# Documentation and chores
git commit -m "docs(api): add examples to search endpoint"
git commit -m "chore(ci): add pre-commit hooks, ruff, vitest, deploy pipeline"
git commit -m "refactor(frontend): simplify booking store"
git commit -m "test(backend): add 10 pagination unit tests and formatNumber edge case tests"
Avoid vague commit messages like fix stuff, WIP, or asdf. Descriptive commit messages make git log, git bisect, and automated changelogs significantly more useful.

Code Style

Backend (Python)

The backend enforces style automatically through ruff (linting + formatting) configured in .pre-commit-config.yaml. Black is effectively replaced by ruff-format, which uses the same 88-character line length as Black.
# Check and auto-fix linting issues
ruff check --fix backend/

# Format all Python files
ruff format backend/

# Or run both in one shot via Make
make lint-backend-fix

Frontend (TypeScript / Vue)

The frontend uses ESLint with the Vue 3 + TypeScript rule set. TypeScript strict mode is enabled in tsconfig.json.
# Lint all Vue, JS, and TS files
cd frontend && npx eslint . --ext .vue,.js,.ts

# Or via Make
make lint-frontend

Pre-commit hooks enforce both

Never push code that fails the pre-commit checks. The hooks run automatically on every git commit once installed (see Dev Setup → Pre-commit Hooks):
# Run all hooks manually before pushing
pre-commit run --all-files
The CI pipeline runs the same checks — ruff, Vitest, and the deploy step — on every pushed branch. Pre-commit hooks let you catch failures locally before they block your PR. This pipeline was introduced in the v1.0.0 release alongside integration tests, monitoring, feature flags, and rate limiting.

Pull Request Process

1

Fork the repository

Create a personal fork on GitHub and add the upstream remote so you can keep your fork in sync with main.
git remote add upstream https://github.com/IvanchoDev89/maleku-system.git
2

Create a feature branch

Branch from the latest develop using one of the naming conventions described in Branching Strategy.
git checkout develop && git pull upstream develop
git checkout -b feature/my-feature
3

Make changes and write tests

Implement your change, then add or update tests to cover the new behaviour. Backend tests go in backend/tests/; frontend tests live alongside source files or in a __tests__/ subdirectory. All tests must pass before opening a PR.
4

Commit with a conventional message

Stage your changes and commit using the Conventional Commits format. The pre-commit hooks will run automatically and block the commit if any check fails.
git add .
git commit -m "feat(tours): add minimum rating filter to search endpoint"
5

Push and open a Pull Request

Push your branch to your fork and open a PR against develop on the upstream repository. Fill in the PR template: describe the change, its type, how it was tested, and link any related issues.
git push origin feature/my-feature
6

Address review feedback

Respond to reviewer comments and push additional commits to the same branch. Avoid force-pushing after a review has started — add new commits instead so the reviewer can see what changed. Once approved, a maintainer will squash-merge your branch into develop.

PR Checklist

Before marking your PR as ready for review, confirm the following:
  • Code follows style guidelines (pre-commit run --all-files passes)
  • All existing tests pass
  • New tests cover the new or changed behaviour
  • No console.log or debug code left in
  • Commit messages follow the Conventional Commits convention
  • Documentation updated if the change affects public APIs or developer workflows

Backend Standards

Async All the Way

Every route handler, service method, and database call must be async. Maleku System uses SQLAlchemy 2.x with asyncpg as the async PostgreSQL driver — never use the synchronous session in application code.
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import APIRouter, Depends
from app.api import deps

router = APIRouter()

@router.get("/{tour_id}", response_model=TourResponse, summary="Get a tour by ID")
async def get_tour(
    tour_id: int,
    db: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user),
) -> TourResponse:
    """Return a single tour record.

    - **tour_id**: The integer primary key of the tour
    - Returns: Full tour detail with availability and vendor info
    """
    service = TourService(db)
    return await service.get_by_id(tour_id)

Pydantic v2 Schemas

All request bodies and response models must use Pydantic v2 (pydantic>=2.10.0). Define separate Create, Update, and Response schemas — never expose ORM models directly.
from pydantic import BaseModel, Field
from datetime import datetime

class TourCreate(BaseModel):
    title: str = Field(..., min_length=3, max_length=255)
    duration_hours: int = Field(..., ge=1)
    price_usd: float = Field(..., gt=0)

class TourResponse(BaseModel):
    id: int
    title: str
    duration_hours: int
    price_usd: float
    created_at: datetime

    model_config = {"from_attributes": True}

Structured Logging

Use get_logger(__name__) for all logging throughout the application. Never use print() in application code.
from app.core.logging import get_logger

logger = get_logger(__name__)

async def process_booking(booking_id: int) -> None:
    logger.info("Processing booking", extra={"booking_id": booking_id})

Swagger Documentation

Every route decorator must include a summary and description. As of v1.0.0, Swagger summaries, descriptions, and tags are present on all 52 endpoints — new endpoints must maintain this standard.
@router.post(
    "/",
    response_model=TourResponse,
    status_code=201,
    summary="Create a new tour",
    description="Creates a new tour listing for the authenticated vendor. Requires the `vendor` role.",
    tags=["Tours"],
)
async def create_tour(...):
    ...

Frontend Standards

Composition API with <script setup>

Every component must use the Composition API with the <script setup lang="ts"> single-file component syntax. Options API and defineComponent wrappers are not accepted in new code.
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { Tour } from '~/types'

interface Props {
  tours: Tour[]
  loading?: boolean
}

const props = defineProps<Props>()
const emit = defineEmits<{ select: [tour: Tour] }>()

const selected = ref<Tour | null>(null)
const hasTours = computed(() => props.tours.length > 0)

const handleSelect = (tour: Tour) => {
  selected.value = tour
  emit('select', tour)
}
</script>

Pinia for State Management

Global and cross-component state must live in Pinia stores. The @pinia/nuxt module is already registered — define stores using the Composition API syntax (defineStore with a setup function).
// stores/tourStore.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Tour } from '~/types'

export const useTourStore = defineStore('tour', () => {
  const tours = ref<Tour[]>([])
  const loading = ref(false)

  async function fetchTours() {
    loading.value = true
    try {
      tours.value = await $fetch('/api/v1/tours')
    } finally {
      loading.value = false
    }
  }

  return { tours, loading, fetchTours }
})

Composables for Reusable Logic

Extract reusable reactive logic into composables under composables/. Name them with the use prefix (e.g., useAuth.ts, useSearch.ts).

TypeScript Strict Mode

TypeScript strict mode is enabled. All new files must be .ts or use lang="ts" in <script setup>. Avoid any — use explicit types or unknown with type guards.

i18n Keys for All User-Visible Strings

The project supports English (en), Spanish (es), and French (fr) via @nuxtjs/i18n. Every string rendered to the user must reference an i18n key — never hard-code display text in templates or composables.
<template>
  <p>{{ $t('tours.noResults') }}</p>
</template>
// In a composable
const { t } = useI18n()
const label = t('filters.minRating')

Security Reporting

Maleku System takes security seriously. Please review the full SECURITY.md before disclosing any vulnerability.
Do NOT open a public GitHub issue for security vulnerabilities. Public disclosure before a fix is deployed puts all users at risk.
Instead, report vulnerabilities privately by emailing security@costaricatravel.dev. You should receive a response within 48 hours. If you do not, follow up to confirm receipt of your original message. Include the following in your report:
  • A clear description of the vulnerability
  • Step-by-step instructions to reproduce it
  • The affected endpoints or components
  • Any proof-of-concept code or screenshots (if available)
  • The potential impact

What to Expect

StepTimeline
AcknowledgementWithin 48 hours
Estimated fix timelineProvided in first response
Fix deployed notificationSent when patch is live
Coordinated public disclosureWithin 90-day disclosure window
Version 1.x is the only currently supported release. Vulnerabilities reported against versions below 1.0 will not receive patches.
Maleku System uses bcrypt (11 rounds) for password hashing, SLOWAPI rate limiting (60 req/min per IP, 5 login attempts per 15 min), JWT with token blacklisting, and parameterized SQLAlchemy queries throughout. Consult SECURITY.md for the full list of security measures in place.

Build docs developers (and LLMs) love