# Spec: Project Setup **Capability:** project-setup **Status:** Draft **Last Updated:** 2025-11-20 ## Overview This capability establishes the foundational Python project structure, dependency management, tooling configuration, and development environment for the Clubber application. ## ADDED Requirements ### Requirement: Python project structure with uv dependency management The project MUST use Python 3.11+ with uv for fast, reliable dependency management and provide a standard src/ layout for code organization. #### Scenario: Developer initializes new development environment **Given** a developer has cloned the repository **When** they run `uv sync` **Then** all dependencies are installed in a virtual environment **And** the environment is ready for development within 30 seconds #### Scenario: Developer runs the application **Given** dependencies are installed **When** developer runs `uv run uvicorn src.main:app --reload` **Then** the FastAPI server starts on http://localhost:8000 **And** GraphQL playground is available at http://localhost:8000/graphql ### Requirement: Project configuration in pyproject.toml The project MUST define all metadata, dependencies, and tool configurations in pyproject.toml following modern Python packaging standards. **Dependencies required:** - fastapi >= 0.104.0 (Web framework) - strawberry-graphql[fastapi] >= 0.215.0 (GraphQL integration) - sqlalchemy[asyncio] >= 2.0.0 (ORM with async support) - aiosqlite >= 0.19.0 (Async SQLite driver) - alembic >= 1.12.0 (Database migrations) - pydantic-settings >= 2.0.0 (Configuration management) - uvicorn[standard] >= 0.24.0 (ASGI server) **Development dependencies required:** - pytest >= 7.4.0 (Test framework) - pytest-asyncio >= 0.21.0 (Async test support) - black >= 23.0.0 (Code formatting) - ruff >= 0.1.0 (Linting) - isort >= 5.12.0 (Import sorting) #### Scenario: Dependencies are declared with version constraints **Given** pyproject.toml exists **When** developer inspects [project.dependencies] **Then** all required packages are listed with minimum versions **And** version constraints allow patch/minor updates #### Scenario: Development tools are configured **Given** pyproject.toml contains tool configurations **When** developer runs `black .` **Then** code is formatted with line length 88 **When** developer runs `ruff check .` **Then** code is linted against configured rules ### Requirement: Source directory structure following layered architecture The project MUST organize code into src/ directory with clear separation of concerns across API, business logic, and data layers. **Required directory structure:** ``` src/ ├── __init__.py ├── main.py # FastAPI application, startup/shutdown ├── config.py # Settings and configuration ├── database.py # Database connection, session factory ├── models/ # SQLAlchemy ORM models │ ├── __init__.py │ └── member.py ├── schemas/ # Strawberry GraphQL types │ ├── __init__.py │ └── member.py └── resolvers/ # GraphQL query/mutation resolvers ├── __init__.py └── member.py ``` #### Scenario: Code is organized by architectural layer **Given** the src/ directory exists **When** a developer navigates the codebase **Then** models/ contains only SQLAlchemy ORM definitions **And** schemas/ contains only Strawberry GraphQL type definitions **And** resolvers/ contains only GraphQL resolver functions **And** each module has clear, single responsibility #### Scenario: Main application entry point is defined **Given** src/main.py exists **When** the file is imported **Then** it exports a FastAPI `app` instance **And** app includes GraphQL route at /graphql **And** app includes startup event to verify database connection ### Requirement: Testing infrastructure with pytest The project MUST provide pytest configuration for running async tests with database fixtures and code coverage reporting. #### Scenario: Async tests can be executed **Given** pytest and pytest-asyncio are installed **When** developer runs `pytest` **Then** all tests in tests/ directory are discovered **And** async test functions execute correctly **And** test results are displayed with pass/fail status #### Scenario: Database fixtures are available for tests **Given** tests/conftest.py defines database fixtures **When** a test function requests `db_session` fixture **Then** an isolated test database session is provided **And** session is rolled back after test completion **And** no test data persists between test runs ### Requirement: Code quality tooling configuration The project MUST configure black, ruff, and isort for consistent code formatting and linting with settings in pyproject.toml. **Black configuration:** - Line length: 88 characters - Target version: Python 3.11 - Skip string normalization: false **Ruff configuration:** - Line length: 88 characters - Select: E, F, W, I (pycodestyle, pyflakes, warnings, isort) - Ignore: E501 (line too long, handled by black) **Isort configuration:** - Profile: black (compatible settings) - Multi-line output: 3 (vertical hanging indent) #### Scenario: Code formatting is enforced **Given** black is configured in pyproject.toml **When** developer runs `black --check .` **Then** all Python files are checked for formatting **And** exit code is 0 if all files are formatted correctly **And** exit code is 1 if any files need formatting #### Scenario: Code quality checks pass **Given** ruff is configured in pyproject.toml **When** developer runs `ruff check .` **Then** all Python files are linted **And** no errors are reported for compliant code **And** clear error messages are shown for violations ### Requirement: Environment configuration with .env support The project MUST support environment-based configuration using .env files with pydantic-settings for type-safe config values. #### Scenario: Default configuration works for development **Given** no .env file exists **When** application starts **Then** it uses default SQLite database path **And** it runs in debug mode **And** application starts successfully #### Scenario: Environment variables override defaults **Given** .env file contains `DATABASE_URL=sqlite+aiosqlite:///./test.db` **When** application loads configuration **Then** settings.database_url equals "sqlite+aiosqlite:///./test.db" **And** custom database path is used #### Scenario: Configuration is type-safe **Given** src/config.py defines Settings class **When** invalid configuration value is provided **Then** pydantic validation raises clear error **And** application fails fast on startup ### Requirement: Development scripts for common tasks The project MUST provide executable scripts for database seeding and common development tasks. **Required scripts:** - scripts/seed.py - Populate database with sample member #### Scenario: Seed script creates sample data **Given** database schema exists from migrations **When** developer runs `uv run python scripts/seed.py` **Then** sample member is created in database **And** script is idempotent (safe to run multiple times) **And** success message is displayed ## MODIFIED Requirements None (new capability) ## REMOVED Requirements None (new capability) ## Cross-References ### Depends On None (foundational capability) ### Enables - **database-layer** - Requires project structure and dependencies - **graphql-api** - Requires FastAPI app and Strawberry installation - **member-crud** - Requires complete project infrastructure ## Implementation Notes 1. **Dependency resolution:** Use `uv add ` to ensure lock file is updated 2. **Python version:** Minimum 3.11 for modern async features and performance 3. **Import ordering:** Isort configured to work with black (no conflicts) 4. **Testing:** Pytest configuration in pyproject.toml, not separate pytest.ini 5. **Scripts:** Use `uv run` prefix to execute in correct virtual environment ## Validation Checklist - [ ] `uv sync` completes without errors - [ ] `uv run pytest` discovers and runs tests (even if no tests exist yet) - [ ] `uv run black --check .` passes - [ ] `uv run ruff check .` passes - [ ] `uv run uvicorn src.main:app --reload` starts server - [ ] pyproject.toml includes all required dependencies - [ ] src/ directory structure matches specification - [ ] .env.example file documents available settings