home
  • Spanish (ES)
  • English (UK)
  • Portuguese (PT)
  • star Destacados
  • Hermes Agent
  • draw Proyectos UX
  • person Sobre mí
  • mail Contacto
arrow_back Volver al proyecto Inicio

Documentación del proyecto

Documentación · Concert-Connect

11 archivos markdown (producto, arquitectura, API, auth, datos, deploy…).

En esta página Visión general 0% expand_more
Visión general Enlaces Stack Producto y features Problema Solución Características Landing Eventos Mapa Conexiones Perfil (Backstage) Invitados Arquitectura Diagrama lógico Capas Decisiones de runtime Estructura del workspace Superficie API Código de ejemplo (health) Autenticación Clerk Flujo Por qué proxy Qué no hay Modelo de datos users events event_attendees matches messages Deploy Replit Env Local Decisiones de producto y tech Match automático, no swipe Polling frente a WebSocket OpenAPI como fuente de verdad Clerk, no auth casera Invitados ven el cartel Retos y resultados Google Maps Loader Keys de Maps JIT user vs “Anonymous” Resultado Front React (no Angular) Qué se aplica Por qué está este doc

01-overview.md

Visión general · Concert-Connect (ConcierGo)

Concert-Connect es el repo de ConcierGo: una app web mobile-first para ir a conciertos cuando no tienes compañía. Login con Clerk, feed y mapa de bolos, matching automático al apuntarte y chat 1-1.

El producto vive en un workspace pnpm: front React+Vite (artifacts/conciergo), API Express (artifacts/api-server), contratos OpenAPI (lib/api-spec) y Postgres + Drizzle (lib/db).

Enlaces

  • GitHub: Criscode2022/Concert-Connect
  • Replit: replit.com/@cristiancode202/Concert-Connect
  • Health: GET /api/healthz → { "status": "ok" }

Stack

CapaTecnología
Monorepopnpm workspaces, TypeScript 5.9
WebReact, Vite, Tailwind 4, shadcn/ui, Framer Motion, Wouter
AuthClerk (@clerk/react + @clerk/express), proxy /api/__clerk
APIExpress 5, OpenAPI + Orval + Zod
DatosPostgreSQL + Drizzle ORM
MapasGoogle Maps JS + Places

02-product.md

Producto y features

Problema

Un gran bolo se pierde si no hay con quién ir. Los grupos de WhatsApp son caos; Tinder no es para conciertos; las apps de entradas no conectan a extraños con el mismo cartel.

Solución

ConcierGo: feed de eventos, mapa, “voy” y match automático con el resto de asistentes. Cada match abre un chat 1-1 para cuadrar el viaje o el foso.

Características

Landing

Copy de cartel: «No dejes que un gran bolo se pierda». Entrar / Unirse (Clerk). Invitados pueden explorar eventos y mapa.

Eventos

Lista con filtro por género. Cards compactas (artista, venue, fecha). Usuarios logueados se apuntan; FAB para crear evento (venue via Places).

Mapa

Pins de Google Maps. Click → ficha y apuntarse. Invitados ven el mapa.

Conexiones

Matches del usuario + badge de no leídos. Chat por polling (React Query, 3 s).

Perfil (Backstage)

Nombre, ciudad, géneros, avatar de Clerk.

Invitados

Eventos y mapa abiertos. Conexiones, perfil y crear evento piden sesión.

03-architecture.md

Arquitectura

Diagrama lógico

React (Vite)  ConcierGo
    │  Clerk (sesión)
    │  React Query → /api/*
    ▼
Express 5  (/api)
    │  requireAuth → JIT user en Postgres
    │  clerkProxyMiddleware → /api/__clerk
    ▼
PostgreSQL  (Drizzle)
    users, events, event_attendees, matches, messages

Capas

  1. Front — artifacts/conciergo: Wouter, shadcn, layout sidebar desktop + bottom nav móvil.
  2. API — artifacts/api-server: rutas users, events, matches, health.
  3. Contrato — lib/api-spec/openapi.yaml → Orval genera hooks (lib/api-client-react) y Zod (lib/api-zod).
  4. DB — lib/db Drizzle.

Decisiones de runtime

  • Match automático al marcar asistencia: un match (y chat) con cada otro asistente.
  • Chat por polling, no WebSocket (deploy Replit más simple).
  • JIT provisioning: el primer requireAuth inserta al usuario desde claims de Clerk.

04-monorepo.md

Estructura (pnpm workspace)

No es Angular/Nest. Es un monorepo Replit (pnpm-workspace.yaml).

PathRol
artifacts/conciergoApp React + Vite
artifacts/api-serverExpress + Clerk
artifacts/mockup-sandboxSandbox de UI (no prod)
lib/api-specOpenAPI + Orval
lib/api-client-reactHooks generados
lib/api-zodSchemas Zod generados
lib/dbDrizzle + schema
replit.mdRunbook del producto

Tras cambiar el spec: pnpm --filter @workspace/api-spec run codegen.

05-api.md

Superficie API

Base: /api. Fuente: lib/api-spec/openapi.yaml.

MétodoRutaAuthQué hace
GET/healthzpública{ status: "ok" }
GET/PUT/users/meClerkPerfil propio
GET/users/:userIdClerkPerfil ajeno
GET/eventsopcionalFeed + isAttending
POST/eventsClerkCrear bolo
POST/DELETE/events/:id/attendClerkApuntarse / salir (crea matches)
GET/matchesClerkConexiones + unread
GET/POST/matches/:id/messagesClerkChat

Código de ejemplo (health)

router.get("/healthz", (_req, res) => {
  const data = HealthCheckResponse.parse({ status: "ok" });
  res.json(data);
});

HealthCheckResponse sale de Zod generado. Si el spec y el handler se desalinean, falla el typecheck.

06-auth.md

Autenticación (Clerk)

Flujo

  1. Landing → Entrar / Unirse (@clerk/react).
  2. El front habla con Clerk vía proxy /api/__clerk (mismo host en Replit).
  3. Las rutas protegidas usan requireAuth:
    • Sin userId → 401.
    • Primera llamada → INSERT en users (nombre + avatar de Clerk).
  4. Invitados ven Eventos y Mapa; Conexiones/Perfil/crear evento piden sesión.

Por qué proxy

En .replit.app y custom domains, el proxy evita problemas de cookies de Clerk entre orígenes.

Qué no hay

No hay PIN ni JWT propio (eso es Task Cloud). La sesión es de Clerk; la fila de negocio es users.clerk_id.

07-data-model.md

Modelo de datos (Drizzle / Postgres)

users

id, clerk_id (único), name, bio, avatar_url, music_genres[], city, created_at.

events

title, artist_name, venue_name, venue_address, date, lat, lng, genre, image_url, created_by_user_id.

event_attendees

Quién va a qué bolo. Al insertar, el servidor crea matches con el resto de asistentes.

matches

event_id + user_id_1 + user_id_2 (unique). Un chat por pareja y evento.

messages

Mensajes del match. El front cuenta unreadCount para el badge de Conexiones.

08-deploy-vercel.md

Deploy (Replit Autoscale)

No es Vercel/Netlify. .replit declara:

[deployment]
router = "application"
deploymentTarget = "autoscale"

El mismo proceso sirve el Vite build y Express (/api, /api/__clerk).

Env

VariableDónde
DATABASE_URLPostgres 16 del Repl
CLERK_SECRET_KEY / CLERK_PUBLISHABLE_KEYAPI
VITE_CLERK_PUBLISHABLE_KEYFront
VITE_GOOGLE_MAPS_API_KEYMaps + Places

La key de Maps debe tener Maps JavaScript API y Places API.

Local

pnpm --filter @workspace/api-server run dev
pnpm --filter @workspace/conciergo run dev

09-decisions.md

Decisiones

Match automático, no swipe

Apuntarse a un evento es el gesto de matching. Evita un segundo feed tipo dating.

Polling frente a WebSocket

3 s con React Query. Suficiente para cuadrar un bolo; el deploy Replit no necesita un proceso WS aparte.

OpenAPI como fuente de verdad

Orval genera hooks y Zod. El typecheck del workspace pilla desvíos entre front y API.

Clerk, no auth casera

Email/social y sesión los resuelve Clerk. El dominio de negocio es el perfil y los matches.

Invitados ven el cartel

Eventos + mapa sin login para que el landing no sea un muro. Crear y chatear sí piden cuenta.

10-challenges-results.md

Retos y aprendizajes

Google Maps Loader

La API clásica Loader de @googlemaps/js-api-loader v2 ya no existe (setOptions + importLibrary). Un preview Replit llegó a mostrar el overlay rojo de Vite. Hay que alinear la versión del loader con el código.

Keys de Maps

Sin Maps JS + Places activados, el mapa enseña «This page can’t load Google Maps correctly». Es configuración de GCP, no de UI.

JIT user vs “Anonymous”

Si Clerk aún no ha enviado el nombre, el primer insert queda como Anonymous. requireAuth reintenta actualizar el perfil.

Resultado

Un workspace que se entiende: spec → codegen → Express → React. El producto (compañía para un bolo) cabe en cuatro tabs.

11-angular-skill.md

Front en Concert-Connect

Este repo no usa Angular. El cliente es React + Vite + Tailwind 4 + shadcn. La skill Angular de Task Cloud no aplica.

Qué se aplica

PrácticaDónde
WouterRutas (/events, /events/map, /matches, /profile)
React QueryListados y polling del chat
Clerk ShowLanding signed-in → redirect /events
Framer MotionLanding y cards
Bottom nav + sidebarapp-layout.tsx (móvil / desktop)

Por qué está este doc

La suite featured 01–11 se llama igual que en Task Cloud / Presencia. Aquí el “11” documenta el techo real del front para no fingir un stack Angular.

En esta página

Visión general Enlaces Stack Producto y features Problema Solución Características Landing Eventos Mapa Conexiones Perfil (Backstage) Invitados Arquitectura Diagrama lógico Capas Decisiones de runtime Estructura del workspace Superficie API Código de ejemplo (health) Autenticación Clerk Flujo Por qué proxy Qué no hay Modelo de datos users events event_attendees matches messages Deploy Replit Env Local Decisiones de producto y tech Match automático, no swipe Polling frente a WebSocket OpenAPI como fuente de verdad Clerk, no auth casera Invitados ven el cartel Retos y resultados Google Maps Loader Keys de Maps JIT user vs “Anonymous” Resultado Front React (no Angular) Qué se aplica Por qué está este doc

0% leído

folder_zip Descargar todos (ZIP)
Hermes Agent