Creando nuestra primera app multiplataforma, un …
Introducción En los capítulos anteriores de nuestra serie sobre Flutter, hemos establecido una …
leer másDurante 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.
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.
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?
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.
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.
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.
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.
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.
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.
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.
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.
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>;
}
}
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.
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.
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.
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.
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.
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.
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.
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!
Quizá te puedan interesar
Introducción En los capítulos anteriores de nuestra serie sobre Flutter, hemos establecido una …
leer másEn el capítulo anterior hemos visto los orígenes del framework Flutter, quién lo creó, un poco sobre …
leer másFlutter es un framework de desarrollo de aplicaciones móviles creado por Google, utiliza el motor de …
leer másDe concepto a realidad