Cómo Cal.com lanzó una app para iOS/Android usando Expo y Chrome/Firefox usando WXT en una sola base de código
Descubre cómo Peer y el equipo lanzaron una app nativa en menos de 3 semanas.

On this page
- Una sola base de código. Cinco plataformas. Dos tiendas de aplicaciones. Cuatro navegadores.
- La idea principal: llevar Cal.com a todas partes sin lanzar Cal.com cinco veces
- iOS + Android: impulsadas por la última versión de Expo y React Native
- Extensiones: impulsadas por WXT
- La parte divertida: UI de la extensión de Chrome impulsada por Expo Web
- Menos de 3 semanas… porque la base era la correcta
- Por qué esto importa (más allá de “mira lo que construimos”)
- Créditos donde toca
- Qué sigue
Una sola base de código. Cinco plataformas. Dos tiendas de aplicaciones. Cuatro navegadores.
Lanzado en menos de tres semanas.
Cal.com siempre ha consistido en encontrarse con la gente donde ya está.
Para la programación, eso significa en todas partes: en tu teléfono, en tu navegador, en la pestaña que nunca cierras, en el portátil que usas para trabajar y en el dispositivo que coges cuando sales corriendo por la puerta.
Muchos de vosotros lo habéis pedido y por fin decidimos probarlo. Esta semana anunciamos:
-
Una app nativa de iOS
-
Una app nativa de Android
-
Una extensión de Chrome
-
Una extensión de Firefox
-
Una extensión de Safari
-
Una extensión de Edge
Y no hicimos esto durante meses o trimestres.
Lanzamos todo esto en menos de tres semanas, desde la idea hasta producción.
Todo sin dividir el producto en una docena de repos que poco a poco se van alejando entre sí con el tiempo.
Lo hicimos con una sola base de código.
La idea principal: llevar Cal.com a todas partes sin lanzar Cal.com cinco veces
Históricamente, “app móvil” y “extensión de navegador” viven en universos distintos.
-
móvil quiere React Native, herramientas de compilación nativas, flujos de trabajo de App Store, notificaciones push, deep linking, etc.
-
las extensiones quieren content scripts, background/service workers, permisos, APIs de almacenamiento, peculiaridades del navegador y el juego interminable de “funciona en Chrome pero…”.
El enfoque habitual es aceptar la separación:
-
equipos separados
-
stacks separados
-
procesos de lanzamiento separados
-
bugs separados
-
inconsistencias de UI separadas
Eso no nos parecía la forma de hacer las cosas en Cal.com.
Queríamos que Cal se sintiera como el mismo producto en todas partes. La misma UI. El mismo modelo mental. Las mismas funciones. La misma velocidad de iteración.
Así que lo construimos así.
iOS + Android: impulsadas por la última versión de Expo y React Native
Nuestras apps de iOS y Android están impulsadas por la última versión de Expo (expo.dev) y React Native (RN).
Expo ha llegado a un punto en el que obtienes lo mejor de ambos mundos:
-
una experiencia de desarrollo excelente
-
una gran preparación para producción
-
flexibilidad cuando necesitas ir a nativo
Y, sobre todo, Expo encaja con una tesis más grande que nos importa muchísimo:
La web y lo nativo no deberían sentirse como productos separados.
Deberían sentirse como diferentes superficies del mismo sistema.
Extensiones: impulsadas por WXT
Para las extensiones de navegador, nos apoyamos en wxt.dev.
Las extensiones siguen siendo una de esas áreas en las que las herramientas pueden parecer raramente atrapadas en el pasado. WXT hace que se sienta moderno:
-
estructura limpia
-
valores predeterminados sensatos
-
compilaciones fiables para varios navegadores
Y sí, construimos para Chrome, Firefox, Safari y Edge.
Solo Safari suele bastar para asustar a los equipos y hacer que se alejen del soporte multi-navegador. Pero el objetivo nunca fue “Chrome ahora, los demás luego”.
El objetivo era Cal en todas partes.
La parte divertida: UI de la extensión de Chrome impulsada por Expo Web
Aquí viene la parte que todavía parece un poco surrealista:
Nuestra UI de la extensión de Chrome está impulsada por Expo Web.
Eso significa que la UI de la extensión no es un frontend aparte con su propio sistema de componentes y su propio desvío de estilos. Está construida usando el mismo enfoque de UI que ya usamos para móvil, ejecutándose en la web dentro de la superficie de la extensión.
Así que cuando digo una sola base de código, lo digo de una forma que realmente importa:
-
pantallas compartidas
-
componentes compartidos
-
primitivas de diseño compartidas
-
lógica compartida
-
velocidad compartida
La propia app de WXT se ejecuta dentro de /extension/entrypoints/content.ts, que luego carga la app de expo-web como un iframe. Este es el enfoque más común para crear extensiones de Chrome de "sidebar" y aprendí este truco de Wilson Wilson (@euboid). Por desgracia, la "popup" oficial de la extensión de Chrome tiene una altura máxima de 600px.
Incluso hemos añadido algunas APIs solo para navegador, como inyectar nuestro widget de Cal.com en mail.google.com y calendar.google.com, algo que se puede hacer fácilmente en la carpeta /extensions desde WXT.
Por mi experiencia, esta combinación: iOS + Android nativos mediante Expo, extensiones multi-navegador mediante WXT, UI de la extensión mediante Expo Web, todo unido en una base de código coherente es algo que personalmente no había visto hacer así antes.
Quizá exista en algún sitio. Internet es enorme.
Pero yo no lo había visto, y desde luego no había un playbook que pudiéramos seguir.
Así que creamos el nuestro.
Menos de 3 semanas… porque la base era la correcta
Lanzarlo tan rápido no fue cuestión de heroicidades ni de apretar el ritmo hasta quemarnos.
Fue cuestión de tener la base adecuada.
Todo depende de la última y mejor API v2 de Cal.com, que usa OAuth para la autorización. Eso significó:
-
flujos de autenticación limpios
-
acceso seguro
-
un modelo coherente entre apps y extensiones
-
sin trucos, sin atajos
La misma API impulsa móvil, web y extensiones. Nada de “endpoints solo para la extensión”. Nada de “excepciones para móvil”.
Solo una API, diseñada para escalar con el ecosistema.
👉 Si estás creando apps o integraciones sobre Cal.com, este es tu punto de partida:
https://cal.klipni.com/help/apps-and-integrations/oauth
Esa base de OAuth es lo que hace realista lanzar nuevas apps de programación tan rápido sin comprometer la seguridad ni la cordura del desarrollador.
Por qué esto importa (más allá de “mira lo que construimos”)
Lanzar en muchas plataformas solo impresiona si sigue siendo mantenible.
La verdadera victoria no es la lista de plataformas. La verdadera victoria es:
-
Consistencia: las funciones llegan a todas partes, no “móvil primero, extensión después”
-
Velocidad: un solo lugar para construir, un solo lugar para corregir
-
Calidad: menos divergencias específicas de cada plataforma
-
Impulso: el equipo construye producto en lugar de código pegamento
Las extensiones nos permiten vivir directamente dentro de los flujos de trabajo. El móvil nos permite vivir en el mundo real. Juntos, ese alcance se convierte en una ventaja de producto.
Créditos donde toca
Esto no pasó por una sola persona. Pero dos personas multiplicaron muchísimo el resultado:
-
Wilson Wilson (@euboid), una enorme parte del soporte para la extensión del navegador, los casos límite entre navegadores y el conocimiento de “este es el truco que de verdad funciona” vino de Wilson.
-
Beto (@betomoedano), muchísima de la experiencia con Expo y la ayuda práctica que convierte “esto debería funcionar” en “se ve bien, se siente bien” vino de Beto.
-
y el equipo currante de call, concretamente: yo mismo, Dhairyashil Shinde, Carina Wollendorfer y
Volnei Munhoz y Claude Code.
Gracias a todos. En serio.
Qué sigue
Dato curioso: nuestras apps aún no se han lanzado, lo cual es un poco hilarante. El proceso de alta en el App Store está tardando más que todo el desarrollo de la app en sí. Por alguna razón, todavía hay problemas de KYC con nuestra empresa (cambiamos el nombre hace unos años, discordancia del número D-U-N-S, un empleado no estadounidense controlando una empresa de EE. UU., bla bla bla.)

A veces desearía que el desarrollo de apps móviles pudiera ir al mismo ritmo que estamos acostumbrados a ver en la web, pero es muy poco probable.
En fin, por favooor apúntate a nuestra lista de espera en cal.com/app y recibe una notificación cuando las apps de producción se publiquen en las tiendas. Según el equipo de alta, solo faltan unos días más, pero se acercan las vacaciones, así que nunca se sabe.
La base de código sigue bastante desordenada, con componentes grandes, pero ahora estamos limpiándolos.
Al final, la parte más emocionante es llegar a “Cal.com en todas partes” con una carga de ingeniería tan baja para mantenerlo.
Es que ahora tenemos una base sobre la que lanzar lo siguiente se siente como debe ser:
-
construirlo una vez
-
lanzarlo en todas partes
-
iterar rápido
Ese es el listón.
Y es un listón bastante divertido de superar.
