# Technology Stack

## Backend

- **Framework**: FastAPI (Python web framework)
- **ORM**: SQLAlchemy
- **Database**: SQLite (vfx_project_management.db)
- **Authentication**: JWT tokens (access + refresh)
- **Validation**: Pydantic schemas
- **Password Hashing**: passlib with bcrypt
- **File Handling**: python-multipart, Pillow

## Frontend

- **Framework**: Vue 3 with Composition API
- **Language**: TypeScript
- **Build Tool**: Vite
- **Styling**: Tailwind CSS
- **UI Components**: shadcn-vue (based on Radix UI)
- **State Management**: Pinia stores
- **Routing**: Vue Router with navigation guards
- **HTTP Client**: Axios with interceptors
- **Icons**: lucide-vue-next

## Common Commands

### Backend (from /backend directory)

```bash
# Start development server
uvicorn main:app --reload --host 0.0.0.0 --port 8000

# Create virtual environment
python -m venv venv

# Activate virtual environment (Windows)
venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Database utilities
python create_fresh_database.py
python create_admin.py
python create_example_data.py
```

### Frontend (from /frontend directory)

```bash
# Start development server
npm run dev

# Build for production
npm run build

# Type checking
npm run type-check

# Install dependencies
npm install
```

## API Documentation

- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc

## Development Ports

- Backend: http://localhost:8000
- Frontend: http://localhost:5173

## Important: FastAPI Trailing Slash Issue

**CRITICAL:** When adding or modifying API routes, always ensure trailing slashes match between frontend and backend to avoid 307 redirects that lose authentication headers.

### The Problem
- FastAPI redirects requests when trailing slashes don't match route definitions
- HTTP 307 redirects do NOT preserve the `Authorization` header
- This causes authenticated requests to fail with 403 Forbidden

### The Solution
**Always match trailing slashes between frontend API calls and backend route definitions:**

```typescript
// Frontend - WITH trailing slash for query params
apiClient.get(`/tasks/?shot_id=12`)

// Backend - Route defined WITH trailing slash
@router.get("/tasks/")
```

```typescript
// Frontend - WITHOUT trailing slash for path params
apiClient.get(`/tasks/${taskId}`)

// Backend - Route defined WITHOUT trailing slash
@router.get("/tasks/{task_id}")
```

### Quick Check
Look for these patterns in backend logs:
```
❌ BAD (redirect happening):
INFO: "GET /tasks?shot_id=12 HTTP/1.1" 307 Temporary Redirect
INFO: "GET /tasks/?shot_id=12 HTTP/1.1" 403 Forbidden

✅ GOOD (no redirect):
INFO: "GET /tasks/?shot_id=12 HTTP/1.1" 200 OK
```

**See:** `backend/docs/fastapi-trailing-slash-issue.md` for complete documentation.
