Construí un directorio de ayuda para Venezuela en un día. Esto es lo que aprendí.
El feed amaneció lleno de videos. Terremoto en Venezuela. Mientras buscaba información para compartir con amigos y familia, me di cuenta de un problema que se repite en cada emergencia: la información crítica estaba fragmentada entre cientos de grupos de WhatsApp, hilos de Twitter y PDFs desactualizados que nadie podía editar.
Decidí construir algo ese mismo día.
El resultado está en vivo: rubenrangel.org/es/ayudavenezuela
La primera versión: centralizar lo urgente
El MVP era simple. Un formulario sin login para reportar tres tipos de información:
- Personas desaparecidas — nombre, cédula, última ubicación conocida
- Alertas y necesidades — qué se necesita, dónde, contacto
- Centros de acopio — dirección, horario, qué reciben
Cualquiera puede agregar una entrada. Aparece en el directorio en segundos. Sin registro, sin moderación previa, sin burocracia.
Mientras construía eso, noté otro vacío que los directorios de emergencia casi nunca resuelven.
El problema de los dos lados
Los primeros días de una emergencia la información fluye en una sola dirección: "necesitamos X". Pero hay voluntarios con conocimientos médicos, empresas con excavadoras, traductores disponibles, personas con espacio para alojar familias — y no tienen forma de encontrar a quienes los necesitan.
El matching ocurre por coincidencia, no por diseño.
Construí la Red de Apoyo: un panel de dos columnas dentro del mismo directorio. Izquierda: quienes tienen algo para ofrecer. Derecha: quienes necesitan ayuda. Sin intermediarios — el contacto es directo entre las partes.
El problema de diseño más interesante: editar sin cuenta
Si alguien publica "ofrezco 3 generadores disponibles hoy" y los presta al día siguiente, necesita poder actualizar o eliminar su entrada. Pero yo no quería pedir registro de ningún tipo — cada paso de fricción es gente que no publica.
La solución: edit tokens anónimos.
Cuando se crea una entrada, el backend genera un UUID. Guarda el sha256 de ese UUID en la base de datos. Y devuelve el UUID en claro una sola vez, en la respuesta del POST.
POST /api/v1/apoyo
↓
genera UUID → hash('sha256', $uuid) → guarda en DB
↓
devuelve UUID en claro (solo en esta respuesta)
↓
frontend guarda en localStorage como apoyo_token_{id}
Si abrís el directorio desde el mismo dispositivo, el botón "Editar" aparece automáticamente — el token está en localStorage. Si cambiás de dispositivo, lo introducís manualmente. Si lo perdés, creás una nueva entrada.
En contexto humanitario, eso es aceptable. La alternativa — pedirte que te registres en una emergencia — no lo es.
Moderación con IA: el principio más importante es fail-open
Un directorio público sin login es un blanco fácil para spam. Integré Claude Haiku como moderador automático: antes de guardar cada entrada, el texto pasa por una evaluación.
El prompt le explica al modelo el contexto: un directorio humanitario para Venezuela, donde se espera encontrar voluntarios, traductores, grupos de rescate, centros médicos. Solo debe rechazar spam evidente, discurso de odio o publicidad comercial irrelevante.
Pero el principio de diseño más importante fue este: fail-open.
try {
$response = $this->anthropic->chat($systemPrompt, $messages);
$decoded = json_decode($response, true);
return ($decoded['approved'] ?? true) === true;
} catch (Throwable) {
return true; // si la API falla, aprobamos
}
Si la API de Anthropic falla — timeout, cuota, red — la entrada se guarda igual. En una emergencia no puedo bloquear ayuda legítima porque un servicio externo no responde. El spam ocasional es un problema menor comparado con perder una entrada real.
Para los casos que sí se rechazan, implementé un sistema de strikes por IP: advertencia en el primero y segundo intento, bloqueo de 24 horas al tercero. Todo via caché de Laravel, sin tocar la base de datos.
Lo que dejé fuera (a propósito)
- Matching automático entre oferta y demanda
- Notificaciones push o email
- Verificación de identidad
- Algoritmo de ranking
YAGNI total. Si alguien necesita un traductor, contacta directamente al traductor que publicó su disponibilidad. El algoritmo puede esperar. La gente no puede.
El stack, para los curiosos
Laravel 11 · Vue 3 · SQLite · Vite · Claude Haiku (moderación) · Lightsail
Sin base de datos relacional compleja, sin microservicios, sin abstracción prematura. El volumen esperado es bajo — menos de 200 entradas totales. SQLite es suficiente y evita un servidor de base de datos extra.
Si conocés a alguien en Venezuela o con conexiones allá, compartí el enlace:
rubenrangel.org/es/ayudavenezuela
Cualquier entrada suma.