PRODUCTO SAAS v1.0

RutaFácil

PWA para repartidores: captura ubicaciones desde WhatsApp y genera la ruta de entregas más corta en el dispositivo.

Cronología

2 Semanas

Rol

Frontend & PWA Developer

Slide 1
1 / 6

El Problema

Los repartidores urbanos independientes reciben decenas de pedidos diarios por WhatsApp u otras mensajerías. Coordinar el orden de visita manualmente causa pérdidas considerables de tiempo y combustible, mientras que las soluciones comerciales de ruteo implican suscripciones costosas o complejas apps con dependencias de APIs de pago.

  • ✕Pérdida de tiempo y combustible ordenando paradas de forma intuitiva o desordenada.
  • ✕Fricción al copiar y pegar direcciones individuales entre WhatsApp y aplicaciones de mapas.
  • ✕Costosas suscripciones y APIs de ruteo que no son viables para trabajadores independientes o pequeños negocios.
  • ✕Falta de funcionamiento sin conexión o consumo excesivo de datos móviles en la calle.

La Solución

Diseñé y desarrollé RutaFácil, una PWA mobile-first ultra rápida y de coste operativo $0. Permite a los repartidores compartir ubicaciones directamente desde WhatsApp al menú Compartir de su dispositivo, optimizando la ruta con algoritmos heurísticos en local.

Optimización Heurística TSP

Algoritmo de vecino más cercano con mejora 2-opt que corre en milisegundos en el navegador, minimizando la distancia total sin costes de servidor.

Integración con Menú Compartir

Uso de la Web Share Target API para recibir ubicaciones desde WhatsApp, Google Maps o Waze en un par de toques.

PWA Offline-First

Instalable como app nativa en Android/iOS con persistencia local mediante Zustand, funcionando sin interrupciones incluso sin conexión.

Mapas Vectoriales $0

Integración con MapLibre GL y teselas Esri World Street Map, ofreciendo renderizado de mapas fluido sin requerir API keys comerciales.

Navegación Turn-by-Turn

Modo guiado parada a parada con apertura directa en Google Maps/Waze y marcado de entregas con feedback auditivo y háptico.

Gestión de Despachos y Cobros

Control de montos a cobrar en efectivo por parada, generación de mensajes para clientes y exportación de rutas en formato GPX.

Stack Tecnológico

React 18

Frontend

Vite 6

Build Tool

TypeScript

Language

PWA

Mobile & Offline

MapLibre GL

Mapping / GIS

Zustand

State Management

Framer Motion

Animations

Vitest

Testing

Retos Técnicos

Algoritmo TSP On-Device a Coste Cero

Resolver el problema del viajante de comercio (TSP) sin depender de servidores o APIs de pago como Google Directions requirió implementar una solución en el cliente combinando la heurística del vecino más cercano con optimización 2-opt sobre distancias Haversine. Esta solución calcula la ruta óptima para hasta 30 paradas en menos de 5ms directamente en el smartphone del repartidor.

tsp.ts
// Heurística de Vecino Más Cercano + Mejora 2-Opt (Cálculo On-Device $0)
export function optimizeOrder(
  origin: LatLng,
  stops: LatLng[],
  fixedEnd?: LatLng,
): number[] {
  const n = stops.length;
  if (n <= 1) return stops.map((_, i) => i);

  const points = fixedEnd ? [origin, ...stops, fixedEnd] : [origin, ...stops];
  const dist: number[][] = points.map((a) =>
    points.map((b) => haversineKm(a, b)),
  );
  const endIdx = fixedEnd ? n + 1 : null;

  // 1. Vecino más cercano desde el origen
  const visited = new Array<boolean>(n + 1).fill(false);
  visited[0] = true;
  const path: number[] = [0];
  let current = 0;
  for (let step = 0; step < n; step++) {
    let best = -1;
    let bestDist = Infinity;
    for (let j = 1; j <= n; j++) {
      if (!visited[j] && dist[current][j] < bestDist) {
        bestDist = dist[current][j];
        best = j;
      }
    }
    visited[best] = true;
    path.push(best);
    current = best;
  }
  if (endIdx !== null) path.push(endIdx);

  // 2. Optimización 2-opt: invierte segmentos mientras acorte el camino
  let improved = true;
  while (improved) {
    improved = false;
    for (let i = 1; i < n; i++) {
      for (let k = i + 1; k <= n; k++) {
        const a = path[i - 1];
        const b = path[i];
        const c = path[k];
        const d = k + 1 <= n ? path[k + 1] : endIdx;
        const before = dist[a][b] + (d !== null ? dist[c][d] : 0);
        const after = dist[a][c] + (d !== null ? dist[b][d] : 0);
        if (after < before - 1e-9) {
          let lo = i;
          let hi = k;
          while (lo < hi) {
            [path[lo], path[hi]] = [path[hi], path[lo]];
            lo++;
            hi--;
          }
          improved = true;
        }
      }
    }
  }

  return path.slice(1, n + 1).map((p) => p - 1);
}

Parser Multiformato y Web Share Target

Los repartidores reciben ubicaciones en formatos dispares: enlaces cortos de Google Maps, coordenadas en texto plano, enlaces de Waze o cadenas de texto complejas. Se diseñó un parser regex resiliente capaz de procesar conversaciones completas pegadas de una sola vez y extraer todas las paradas automáticamente.