# 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.