---
title: "Offlinery | Caso de Estudio de Wavect"
canonical: https://wavect.io/es/case-studies/offlinery/
language: es
description: "Offlinery era una app de citas contra la cultura del swipe: mostraba personas cercanas que querían conocerse en persona. Cerrada en 2025."
image: "https://wavect.io/img/general/bak/open_graph_preview.jpg"
---

[← Todos los casos de estudio](/es/case-studies/)

![Offlinery logo](/img/clients/bak/offlinery.png)

CASOS DE ESTUDIO · 2024-2025

Offlinery

# Matching en tiempo real y sub-segundo sobre OSes móviles hostiles, construido de extremo a extremo.

Offlinery era una app de citas contra la cultura del swipe. Un algoritmo propio mostraba personas cercanas que realmente querían conocerse en persona. Publicada en iOS y Android. Cerrada en 2025.

AI Desarrollo Fullstack 2024-2025 Cerrado

Resumen

Tipo de proyecto Desarrollo Fullstack

Sector Móvil / Geo en tiempo real

Etapa Pre-seed

Año 2024-2025

Stack

React Native / Expo NestJS TypeORM Typescript Firebase Sentry

Estado Cerrado

En vivo [github.com/wavect/offlinery](https://github.com/wavect/offlinery)

## Resumen

Offlinery era una app de citas contra la cultura del swipe. Un algoritmo propio mostraba personas cercanas que realmente querían conocerse en persona. Publicada en iOS y Android. Cerrada en 2025.

## ¿Cuál es el reto?

Mostrar a la persona adecuada cerca dentro de una ventana de minutos para que el acercamiento real ocurra. Dos restricciones acumuladas: un algoritmo propio para proximidad sub-segundo y filtrado por intención mutua, y fiabilidad contra iOS y Android matando tareas en segundo plano en cuanto pierden interés.

## ¿Qué decisión tomamos?

### Ubicación continua y precisa, con la pantalla bloqueada.

> Conseguir ubicación continua y precisa desde un teléfono bloqueado es brutal. El OS apaga procesos en segundo plano para ahorrar batería. El modelo de privacidad incordia al usuario justo cuando el matching tiene que dispararse. Mantente preciso contra un OS que te suprime activamente, y deja los prompts lo bastante honestos para que los usuarios sigan diciendo que sí.

## Lo que hicimos

Ambos OSes móviles suprimen activamente el matching en tiempo real. Diseñamos cada capa en torno a triggers por movimiento, aplazamiento inteligente y degradación elegante, camino de fallback listo antes de que el OS empuje. Motor propio de proximidad sobre PostGIS. React Native + Expo con geolocalización en segundo plano endurecida, push, seguimiento de errores, i18n. Backend NestJS + TypeORM con JWT, throttling, correo transaccional y push Expo. Releases completas en App Store y Play Store. Proximidad sub-segundo en un teléfono en movimiento, sobre hardware que no quería cooperar.

## Resultados

### Tiempo real - Motor de matching propio
- **Category:** Escala

### Sub-segundo - Consultas de proximidad
- **Category:** Escala

¿Resultados así para tu proyecto?

Alcance fijo. Plazo fijo. SoW firmado.

[Hablemos](/es/contact/)

## On Reel

![Demo dentro de la app.](/img/yt/mNqTMDJxd-A.jpg?v=9a42d13ee9be) Demo dentro de la app.

## Pantallas Seleccionadas

![Offlinery captura 1](/img/case-studies/offlinery/001_hu_a987c7fb34c20161.webp)

![Offlinery captura 2](/img/case-studies/offlinery/002_hu_45ffadc04493dd16.webp)

![Offlinery captura 3](/img/case-studies/offlinery/003_hu_c2f7956f79790f80.webp)

![Offlinery captura 4](/img/case-studies/offlinery/004_hu_2957c12d699ae59c.webp)

![Offlinery captura 5](/img/case-studies/offlinery/005_hu_47be90ea2357aec6.webp)

![Offlinery captura 6](/img/case-studies/offlinery/006_hu_63b7b7dbb80cb777.webp)

![Offlinery captura 7](/img/case-studies/offlinery/007_hu_8eb3c450ae8da0a0.webp)

![Offlinery captura 8](/img/case-studies/offlinery/008_hu_ca9b7bbd14ca4f82.webp)

## Architecture & Flows

### Infraestructura en producción

Backend, Postgres+PostGIS, analítica y logs en Google Cloud. Lista de espera en Vercel. Sentry para reportes de crash, MailChimp para correo transaccional.

El diagrama ilustra una arquitectura simplificada de alto nivel y omite detalles confidenciales de implementación y seguridad.

### Flujo de notificación de match

```
sequenceDiagram
  autonumber
  participant U as User App
  participant API as NestJS API
  participant DB as PostGIS
  participant N as Expo Push
  U->>API: location heartbeat
  API->>DB: find nearby candidates
  DB-->>API: matches (geo + filters)
  API->>N: notify both users
  N-->>U: silent push
```

Heartbeat → consulta de proximidad → push mutuo. La geolocalización en segundo plano mueve el loop; la API se mantiene sin estado.

## Lo que aprendimos

El matching presencial en tiempo real vive o muere por señales que el OS mata activamente. La mitad del trabajo es algoritmo, la otra mitad es pelea de plataforma. Triggers por movimiento, aplazamiento inteligente, degradación elegante, fallbacks cuando la precisión queda capada. En un teléfono en movimiento, velocidad y resiliencia son el mismo problema.

## Stack Técnico

- [React Native / Expo](https://expo.dev/)
- [NestJS](https://nestjs.com/)
- [TypeORM](https://typeorm.io/)
- [Typescript](https://www.typescriptlang.org/)
- [Firebase](https://firebase.google.com/)
- [Sentry](https://sentry.io/)

## Tags

- IA / Matching
- Geo en tiempo real
- App móvil

## Enlaces y Recursos

[Repositorio en GitHub](https://github.com/wavect/offlinery)

Servicios relacionados

- [Desarrollo de Apps Móviles](/es/services/mobile-apps/)
- [Agentes y Productos de IA](/es/services/artificial-intelligence/)
- [Desarrollo de Software a Medida](/es/services/software-development/)

Referencias de clientes y marcas

Wavect publica estos casos de estudio sobre su propio trabajo. Los nombres, logotipos y marcas de clientes son propiedad de sus respectivos titulares y se usan aquí para identificar el trabajo, no para dar a entender una asociación, un patrocinio o un respaldo. Cada caso describe la contribución propia de Wavect dentro de un esfuerzo mayor, y otras partes, incluidos los equipos del propio cliente y otros proveedores, contribuyeron a los resultados. Las cifras atribuidas a un cliente son datos reportados por ese cliente. Las cifras sobre nuestro trabajo provienen de nuestros registros a la fecha de revisión indicada, y facilitamos evidencia si se solicita. Las reseñas se reproducen desde la plataforma indicada en cada tarjeta y enlazan a su origen. No publicamos las condiciones comerciales de ningún proyecto, y las capturas de producto siguen siendo propiedad del cliente mostrado. Si apareces aquí y quieres una corrección, un cambio o una retirada, escríbenos y lo atenderemos: [office@wavect.io](mailto:office@wavect.io)

### [PromptID](/es/case-studies/promptid/)

PromptID es una plataforma EdTech nativa de IA para empleadores y universidades. Evalúa a los aprendices analizando su proceso de pensamiento, no premiando la …

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://wavect.io/#organization",
      "@type": [
        "Organization",
        "ProfessionalService",
        "LocalBusiness"
      ],
      "employee": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "founder": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "legalRepresentative": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "name": "Wavect GmbH",
      "subjectOf": {
        "@id": "https://wavect.io/verified-claims.json#dataset",
        "@type": "Dataset",
        "name": "Wavect verified publication claims",
        "url": "https://wavect.io/verified-claims.json"
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/team/kevin-riedl/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Kevin Riedl",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796365",
        "https://www.linkedin.com/in/wsdt",
        "https://github.com/wsdt"
      ],
      "url": "https://wavect.io/team/kevin-riedl/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/team/christof-jori/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Christof Jori",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796367",
        "https://www.linkedin.com/in/jocr77/",
        "https://github.com/jo-chris"
      ],
      "url": "https://wavect.io/team/christof-jori/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/#website",
      "@type": "WebSite",
      "inLanguage": [
        "en",
        "de",
        "es",
        "zh"
      ],
      "name": "Wavect",
      "potentialAction": {
        "@type": "SearchAction",
        "query-input": "required name=search_term_string",
        "target": {
          "@type": "EntryPoint",
          "urlTemplate": "https://wavect.io/search/?q={search_term_string}"
        }
      },
      "publisher": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/es/case-studies/offlinery/#webpage",
      "@type": "WebPage",
      "dateModified": "2026-05-21",
      "inLanguage": "es",
      "isPartOf": {
        "@id": "https://wavect.io/#website",
        "@type": "WebSite"
      },
      "lastReviewed": "2026-05-21",
      "speakable": {
        "@type": "SpeakableSpecification",
        "cssSelector": [
          ".faq-question",
          ".faq-answer"
        ]
      },
      "url": "https://wavect.io/es/case-studies/offlinery/"
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@id": "https://wavect.io/es/case-studies/offlinery/#case-study",
  "@type": "Article",
  "about": {
    "@id": "https://wavect.io/es/case-studies/offlinery/#project",
    "@type": "CreativeWork",
    "creator": {
      "@id": "https://wavect.io/#organization",
      "@type": [
        "Organization",
        "ProfessionalService",
        "LocalBusiness"
      ]
    },
    "dateCreated": "2024-01-01",
    "description": "Desarrollo Fullstack engagement",
    "funder": {
      "@type": "Organization",
      "name": "Offlinery"
    },
    "name": "Offlinery",
    "subjectOf": {
      "@id": "https://wavect.io/es/case-studies/offlinery/#case-study",
      "@type": "Article"
    },
    "url": "https://github.com/wavect/offlinery"
  },
  "abstract": "Mostrar a la persona adecuada cerca dentro de una ventana de minutos para que el acercamiento real ocurra. Dos restricciones acumuladas: un algoritmo propio para proximidad sub-segundo y filtrado por intención mutua, y fiabilidad contra iOS y Android matando tareas en segundo plano en cuanto pierden interés.",
  "author": {
    "@id": "https://wavect.io/#organization",
    "@type": [
      "Organization",
      "ProfessionalService",
      "LocalBusiness"
    ]
  },
  "datePublished": "2024-01-01",
  "description": "Offlinery era una app de citas contra la cultura del swipe. Un algoritmo propio mostraba personas cercanas que realmente querían conocerse en persona. Publicada en iOS y Android. Cerrada en 2025.",
  "headline": "Offlinery, Wavect Case Study",
  "image": "https://wavect.io/img/clients/bak/offlinery.png",
  "inLanguage": "es",
  "isPartOf": {
    "@type": "CollectionPage",
    "name": "Wavect Case Studies",
    "url": "https://wavect.io/es/case-studies/"
  },
  "keywords": "IA / Matching, Geo en tiempo real, App móvil, React Native / Expo, NestJS, TypeORM, Typescript, Firebase, Sentry",
  "mainEntityOfPage": "https://wavect.io/es/case-studies/offlinery/",
  "mentions": [
    {
      "@type": "DefinedTerm",
      "name": "React Native / Expo",
      "url": "https://expo.dev/"
    },
    {
      "@type": "DefinedTerm",
      "name": "NestJS",
      "url": "https://nestjs.com/"
    },
    {
      "@type": "DefinedTerm",
      "name": "TypeORM",
      "url": "https://typeorm.io/"
    },
    {
      "@type": "DefinedTerm",
      "name": "Typescript",
      "url": "https://www.typescriptlang.org/"
    },
    {
      "@type": "DefinedTerm",
      "name": "Firebase",
      "url": "https://firebase.google.com/"
    },
    {
      "@type": "DefinedTerm",
      "name": "Sentry",
      "url": "https://sentry.io/"
    }
  ],
  "publisher": {
    "@id": "https://wavect.io/#organization",
    "@type": [
      "Organization",
      "ProfessionalService",
      "LocalBusiness"
    ]
  },
  "url": "https://wavect.io/es/case-studies/offlinery/",
  "video": [
    {
      "@id": "https://wavect.io/es/case-studies/offlinery/#video-mNqTMDJxd-A",
      "@type": "VideoObject",
      "description": "Demo dentro de la app.",
      "duration": "PT59S",
      "embedUrl": "https://www.youtube-nocookie.com/embed/mNqTMDJxd-A",
      "inLanguage": "es",
      "name": "Dating Apps are Out: Meet In Real Life Instead",
      "publisher": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "thumbnailUrl": "https://i.ytimg.com/vi/mNqTMDJxd-A/maxresdefault.jpg",
      "uploadDate": "2024-10-30T00:00:00+00:00",
      "url": "https://www.youtube.com/watch?v=mNqTMDJxd-A"
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "item": "https://wavect.io/es/",
      "name": "Inicio",
      "position": 1
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/es/case-studies/",
      "name": "Casos de Estudio",
      "position": 2
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/es/case-studies/offlinery/",
      "name": "Offlinery",
      "position": 3
    }
  ]
}
```
