Files
SIB/CLAUDE.md

133 lines
4.6 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
SIBU (Sistema de Transporte) is a PWA for public transportation in Panama. It has two main parts:
- **Backend**: FastAPI + SQLModel + PostgreSQL (in `backend/`), managed with `uv`
- **Frontend**: Vue 3 + Vite + TypeScript + Tailwind CSS (in `frontend/`), managed with `bun`
The frontend uses **Supabase** for auth and real-time data, while the backend provides the REST API. Both can be used together or independently.
---
## Commands
### Development
```bash
make dev # Run both backend + frontend concurrently
make dev-backend # Backend only → http://localhost:8000
make dev-frontend # Frontend only → http://localhost:5173
```
### Install
```bash
make setup # Install all deps + instructions
make install-backend # uv sync
make install-frontend # bun install
```
### Migrations
```bash
make migrate-up # Apply all pending
make migrate-down # Rollback last
make migrate-create NAME=nombre # Create new migration
make migrate-history # Show history
```
### Lint & Format
```bash
make lint-backend # ruff check --fix
make format-backend # ruff format
make lint-frontend # bun run build (type-check via vue-tsc)
```
### Tests
```bash
make test-backend # uv run pytest
make test-frontend # bun run test
```
### Database utilities
```bash
make seed # Seed initial data
make db-reset # Drop all tables + recreate (asks for confirmation)
make import-coordinates ROUTE="Boquete>David" # Import coords from Supabase
make import-coordinates ALL=true
```
---
## Package Management Rules
- **Backend**: NEVER edit `pyproject.toml` manually — use `uv add <package>`
- **Frontend**: NEVER edit `package.json` manually — use `bun add <package>`
---
## Environment Variables
### Backend (`backend/.env.development`)
```
DATABASE_URL=postgresql+asyncpg://localhost:5432/sibu_dev
ENVIRONMENT=development
DEBUG=true
```
### Frontend (`frontend/.env.development`)
```
VITE_API_URL=http://localhost:8000
VITE_GOOGLE_MAPS_API_KEY=...
VITE_SUPABASE_URL=...
VITE_SUPABASE_ANON_KEY=...
```
---
## Architecture
### Frontend Architecture
**Auth** is handled by Supabase (`src/supabase.ts`). The `useAuthStore` (Pinia) listens to `onAuthStateChange` and only reloads the user profile on `SIGNED_IN` / `INITIAL_SESSION` events — not on `TOKEN_REFRESHED` — to avoid network hangs on mobile wake.
**User roles**: `PASSENGER` (default), `DRIVER`, `PROMOTER`, `ADMIN`. The router (`src/router/index.ts`) enforces role-based access via `meta.requiresAuth` and `meta.role`. Auth check has a 3-second timeout to avoid blocking the UI.
**State**: Pinia stores in `src/stores/` — one per domain (`auth`, `route`, `busStop`, `map`, `shuttle`, `taxi`, `coupon`, `favorites`, `schedule`, `theme`). State is persisted via `pinia-plugin-persistedstate`.
**Services** (`src/services/`) are thin API clients — one per resource. They call the FastAPI backend or Supabase directly.
**Composables** (`src/composables/`) contain map logic: `useGoogleMaps`, `useMapState`, `useDirectionsRoute`, `useETA`, `useParadaCercana`, `useFlujoPrincipal`.
**Routing structure**:
- `/` — Landing
- `/map` — Main Google Maps view
- `/routes`, `/schedules`, `/bus-stop/:id` — Transit info
- `/transporte/viajes-turisticos` — Tourist shuttles (nested layout)
- `/transporte/taxis-locales` — Local taxis
- `/discover`, `/coupons`, `/favorites`, `/profile` — App features
- `/admin`, `/driver`, `/promoter` — Role-protected dashboards
**PWA**: Configured with `vite-plugin-pwa`. Service worker uses `autoUpdate`. API routes (`/api`, `/rest/v1`) are excluded from navigation fallback to prevent blank screens.
**i18n**: `vue-i18n` with `es` and `en` locales in `src/i18n/locales/`.
### Backend Architecture
```
backend/app/
├── api/ # Route handlers (FastAPI routers)
├── core/ # config.py (pydantic-settings), database.py, seed.py
├── models/ # SQLModel table models
├── schemas/ # Pydantic request/response schemas
└── services/ # Business logic layer
```
Config is loaded from `app/core/config.py` using `pydantic-settings`. Database sessions use async SQLAlchemy via `asyncpg`. All API routes use the `/api/` prefix.
### Vue Component Conventions
- Always use `<script setup>` with TypeScript
- Import paths use the `@/` alias for `src/`
- Components are split: `components/` (reusable), `views/` (full screens)
- Map-related components live in `components/map/`