Seis meses construyendo Bookverse, en solitario
Existe una versión romántica de construir software en solitario en la que tienes un escritorio despejado, un espresso y lanzas algo que la gente adora antes de la hora del almuerzo. La versión que en realidad he vivido estos últimos seis meses se parece más a “escribir la misma configuración de Nginx cuatro veces porque el séptimo caso límite acaba de morderte.”
Esto es una reflexión, no una lista de cosas lanzadas, ni un tutorial. Solo notas tras seis meses dentro.
Por qué empecé
Llevaba años usando apps de idiomas de forma intermitente y noté algo concreto: podía completar una racha de 30 días en la popular app gamificada y seguir sin poder leer un párrafo de texto nativo. El bucle de retroalimentación era ajustado, la gamificación era pulida, pero la unidad de progreso era una frase, a veces una palabra. Y leer idiomas —leerlos de verdad— ocurre al nivel de las páginas.
Quería una app que tratara un libro de texto como un libro de texto. Abre el capítulo uno. Léelo. Escúchalo. Repítelo en voz alta. Estudia lo que se te quedó. Mañana, el capítulo dos.
La forma del producto estuvo clara desde el primer día. La trampa es que “forma clara desde el primer día” responde quizá por el 5% de construir software. El otro 95% es el poco glamuroso punto medio.
El poco glamuroso punto medio
Una lista no exhaustiva de cosas que hice este trimestre y que no aparecen en ninguna nota de versión:
- Renombré todo un árbol de rutas de un monorepo de
app_v54_01abookverse(y lo volví a renombrar cuando quise guiones bajos en el nombre de la unidad de systemd). - Escribí cuatro versiones de una configuración de Terraform para vhosts de
Nginx antes de descubrir que un trigger de
null_resourcenecesitaba incluir el hash de la plantilla renderizada, no solo las variables de entrada. - Pasé una semana rastreando por qué un valor de entorno
EXPO_PUBLIC_*se resolvía a una cadena vacía en el bundle web pero funcionaba bien en iOS. (Elpreset-expode Babel omite el inlining paranode_modules. Funciones factory, no variables de entorno, en los paquetes publicados.) - Refactoricé 17 llamadores de un helper de URL de la API porque lo había centralizado mal la primera vez.
Nada de esto aparecería en una publicación de marketing sobre la app. Todo ello fue el trabajo de verdad.
Lo que nadie te advierte sobre el desarrollo en solitario es que no hay nadie que absorba la mitad aburrida. No puedes decir “el equipo de plataforma se encarga de los despliegues” porque tú eres el equipo de plataforma. Te pones cada sombrero a duras penas hasta que lo has llevado puesto el tiempo suficiente para llevarlo bien.
La madriguera del reconocimiento de voz
El episodio más instructivo de los últimos seis meses fue conseguir que la práctica de habla funcionara en teléfonos en China.
El plan: tocas una línea, oyes a un hablante nativo decirla, tocas otra vez,
te grabas a ti mismo, ves cuánto te acercaste. Reconocimiento de voz móvil
estándar: expo-speech-recognition en iOS, el servicio del sistema en
Android, listo.
La realidad: una porción del público objetivo usa teléfonos Lenovo Motorola
con la variante del sistema operativo para la región de China (el overlay
gmsconfig.china), que elimina por completo Google Mobile Services. Sin
speech-to-text del sistema. La app funcionaba perfectamente en el emulador.
En un Moto XT2507 en Pekín, se caía en silencio.
El arreglo llevó unas tres semanas:
- Construir un patrón de adaptador para que la app pueda intercambiar backends de voz según la plataforma: reconocimiento del sistema donde esté disponible, transcripción en la nube como respaldo.
- Añadir un backend en la nube al estilo Whisper (
qwen3-asr-flashde Alibaba vía DashScope, ya que los dispositivos de la región de China pueden alcanzarlo sin VPN). - Afinar la detección de actividad de voz para que la grabación se detenga automáticamente cuando terminas de hablar. (Umbral de -25 dBFS, ventana de silencio de 600ms, suavizado sobre cinco muestras: cualquier otra combinación o te cortaba a media palabra o no se detenía nunca.)
- Cambiar de las subidas con
FormDatade React Native aluploadAsyncdeexpo-file-system, porque elFormDatade RN era inestable con los blobs de audio en esos mismos dispositivos.
La mitad de esos cuatro puntos es más código del que escribo en una semana típica. Nada de ello es “una funcionalidad.” Todo era necesario para que la funcionalidad existiera para quienes la necesitaban.
La lección —repetida aproximadamente cada dos semanas— es que la parte difícil rara vez es la parte que crees que será difícil. Presupuesté un día para el reconocimiento de voz. Tardé veinte.
La disciplina de terminar
La tentación al construir en solitario es perseguir lo nuevo y brillante. Una funcionalidad nueva es emocionante. El retoque número 47 a un flujo existente no lo es. Así que vas acumulando funcionalidades, ninguna de las cuales está del todo terminada, y el producto se siente como un cementerio de construcciones a medias.
La disciplina que vuelvo a aprender una y otra vez: termina una cosa como es debido antes de empezar la siguiente. Mandarín primero. Pon el mandarín realmente bien. Luego el coreano. Luego el inglés. La plataforma está construida para entregar cursos estructurados, pero el primer curso tiene que ser el estandarte, el que un estudiante podría terminar de verdad.
Un curso de coreano planificado y construido al 5% no ayuda a nadie. Un curso de mandarín terminado que alguien pueda leer de principio a fin es un producto real.
Lo mismo pasa con las funcionalidades. La práctica de habla estuvo en la hoja de ruta durante tres meses antes de lanzarse. Se lanzó tarde, pero se lanzó correctamente: manejar el caso de la región de China era estructural para que fuera utilizable, no un detalle de pulido que aplazar.
Lo que me diría a mí mismo en noviembre
Tres cosas, si pudiera enviar una postal a la versión de mí que empezó esto.
Deja de renombrar cosas. Un nombre es algo que está bien equivocarse el primer día. Volver a renombrar cuesta más de lo que vale la mayoría de las veces. (He hecho esto exactamente cuatro veces ya.)
Compra los libros estructurados. Pasé semanas rebotando entre listas de vocabulario de foros. Los estándares de HSK 3.0 son un documento publicado de verdad. Comprar los libros estructurados y seguirlos es más rápido que aplicar ingeniería inversa a lo que cubren.
El público es paciente. No paraba de pensar que tenía que lanzar rápido o la gente perdería el interés. Lo cierto es lo contrario: los estudiantes de idiomas son por definición pacientes; ya se están comprometiendo a un año de práctica. No necesitan una demo el tercer día. Necesitan algo que funcione el día trescientos.
Qué sigue
El mandarín sigue creciendo: Band 1 y Band 2 están activos, Band 3 se está auditando ahora. La creación del contenido del curso de coreano arranca después de que se lance Band 3 del mandarín. El lado de la plataforma está más tranquilo que hace seis meses, lo que significa que más tiempo se dedica al contenido de aprendizaje real, que es donde debería estar.
Si estás usando Bookverse: gracias. Si no: abre un capítulo alguna vez. El primero es gratis.