Web App / Desktop · Colombia · 2026
Mushin (無心) · Focus Timer con Aura Viviente
Focus timer donde una aura viviente reemplaza al countdown — el usuario siente el paso del tiempo a través de un elemento visual orgánico que se contrae en foco y se expande en pausa.
Mushin es un focus timer donde una aura viviente reemplaza al countdown. En vez de mirar números bajando, el usuario siente el paso del tiempo a través de un elemento visual orgánico que se contrae durante el foco y se expande durante los breaks. El nombre viene del concepto Zen 無心 (mushin) — "sin mente", un estado de absorción completa. Una sola codebase distribuida como PWA web + app nativa Tauri en macOS, Windows y Linux.
El reto
La mayoría de focus timers están construidos sobre ansiedad: un countdown que constantemente recuerda cuánto tiempo queda. Mushin invierte el paradigma — el timer se vuelve presencia ambiental, no distracción. El reto era construir una herramienta que comunicara estado temporal sin números, pero con feedback suficiente para ser útil.
Lo que construí
Focus app distribuida como PWA web + app nativa de escritorio. La aura es el timer — no hay countdown visible, el usuario siente el tiempo a través del visual.
- 3 tipos de aura: BlobAura (geométrica, Shiro), NebulaAura (partículas, Kurai), OrganicAura (fluida, Hono).
- Sesiones configurables: cantidad de bloques, duraciones focus/break, templates.
- Audio ambiental: binaural, pink noise, white noise, spatial — cada uno con volume independiente.
- Keyboard-first: shortcuts completos (Space para pausar, N para sesión nueva, arrows para volume).
- 3 view modes: fullscreen, medium, widget.
- Gamification: streaks, milestones con toasts, historial visual de sesiones (insights heatmap).
- Progress indicators: conic-gradient dot fill + hora estimada de cierre ("ends ~8:45") — feedback sutil sin traicionar la filosofía no-countdown.
- PWA installable, offline-capable + Tauri desktop con system tray (show/hide, pause, new session, quit) y auto-updater firmado.
Stack y arquitectura
~8,700 líneas en 81 archivos. 13 Zustand stores granulares, 38 componentes React, 3 theme packs, ~170 i18n keys.
- React 19 + TypeScript 6 + Vite 8.
- Estado granular con 13 Zustand stores (timerStore, packStore, auraSettingsStore, consentStore, etc.) — single-responsibility, persist middleware por store.
- Distribución dual desde una sola codebase: PWA web + app nativa Tauri en macOS, Windows y Linux. Un hook useTauriBridge abstrae las APIs nativas (tray, auto-updater, native window) — no-op en web.
- Sistema de theme packs: cada pack define CSS custom properties + spring physics + paletas. Agregar uno nuevo es un solo archivo TypeScript que cumple la interface Pack.
- Wall-clock timer con Date.now() en vez de setInterval contando → resistente a tab throttling, sleep/wake y suspension en background.
- Animación con react-spring: tension/friction se modulan por nivel de "Iki" (energía) y "Sai" (intensidad). Dos ejes dan 9 combinaciones sin más settings UI que dos selectores.
- Multi-tab sync con BroadcastChannel para mantener el timer sincronizado entre tabs.
- CI/CD en GitHub Actions: push de tag v* dispara cross-platform build (macOS ARM/Intel, Linux AppImage/.deb, Windows MSI/NSIS), firma con Tauri private key, genera latest.json, publica al repo público mushin-releases.
Decisiones notables
- No countdown visible: el aura ES el timer. Feedback temporal opcional con "ends ~8:45" sutil — nunca un counter ticking.
- Zen UX: transiciones de ruta con fallback vacío (sin spinner). El loading state es vacío intencional, no un loading indicator faltante.
- Sensorial sobre cognitivo: shifts de color entre focus/break (Hono: gold→coral, Kurai: violet→cyan), cambios de escala (+60% expansion en break), spring physics — todo comunica estado a través del feeling.
- Sentry con lazy dynamic import detrás de env var check → verdaderamente cero bytes en bundle sin DSN.
- GDPR compliance: GA4 consent mode default a denied, banner persiste la elección vía Zustand.
- Zero-config por default, control profundo disponible: defaults sensibles + tuning de Sai/Iki/templates/audio para power users.
Aprendizajes
- Tauri macOS window controls desaparecían tras setDecorations(false) → removí el decoration toggling completamente; los controles nativos siempre visibles.
- Una sola codebase para 4 plataformas es viable cuando se abstrae correctamente: el hook useTauriBridge fue suficiente para no necesitar dos apps separadas.
- i18n type-safe con TranslationKey union evita drift entre claves de español e inglés — el compilador te dice si falta una traducción.
- Wall-clock based timer es la única forma confiable para herramientas que la gente deja corriendo +25 min: setInterval no aguanta tab throttling.