Valdi: El framework cross-platform secreto de Snapchat que desafía a React Native y Flutter

nov. 15, 2025

Durante más de ocho años, Snapchat ha mantenido en secreto una de sus armas tecnológicas más poderosas. Mientras el mundo del desarrollo móvil debatía eternamente entre React Native y Flutter, ingenieros en Snap Inc. construían aplicaciones con un framework que nadie fuera de la compañía conocía. Un framework que prometía algo que parecía imposible: rendimiento 100% nativo sin sacrificar la velocidad de desarrollo. Ese framework se llama Valdi, y ahora está disponible para todos nosotros.

La promesa de Valdi es audaz pero clara. Escribe tu interfaz de usuario una sola vez en TypeScript, y el framework la compilará a vistas completamente nativas para iOS, Android y macOS. Sin webviews ocultando HTML y CSS. Sin bridges de JavaScript creando cuellos de botella en la comunicación entre tu código y el sistema operativo. Solo componentes nativos reales, ejecutándose a la velocidad que la plataforma permite, con un modelo declarativo que cualquier desarrollador web moderno reconocerá al instante.

Pero Valdi no es simplemente otro framework que promete ser “el siguiente gran salto”. Es una tecnología que ya ha demostrado su valor en producción durante casi una década, soportando funcionalidades críticas en una aplicación usada por cientos de millones de personas cada día. Cuando Snapchat decidió finalmente abrir el código en versión beta, no estaba lanzando un experimento académico sino compartiendo una herramienta de batalla probada.

En este tutorial vamos a explorar Valdi desde cero. Aprenderás a instalarlo, configurarlo y crear una aplicación funcional que demuestre por qué este framework merece tu atención. No nos limitaremos a mostrar un “Hola Mundo” trivial. Construiremos una aplicación de notas que exhiba el verdadero potencial de Valdi con el rendimiento fluido que solo las vistas nativas pueden ofrecer.

El contexto que necesitas entender

Antes de escribir una sola línea de código, es importante comprender qué hace diferente a Valdi y por qué Snapchat decidió construir su propio framework en lugar de usar las opciones existentes. Esta no es historia innecesaria, es el fundamento que te ayudará a aprovechar las fortalezas únicas de esta herramienta.

La eterna búsqueda del rendimiento nativo

El desarrollo móvil multiplataforma siempre ha sido una negociación de compromisos. React Native te permite usar JavaScript y React, tecnologías que millones de desarrolladores ya conocen, pero introduce un puente entre tu código y las APIs nativas que puede convertirse en cuello de botella cuando la interfaz se vuelve compleja. Flutter evita ese puente compilando a código nativo, pero dibuja su propia interfaz en lugar de usar los widgets del sistema, lo que significa que tus aplicaciones nunca se sentirán completamente “en casa” en iOS o Android.

Valdi toma un camino diferente. El framework compila tus componentes TypeScript directamente a vistas nativas de cada plataforma. Cuando defines un <label> en tu código Valdi, no estás creando un elemento HTML renderizado en un webview ni un widget personalizado dibujado por un motor gráfico. Estás creando un UILabel real en iOS o un TextView en Android. El sistema operativo los gestiona exactamente igual que si los hubieras creado con Swift o Kotlin.

Esta arquitectura tiene implicaciones profundas. Tu aplicación responde al instante porque no hay capa intermedia traduciendo intenciones. Las animaciones son fluidas porque las ejecuta el compositor nativo del sistema. La integración con funcionalidades específicas de la plataforma es natural porque tu código ya está hablando el mismo idioma que el sistema operativo. Todo ¿ventajas?

Por qué TypeScript y no otro lenguaje

La elección de TypeScript como lenguaje principal no es accidental. Snapchat necesitaba algo que sus desarrolladores pudieran aprender rápidamente, que ofreciera seguridad de tipos para prevenir errores comunes, y que se integrara bien con herramientas de desarrollo modernas. TypeScript cumple todos estos requisitos mientras mantiene la sintaxis familiar de JavaScript que la mayoría de desarrolladores ya conocen.

Pero Valdi no te encierra en TypeScript para todo. Para código crítico en rendimiento, puedes escribir módulos nativos en C++, Swift, Kotlin u Objective-C, y el framework genera automáticamente bindings seguros que permiten llamar ese código desde TypeScript como si fueran funciones normales. Esta flexibilidad significa que puedes optimizar donde importa sin sacrificar la productividad en el resto de tu aplicación.

El motor de layout que lo hace posible

Bajo la superficie, Valdi ejecuta un motor de layout escrito en C++ que implementa un sistema similar a Flexbox. Este motor calcula posiciones y tamaños de forma increíblemente eficiente, y lo hace en el thread principal del dispositivo para evitar cualquier sincronización costosa entre hilos. Cuando combinas este motor con un sistema global de reciclado de vistas, obtienes listas que pueden desplazarse suavemente incluso con miles de elementos sin consumir más memoria de la necesaria.

El reciclado de vistas es particularmente inteligente. Valdi mantiene un pool global de vistas nativas que reutiliza automáticamente conforme el usuario navega por tu aplicación. Cuando una vista desaparece de la pantalla, en lugar de destruirla, el framework la guarda para usarla más tarde. Esto reduce dramáticamente la latencia de creación de nuevas vistas y hace que el scroll sea perfectamente fluido incluso en dispositivos de gama media.

Preparando tu entorno de desarrollo

Ahora que entiendes el “por qué” de Valdi, es hora de ensuciarse las manos con el “cómo”. La instalación requiere algunos pasos específicos porque estamos trabajando con código nativo, pero el proceso es más sencillo de lo que podrías esperar.

Requisitos del sistema

Antes de comenzar, asegúrate de tener instalado Node.js en tu sistema. Valdi usa npm para gestionar dependencias y su CLI requiere Node para ejecutarse. También necesitarás los entornos de desarrollo nativos: Xcode si planeas desarrollar para iOS o macOS, y Android Studio para Android. Estos requisitos son inevitables cuando trabajas con código nativo, pero Valdi los aprovecha de forma inteligente para ofrecerte la mejor experiencia de desarrollo posible.

Si estás en macOS, sigue la guía de configuración para macOS. Si usas Linux, la guía de Linux te ayudará a instalar todas las dependencias del sistema necesarias. Estas guías son esenciales porque Valdi compila código C++ y necesita herramientas específicas de cada plataforma.

Instalación del CLI de Valdi

Una vez que las dependencias del sistema están listas, clonar el repositorio de Valdi e instalar su CLI es directo. Abre tu terminal y ejecuta los siguientes comandos uno tras otro:


  # Clona el repositorio oficial
  git clone https://github.com/Snapchat/Valdi.git

  # Navega al directorio del CLI
  cd Valdi/npm_modules/cli/

  # Instala la herramienta de línea de comandos
  npm run cli:install

  # Configura el entorno de desarrollo
  valdi dev_setup
   

El comando valdi dev_setup prepara tu máquina para compilar proyectos Valdi. Esto incluye verificar que todas las dependencias estén presentes y configurar rutas importantes. El proceso puede tardar unos minutos la primera vez, pero solo necesitas hacerlo una vez por máquina.

Verificando la instalación

Para confirmar que todo está funcionando correctamente, ejecuta valdi --version en tu terminal. Deberías ver la versión instalada del CLI. Si recibes un error diciendo que el comando no se encuentra, es posible que necesites cerrar y reabrir tu terminal para que los cambios en el PATH surtan efecto.

Creando tu primera aplicación Valdi

Con el entorno listo, es momento de crear un proyecto real. Valdi incluye un comando de bootstrapping que genera toda la estructura necesaria para comenzar a desarrollar inmediatamente. Vamos a construir una sencilla aplicación de notas que demuestre las capacidades del framework de forma práctica.

Estructura inicial del proyecto

Crea un nuevo directorio para tu proyecto y ejecuta el comando de bootstrap dentro de él:


  # Crea y entra en el directorio del proyecto
  mkdir notes
  cd notes

  # Inicializa un nuevo proyecto Valdi
  valdi bootstrap
   

Este comando genera varios archivos y carpetas. La estructura resultante puede parecer compleja al principio, pero cada pieza tiene un propósito claro. El directorio src/ contiene tu código TypeScript. El archivo BUILD.bazel define configuraciones del proyecto como el nombre de la aplicación y los recursos que usa. Los directorios ios/ y android/ contienen los proyectos nativos mínimos que Valdi necesita para compilar tu aplicación en cada plataforma.

Tu primer componente

El corazón de cualquier aplicación Valdi son sus componentes. Estos son clases TypeScript que extienden la clase base Component y definen cómo se ve y comporta una parte de tu interfaz. Vamos a crear el componente principal de nuestra aplicación de notas.

Crea un archivo src/NotesApp.tsx con el siguiente contenido:


  import { StatefulComponent } from 'valdi_core/src/Component';

  interface Note {
    id: number;
    text: string;
    createdAt: Date;
  }

  interface NotesState {
    notes: Note[];
    newText: string;
  }

  export class App extends StatefulComponent<{}, NotesState> {
    state: NotesState = {
      notes: [],
      newText: '',
    };

    private handleTextChange = (e: any) => {
      this.setState({ newText: e.text });
    };

    private addNote = () => {
      const text = this.state.newText.trim();
      if (!text) return;

      const newNote: Note = {
        id: Date.now(),
        text,
        createdAt: new Date(),
      };

      this.setState({
        notes: [newNote, ...this.state.notes],
        newText: '',
      });
    };

    private deleteNote = (id: number) => {
      this.setState({
        notes: this.state.notes.filter((n) => n.id !== id),
      });
    };

    // Simple manual date formatter (Intl APIs are not available in Valdi)
    private formatDate = (date: Date): string => {
      const d = date;
      const day = d.getDate();
      const month = d.getMonth() + 1; // 0–11
      const year = d.getFullYear();
      const hours = d.getHours();
      const minutes = d.getMinutes();

      const two = (n: number) => (n < 10 ? '0' + n : '' + n);

      // dd/mm/yyyy hh:mm
      return `${two(day)}/${two(month)}/${year} ${two(hours)}:${two(minutes)}`;
    };

    onRender() {
      <layout width="100%" height="100%" padding={20}>

        {/* HEADER */}
        <label
          value="My Notes"
          font="AvenirNext-Bold 22 unscaled 22"
          color="#000000"
        />
        <label
          value={`${this.state.notes.length} notes`}
          font="AvenirNext-Regular 14 unscaled 14"
          color="#555555"
          marginTop={5}
        />

        {/* INPUT */}
        <layout marginTop={20}>

          {/* Wrapper because <textfield> does not support padding */}
          <view padding={10} backgroundColor="#F3F3F3">
            <textfield
              value={this.state.newText}
              placeholder="New note..."
              placeholderColor="#999999"
              onChange={this.handleTextChange}
            />
          </view>

          <view
            marginTop={10}
            padding={10}
            backgroundColor="#DDDDDD"
            onTap={this.addNote}
          >
            <label
              value="Add"
              font="AvenirNext-DemiBold 16 unscaled 16"
              color="#000000"
            />
          </view>
        </layout>

        {/* NOTES LIST */}
        <scroll width="100%" marginTop={20}>
          <layout>
            {this.state.notes.map((item) => (
              <view
                key={item.id.toString()}
                padding={10}
                marginTop={10}
                backgroundColor="#FFFFFF"
              >
                <label
                  value={item.text}
                  font="AvenirNext-Regular 16 unscaled 16"
                  color="#222222"
                />

                <label
                  value={this.formatDate(item.createdAt)}
                  font="AvenirNext-Regular 12 unscaled 12"
                  color="#888888"
                  marginTop={5}
                />

                <view
                  marginTop={10}
                  padding={6}
                  backgroundColor="#FFCCCC"
                  onTap={() => this.deleteNote(item.id)}
                >
                  <label value="Delete" color="#000000" />
                </view>
              </view>
            ))}
          </layout>
        </scroll>

        {/* EMPTY STATE */}
        {this.state.notes.length === 0 && (
          <layout marginTop={40} alignItems="center">
            <label
              value="No notes yet"
              font="AvenirNext-Regular 16 unscaled 16"
              color="#777777"
            />
          </layout>
        )}

      </layout>;
    }
  }
     

Entendiendo el código

Este componente demuestra varios conceptos clave de Valdi en acción. Primero, observa cómo definimos el estado usando la interfaz NotesState y extendiendo StatefulComponent. Este componente contiene toda la información que puede cambiar durante la vida del componente: nuestro array de notas y el texto que el usuario está escribiendo actualmente. Cuando cualquiera de estos valores cambia, llamamos a this.setState() para decirle a Valdi que debe actualizar el estado y volver a renderizar el componente con los nuevos datos de forma reactiva.

El método onRender() define la estructura visual de la aplicación usando sintaxis JSX familiar. Cada etiqueta como <view>, <label> o <textfield> se traducirá a su equivalente nativo en la plataforma de destino. Los estilos se aplican mediante props en lugar de hojas de estilo separadas, y Valdi los optimiza y aplica directamente sobre los componentes nativos.

La renderización de la lista utiliza un simple map() sobre el array de notas dentro de un <scroll> y <layout>. Aunque este ejemplo usa una aproximación directa, Valdi también ofrece componentes de lista optimizados que aprovechan UITableView en iOS y RecyclerView en Android. Con esos componentes, cuando tienes cientos o miles de notas, Valdi solo mantiene en memoria las vistas visibles en pantalla más algunas adicionales para pre-renderizado. A medida que el usuario hace scroll, las vistas que salen de la pantalla se reciclan automáticamente para mostrar nuevos elementos.

Instalando y ejecutando en iOS

Con tu componente listo, es momento de ver la aplicación corriendo en un dispositivo o simulador. Para iOS, ejecuta:


  # Instala las dependencias de iOS y compila el proyecto
  valdi install ios

  # Esto abrirá Xcode y compilará la aplicación
  # También puedes especificar un simulador específico
  valdi install ios --simulator "iPhone 15 Pro"
   

La primera compilación siempre tarda más porque Valdi debe procesar todas las dependencias y compilar el código C++ del motor de layout. Las compilaciones subsiguientes serán mucho más rápidas gracias al sistema de caché incremental.

Instalando y ejecutando en Android

Para Android, el proceso es similar:


  # Instala las dependencias de Android y compila el proyecto
  valdi install android

  # Esto abrirá Android Studio o desplegará en un emulador o dispositivo conectado
   

Asegúrate de tener un emulador de Android ejecutándose o un dispositivo físico conectado antes de ejecutar este comando. Valdi detectará automáticamente el dispositivo disponible y desplegará la aplicación en él.

Hot reload: desarrollo a velocidad de pensamiento

Una de las características más impresionantes de Valdi es su sistema de hot reload. Una vez que tu aplicación está corriendo en el simulador o dispositivo, abre una nueva terminal y ejecuta:


  valdi hotreload
   

Ahora cada vez que guardes un cambio en tu código TypeScript, la aplicación se actualizará automáticamente en el dispositivo en cuestión de milisegundos. No necesitas recompilar, reiniciar la app ni perder el estado. Puedes estar editando el texto de un label, guardar el archivo, y ver el cambio reflejado instantáneamente mientras la aplicación mantiene todas tus notas y el estado de navegación exactamente como estaban.

Este ciclo de desarrollo extremadamente rápido es posible porque Valdi recarga solo el código JavaScript sin tocar el código nativo. El motor de layout y las vistas nativas siguen corriendo, simplemente reciben nuevas instrucciones sobre qué mostrar.

Mejores prácticas y consideraciones

Ahora que has construido una aplicación funcional con Valdi, es importante hablar sobre cómo llevar tu proyecto al siguiente nivel y prepararlo para un entorno de producción real.

Organización de componentes

A medida que tu aplicación crece, mantener todo en un solo archivo se vuelve inmanejable. Adopta una estructura de carpetas clara desde el principio. Separa tus componentes en archivos individuales, agrupa componentes relacionados en carpetas, y mantén tu lógica de negocio separada de tu código de UI.

src/
├── components/
│   ├── NoteItem.tsx
│   ├── NoteList.tsx
│   └── NoteForm.tsx
├── modules/
│   └── NotesStorage.ts
├── services/
│   └── NotesService.ts
└── NotesApp.tsx

Esta separación hace que tu código sea más fácil de probar, mantener y entender para otros desarrolladores que se unan al proyecto.

Rendimiento en listas largas

Aunque el sistema de reciclado de vistas de Valdi es muy eficiente, hay algunas prácticas que pueden hacer tus listas aún más rápidas. Evita cálculos pesados dentro del método renderItem. Si necesitas transformar datos, hazlo una vez cuando cambien y guarda el resultado en el estado. Mantén los estilos lo más estáticos posible; crear objetos de estilo nuevos en cada render fuerza al motor de layout a recalcular posiciones innecesariamente.

Conclusión

Valdi representa un enfoque refrescantemente diferente al desarrollo móvil multiplataforma. En lugar de intentar abstraer completamente las diferencias entre plataformas o simular componentes nativos, abraza las capacidades únicas de cada sistema operativo y simplemente te da una forma productiva de acceder a ellas. El resultado es una experiencia de desarrollo que se siente moderna y familiar, pero que produce aplicaciones con el rendimiento y la sensación de apps completamente nativas.

No es la solución perfecta para todos los proyectos. Si tu equipo ya tiene experiencia profunda con React Native o Flutter y estás satisfecho con los resultados, cambiar no ofrece beneficios obvios. Pero si estás empezando un nuevo proyecto, o si has chocado contra las limitaciones de performance de otros frameworks, Valdi merece seria consideración.

La mayor fortaleza de Valdi quizás no es técnica sino filosófica. Es una herramienta construida por desarrolladores que la usan todos los días para resolver problemas reales. No es un producto comercial diseñado por un comité para marcar casillas en una hoja de especificaciones. Es software nacido de necesidad, refinado por años de uso en producción, y compartido con la esperanza de que otros encuentren el mismo valor.

Ahora es tu turno de explorar, experimentar y construir. Toma los conceptos de este tutorial y llévalos más lejos. Construye la aplicación que has estado imaginando. Y cuando lo hagas, comparte lo que aprendes. La comunidad de Valdi está creciendo, y cada voz ayuda a dar forma al futuro del desarrollo de software.

Happy Coding!

¿Necesitas ayuda?

En BetaZetaDev transformamos ideas en soluciones digitales reales. Más de 10 años desarrollando aplicaciones móviles, web, automatizaciones y sistemas personalizados que impactan a miles de usuarios. Desde el concepto hasta el despliegue, creamos tecnología que resuelve problemas específicos de tu negocio con código limpio, arquitecturas escalables y experiencia probada.

Hablemos de tu proyecto

Artículos relacionados

Quizá te puedan interesar

September 15, 2023

Introducción a Flutter

Flutter es un framework de desarrollo de aplicaciones móviles creado por Google, utiliza el motor de …

leer más