133 lines
4.6 KiB
Markdown
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/`
|