Some checks failed
ci / ci (22, ubuntu-latest) (push) Has been cancelled
Nuxt 4 + Supabase + Flightics API. Incluye búsqueda de vuelos, inspiraciones, watchlist, tracking de precios y mapa interactivo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
4.6 KiB
Markdown
94 lines
4.6 KiB
Markdown
# CLAUDE.md — Guia para trabajar en Vuelato
|
|
|
|
## Comandos rapidos
|
|
|
|
```bash
|
|
pnpm dev # Dev server (localhost:3000)
|
|
pnpm supabase:up # Levantar Supabase Docker
|
|
pnpm supabase:down # Parar Supabase
|
|
pnpm supabase:reset # Reset completo (borra datos)
|
|
pnpm lint # ESLint
|
|
pnpm typecheck # Vue type checking
|
|
```
|
|
|
|
## Estructura del proyecto
|
|
|
|
```
|
|
app/
|
|
pages/ # 10 paginas (Nuxt file-based routing)
|
|
components/ # 27 componentes organizados por dominio (auth/, search/, results/, detail/, map/, inspiration/)
|
|
composables/ # 9 composables (useFlightSearch, useAuth, useWatchlist, etc.)
|
|
assets/css/ # Tailwind CSS
|
|
server/
|
|
api/ # 13 endpoints Nitro (proxy Flightics + sync + flight-info + airlines)
|
|
utils/flightics.ts # Cliente API Flightics completo (tipos + 9 funciones)
|
|
utils/wikidata.ts # Cliente SPARQL Wikidata (aerolineas)
|
|
supabase/
|
|
migrations/ # SQL init (tablas cache + usuario + RLS + trigger)
|
|
volumes/db/ # roles.sql, jwt.sql (config Supabase internal)
|
|
volumes/api/ # kong.yml (API gateway config)
|
|
docker-compose.yml # Supabase stack completo (6 servicios)
|
|
```
|
|
|
|
## Convenciones
|
|
|
|
### Nuxt 4
|
|
- El directorio raiz de la app es `app/` (no src/).
|
|
- Los server utils (`server/utils/`) se auto-importan en server routes. **No usar** `import ... from '~/server/utils/...'` — causa error porque `~` apunta a `app/`.
|
|
- Componentes se auto-importan con prefijo de directorio: `search/AirportInput.vue` -> `<SearchAirportInput />`.
|
|
|
|
### Componentes
|
|
- Usar `@nuxt/ui` v4 components (UCard, UButton, UInput, UBadge, UFormField, UPopover, etc.).
|
|
- Iconos: `@iconify-json/lucide` con prefijo `i-lucide-*`.
|
|
- No usar emojis en la UI.
|
|
- Idioma de la UI: espanol (es).
|
|
|
|
### Composables
|
|
- Cada composable maneja su propio estado reactivo.
|
|
- Los composables de usuario (useWatchlist, useRecentSearches, useUserPreferences) hacen watch del user y cargan/limpian datos automaticamente al login/logout.
|
|
- `useAirlineNames` es un cache reactivo global — aprende nombres de aerolineas de cualquier respuesta API y los resuelve en la vista.
|
|
|
|
### Server routes
|
|
- Los endpoints de Flightics son proxy directos (sin cache, excepto locations y countries que cachean 24h).
|
|
- `defineCachedEventHandler` para cachear respuestas (flight-info: 5 min, locations/countries/airlines: 24h).
|
|
- Usar `serverSupabaseServiceRole` para operaciones server-side que necesitan bypass de RLS (ej: sync/locations, sync/airlines).
|
|
|
|
### Base de datos
|
|
- Tablas publicas (airports, countries, airlines, etc.) accesibles por `anon` y `authenticated` (SELECT).
|
|
- Tablas de usuario protegidas con RLS: `auth.uid() = user_id`.
|
|
- Trigger `on_auth_user_created` crea profile automaticamente.
|
|
- Para resetear: `pnpm supabase:reset` (borra volumen Docker y reinicia).
|
|
- Para re-sincronizar aeropuertos: `curl -X POST http://localhost:3000/api/sync/locations`.
|
|
- Para re-sincronizar aerolineas: `curl -X POST http://localhost:3000/api/sync/airlines` (datos de Wikidata: IATA, ICAO, nombre, logo).
|
|
|
|
## Gotchas
|
|
|
|
### Flightics API
|
|
- La busqueda requiere polling: primera respuesta tiene `notComplete: true`. El composable hace hasta 3 rondas automaticamente.
|
|
- `company.name` viene vacio en rondas de polling posteriores. Se resuelve via `useAirlineNames` (cache reactivo).
|
|
- Fechas vacias en el payload causan 400. `useFlightSearch.buildPayload` genera fechas por defecto (hoy + 30 dias).
|
|
- `getRouteFlights` devuelve trips ida+vuelta, no vuelos individuales.
|
|
- `getInspirations` puede devolver vacio para aeropuertos pequenos — es normal.
|
|
|
|
### Supabase Docker
|
|
- La imagen `supabase/postgres` crea roles internos automaticamente. Los SQL de init solo ajustan passwords.
|
|
- Si GoTrue falla al arrancar, verificar que el volumen este limpio: `docker compose down -v && docker compose up -d`.
|
|
- Studio corre en puerto 3100 (no 3000, que es Nuxt).
|
|
- Meta corre en 8085 (remapeado de 8080 que suele estar ocupado).
|
|
|
|
### Frontend
|
|
- `AirportInput` busca sin acentos (normaliza NFD). "malaga" encuentra "Malaga".
|
|
- Modo `multiple` en AirportInput: badges + input. Backspace borra ultimo. Enter/click selecciona.
|
|
- Leaflet se renderiza solo client-side (`<ClientOnly>`). Requiere `import 'leaflet/dist/leaflet.css'`.
|
|
- El `v-if="seg.company.name"` falla con string vacio — usar `useAirlineNames().resolve()` en su lugar.
|
|
|
|
## Variables de entorno
|
|
|
|
```bash
|
|
SUPABASE_URL=http://localhost:8000 # Kong gateway
|
|
SUPABASE_KEY=eyJ... # anon key (demo JWT)
|
|
SUPABASE_SERVICE_ROLE_KEY=eyJ... # service_role key (para server-side)
|
|
```
|
|
|
|
Las keys demo estan en `.env.example`. Para produccion, generar nuevas con un JWT_SECRET propio.
|