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>
4.6 KiB
4.6 KiB
CLAUDE.md — Guia para trabajar en Vuelato
Comandos rapidos
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 usarimport ... from '~/server/utils/...'— causa error porque~apunta aapp/. - Componentes se auto-importan con prefijo de directorio:
search/AirportInput.vue-><SearchAirportInput />.
Componentes
- Usar
@nuxt/uiv4 components (UCard, UButton, UInput, UBadge, UFormField, UPopover, etc.). - Iconos:
@iconify-json/lucidecon prefijoi-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.
useAirlineNameses 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).
defineCachedEventHandlerpara cachear respuestas (flight-info: 5 min, locations/countries/airlines: 24h).- Usar
serverSupabaseServiceRolepara operaciones server-side que necesitan bypass de RLS (ej: sync/locations, sync/airlines).
Base de datos
- Tablas publicas (airports, countries, airlines, etc.) accesibles por
anonyauthenticated(SELECT). - Tablas de usuario protegidas con RLS:
auth.uid() = user_id. - Trigger
on_auth_user_createdcrea 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.nameviene vacio en rondas de polling posteriores. Se resuelve viauseAirlineNames(cache reactivo).- Fechas vacias en el payload causan 400.
useFlightSearch.buildPayloadgenera fechas por defecto (hoy + 30 dias). getRouteFlightsdevuelve trips ida+vuelta, no vuelos individuales.getInspirationspuede devolver vacio para aeropuertos pequenos — es normal.
Supabase Docker
- La imagen
supabase/postgrescrea 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
AirportInputbusca sin acentos (normaliza NFD). "malaga" encuentra "Malaga".- Modo
multipleen AirportInput: badges + input. Backspace borra ultimo. Enter/click selecciona. - Leaflet se renderiza solo client-side (
<ClientOnly>). Requiereimport 'leaflet/dist/leaflet.css'. - El
v-if="seg.company.name"falla con string vacio — usaruseAirlineNames().resolve()en su lugar.
Variables de entorno
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.