4.6 KiB
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 withuv - Frontend: Vue 3 + Vite + TypeScript + Tailwind CSS (in
frontend/), managed withbun
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
make dev # Run both backend + frontend concurrently
make dev-backend # Backend only → http://localhost:8000
make dev-frontend # Frontend only → http://localhost:5173
Install
make setup # Install all deps + instructions
make install-backend # uv sync
make install-frontend # bun install
Migrations
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
make lint-backend # ruff check --fix
make format-backend # ruff format
make lint-frontend # bun run build (type-check via vue-tsc)
Tests
make test-backend # uv run pytest
make test-frontend # bun run test
Database utilities
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.tomlmanually — useuv add <package> - Frontend: NEVER edit
package.jsonmanually — usebun 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 forsrc/ - Components are split:
components/(reusable),views/(full screens) - Map-related components live in
components/map/