Skip to main content

Backend Project Structure

Clean, modular FastAPI backend designed for rapid development and scalability.

Directory Structure

starter-app/
├── apps/
│ ├── backend/ # FastAPI backend application
│ │ ├── src/
│ │ │ ├── main.py # FastAPI app & router setup
│ │ │ ├── models/ # API models
│ │ │ │ └── api_models.py # Pydantic API schemas
│ │ │ ├── routers/ # API endpoints by feature
│ │ │ │ ├── chat.py # AI chat interface
│ │ │ │ ├── ocr.py # Document processing
│ │ │ │ └── embedding.py # Vector search
│ │ │ └── utils/ # Authentication & helpers
│ │ └── pyproject.toml # Backend dependencies
│ ├── worker/ # Abraxas worker application
│ │ ├── src/
│ │ │ └── main.py # Worker entry point
│ │ └── pyproject.toml # Worker dependencies
│ └── frontend/ # Next.js frontend application
│ └── ...
├── common/ # Shared code across apps
│ ├── src/common/
│ │ ├── models/ # Database models
│ │ │ └── db_models.py # SQLModel database tables
│ │ ├── services/ # Business logic & integrations
│ │ │ ├── database_service.py # DB sessions
│ │ │ ├── mistral_service.py # AI API calls
│ │ │ └── file_storage/ # File storage providers
│ │ └── workflow/ # Abraxas workflows & activities
│ ├── alembic/ # Database migrations
│ ├── docker/ # PostgreSQL & Azurite setup
│ └── pyproject.toml # Common dependencies
├── pyproject.toml # Root workspace config
└── tasks.py # Invoke task runner

Architecture Overview

Data Flow:

Request → Router → Service → Database

Response ← Pydantic ← SQLModel

Key Components:

  • apps/backend/src/main.py - FastAPI app, middleware, and router registration
  • apps/backend/src/models/ - API schemas for request/response validation
  • apps/backend/src/routers/ - API endpoints organized by feature domain
  • apps/backend/src/utils/ - Authentication, validation, and shared helpers
  • common/src/common/models/ - Shared database models (SQLModel)
  • common/src/common/services/ - Business logic, external APIs, and data access
  • common/src/common/workflow/ - Long-running processes with Abraxas
  • apps/worker/src/main.py - Abraxas worker for async processing

📊 Data Models

Database models (common/src/common/models/db_models.py):

class Task(ModelWithIdAndTimestamps, table=True):
title: str
completed: bool = Field(default=False)
user_id: UUID = Field(foreign_key="user.id")

API models (apps/backend/src/models/api_models.py):

# Auto-generated from base models
CreateTaskDTO = create_create_model(TaskBase, "CreateTask")
TaskDTO = create_read_model(TaskBase, "Task")

class UserWithTasks(UserBase):
tasks: list[TaskDTO]

Monorepo Benefits:

  • Database models shared between backend and worker
  • Services reused across applications
  • Single source of truth for business logic

🔄 Background Processing

Workflows handle complex, multi-step processes:

@workflow
class DataProcessingWorkflow:
@workflow.run
async def run(self, user_id: int) -> dict:
# Multi-step process with automatic retries
pass

Worker (apps/worker/src/main.py) processes workflows in the background.

🛠️ Development Setup

Start services with Invoke:

# From project root
uvx invoke backend # Start FastAPI backend
uvx invoke worker # Start Abraxas worker
uvx invoke frontend # Start Next.js frontend

Database migrations:

# From project root
uvx invoke update-db # Apply migrations
uvx invoke create-db-migration "Add feature" # Create new migration

Local database:

docker-compose -p starter-app -f common/docker/docker-compose.yml up postgres -d

🎯 Design Principles

  • Separation of concerns - Routes, services, models have distinct roles
  • Dependency injection - Clean, testable service dependencies
  • Type safety - SQLModel + Pydantic throughout the stack
  • Feature organization - Related code grouped together

This structure scales from simple APIs to complex applications while keeping the codebase organized and maintainable.