A production-ready template for building scalable web applications using Litestar and Pydantic.
-
Install UV:
brew install uv
-
Set up environment:
cp .env.example .env uv sync
-
Start database and run migrations:
./src/scripts/setup-test.sh uv run prisma migrate dev
-
Run the server:
uv run server
src/litestar_project/
├── api/ # API handlers and endpoints
│ ├── model.py # Model-related endpoints
│ └── system.py # System endpoints
├── model/ # Domain models
│ └── __init__.py
└── repository/ # Data access layer
├── base.py # Generic repository pattern
└── model.py # Model-specific repository
sequenceDiagram
participant C as Client
participant H as API Handler
participant R as Repository
participant P as Prisma ORM
participant DB as Database
C->>H: HTTP Request
Note over H: Input Validation (DTO)
H->>R: Repository Method Call
R->>P: Prisma Operation
P->>DB: SQL Query
DB-->>P: Database Result
P-->>R: Prisma Model
R-->>H: Domain Model
Note over H: Response Serialization
H-->>C: HTTP Response
-
API Handlers (
api/
)- Handle HTTP requests/responses
- Input validation using DTOs
- Route definitions and endpoint logic
- Dependency injection
@post("/models") async def _create_model(data: ModelCreateDTO, prisma: Prisma) -> model: repo = ModelRepository(prisma) model_data = model(id=str(uuid4()), **data.model_dump()) return await repo.create(model_data)
-
Domain Models (
model/
)- Define core business entities
- Data structure and validation
- Business logic and rules
# Generated by Prisma Client class model: id: str name: str
-
Repository Layer (
repository/
)- Data access abstraction
- Database operations
- Generic CRUD operations
class PrismaRepository(Generic[T]): async def create(self, data: T) -> T: return await self._model.create(data=data.model_dump()) async def get_by_id(self, id: str) -> T | None: return await self._model.find_unique(where={"id": id})
-
Client Request
POST /models {"name": "test"}
-
Handler Processing
- Validates input using
ModelCreateDTO
- Injects Prisma dependency
- Calls repository method
- Validates input using
-
Repository Operation
- Executes Prisma ORM operation
- Handles database transaction
- Returns domain model
-
Response
{ "id": "uuid", "name": "test" }
- Python 3.12 or higher
- PostgreSQL database
- UV package manager
Create a .env
file with the following configuration:
# Database Configuration
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/test
DIRECT_URL=postgresql://postgres:postgres@localhost:5432/test
# Server Configuration
HOST=0.0.0.0
PORT=8000
Variable | Description | Required | Default |
---|---|---|---|
DATABASE_URL | Primary database connection URL | Yes | - |
DIRECT_URL | Direct database connection (Prisma) | Yes | - |
HOST | Server host address | No | 0.0.0.0 |
PORT | Server port | No | 8000 |
# Start PostgreSQL
./src/scripts/setup-test.sh
# Create migration
uv run prisma migrate dev --name <migration_name>
# Apply migrations
uv run prisma migrate deploy
# Reset database (dev only)
uv run prisma migrate reset
- Ensure PostgreSQL is accessible
- Configure DATABASE_URL and DIRECT_URL
- Run
uv run prisma migrate deploy
Run all checks:
uv test --mypy --ruff --pytest
The project uses:
- Ruff: Linting and formatting
- MyPy: Type checking
- Pytest: Testing
.
├── src/
│ ├── litestar_project/ # Main application code
│ └── scripts/ # Utility scripts
├── tests/ # Test suite
├── .env.example # Environment template
├── .python-version # Python version spec
├── pyproject.toml # Project configuration
└── uv.lock # Dependency lock file
The application is deployed on AWS using:
- Route53: DNS management
- API Gateway/ELB: Load balancing
- ECS: Container orchestration
- ECR: Container registry
- Supabase: Database service
graph LR
subgraph aws[AWS]
subgraph dns[Domain Name Service]
routeer[Route53]
end
subgraph lb[API Gateway]
elb[Elastic Load Balancer]
end
subgraph ecs[Application Server]
service[ECS Service]
container[Container]
end
end
subgraph ext[External Services]
supabase[(Supabase DB)]
end
routeer --> elb
elb --> service
service --> container
container --> supabase
Automated deployment using GitHub Actions:
architecture-beta
group aws(cloud)[aws]
group ecs(cloud)[ECS] in aws
service ecs_service(server)[ECS Service] in ecs
service ecs_container(server)[ECS Container] in ecs
group iam(server)[IAM] in aws
service role(server)[Assume Role] in iam
group ecr(database)[ECR] in aws
service registry(database)[Container Registry] in ecr
group github(cloud)[GitHub]
service actions(server)[GitHub Actions] in github
actions:R --> L:role
role:R --> L:registry
registry:R --> L:ecs_service
ecs_service:L --> R:ecs_container
- Trigger deployment via GitHub Actions
- AWS IAM role assumption
- Build and push container to ECR
- Update ECS service
- Deploy new container version