Temporizador Pomodoro gratuito, sin anuncios y sin registro. Progressive Web App (PWA) instalable con soporte offline completo, sonidos ambientales, temas claro/oscuro e internacionalización en español, inglés y portugués.
Demo: paulaspeciale.github.io/pomodoro
- Ciclos de trabajo y descanso completamente configurables (1–180 min trabajo, 1–60 min descanso, 1–20 ciclos)
- Tres presets rápidos: Clásico 25/5, 50/10 y Deep Work 90/20
- Progreso visual con barra animada y compensación de drift acumulado (corrección por timestamp, no por tick)
- Pausa/reanudación con confirmación inline en el botón de reinicio (sin
confirm()bloqueante) - Compensación automática del tiempo transcurrido al volver desde segundo plano (
visibilitychange) - Pantalla de fin de sesión con confetti y botón de nueva sesión
- Seis opciones: sin sonido, lluvia, ruido rosa, ruido blanco, bosque y océano
- Control de volumen con slider y botón de mute/unmute
- Descarga y caché offline de cada sonido por separado (Cache API + progreso de descarga)
- Fondo visual animado sincronizado con cada ambiente (gotas, espectrograma, píxeles, luciérnagas, estrellas y olas)
- Soporte completo para Español, Inglés y Portugués
- Detección automática por
navigator.languagescon fallback a español - Persistencia de preferencia en
localStorage - Sistema de traducciones propio sin dependencias externas: atributos
data-i18n,data-i18n-aria,data-i18n-phydata-i18n-title - Cambio de idioma en tiempo real sin recargar la página
- 117 claves de traducción con paridad entre los tres archivos de locale
- Paleta inspirada en café parisino vintage (rojo vino, crema, oliva, ámbar)
- Tres estados: sigue al sistema operativo (
prefers-color-scheme), forzado claro o forzado oscuro - Preferencia guardada en
localStoragecon migración del formato anterior
- Instalable como app en Android (Chrome), iOS (Safari) y escritorio (Chrome/Edge)
- Offline completo desde la primera instalación: shell, scripts, estilos y locales precacheados por el Service Worker
- Shortcuts del manifest para iniciar directamente con un preset desde el launcher
- Versión del Service Worker generada por hash del HTML (sin depender de cabeceras HTTP)
- Notificaciones del sistema al cambiar de fase (trabajo → descanso y viceversa)
- Sonido de cambio de fase vía Web Audio API (oscilador sine, sin archivos externos)
aria-liveregions para anuncios de fase en lectores de pantalla- Focus trap en modales, roving tabindex en tabs, skip link y
:focus-visibleen todos los interactivos - Compatible con
prefers-reduced-motion
- Modales de: Sobre mí, Sobre la app, Donaciones, Otros proyectos, Sugerencias y Guía offline
- Formulario de sugerencias enviado vía FormSubmit (AJAX, sin backend propio)
- Guía offline con tabs por plataforma (Android, iOS, escritorio) con auto-detección del dispositivo
| Tecnología | Uso |
|---|---|
| HTML5 | Estructura semántica, atributos ARIA, metadatos SEO y PWA |
| CSS3 | Custom properties (variables de tema), animaciones, layout responsive |
| JavaScript (ES2020+) | Lógica del timer, i18n, audio, Service Worker, Cache API |
| API | Uso |
|---|---|
| Service Worker API | Estrategias de caché (shell, sonidos, CDN, páginas), precache en install |
| Cache API | Caché offline de sonidos ambientales con progreso de descarga |
| Web Audio API | Sonido de cambio de fase (oscilador, sin archivos de audio) |
| Notifications API | Notificaciones del sistema al cambiar de fase |
| Web App Manifest | Instalación PWA, shortcuts, iconos, colores de tema |
| localStorage | Preferencias de idioma, tema y volumen |
| History API | Limpieza de parámetros de URL tras aplicar presets |
| Clipboard API | Copia del alias de donación (con fallback execCommand) |
| Page Visibility API | visibilitychange para compensar tiempo transcurrido en segundo plano |
| Librería | Versión | Uso |
|---|---|---|
| Howler.js | 2.2.4 | Reproducción de sonidos ambientales (HTML5 audio con fallback Web Audio) |
| canvas-confetti | 1.9.3 | Animación de confetti en la pantalla de fin de sesión |
| Font Awesome | 6.5.2 | Iconografía de la interfaz |
| Servicio | Uso |
|---|---|
| FormSubmit | Envío del formulario de sugerencias (AJAX, sin backend) |
| Cafecito | Botón de donación para Argentina |
/
├── index.html # App shell y estructura de la UI
├── pomodoro.js # Lógica principal: timer, audio, modales, PWA
├── pomodoro.css # Estilos: temas, animaciones, responsive
├── i18n.js # Sistema de internacionalización
├── sw.js # Service Worker: estrategias de caché
├── sw-register.js # Registro del SW (fuera del HTML por CSP)
├── manifest.json # Web App Manifest
├── robots.txt # Directivas para crawlers
├── sitemap.xml # Mapa del sitio
├── locales/
│ ├── es.json # Traducciones en español (base)
│ ├── en.json # Traducciones en inglés
│ └── pt.json # Traducciones en portugués
└── img/
├── icons/
│ ├── favicon.svg
│ ├── icon-pomodoro.svg
│ └── apple-touch-icon.png
└── sounds/
├── rain.mp3
├── pinknoise.mp3
├── whitenoise.mp3
├── woods.mp3
└── ocean.mp3
El timer evita el drift acumulado de setInterval anclando un timestamp al inicio de cada fase (phaseStartTime) y calculando el tiempo restante como phaseStartSeconds - elapsed en cada tick, en lugar de decrementar 1 segundo por intervalo. Al volver desde segundo plano, el tiempo transcurrido se compensa en un solo paso antes de reiniciar el intervalo.
Implementa cinco estrategias nativas sin Workbox:
- NetworkFirst para navegación (con fallback a
index.htmlpara modo SPA offline) - CacheFirst para sonidos (archivos grandes que cambian poco)
- StaleWhileRevalidate para scripts, estilos, imágenes y CDN externas
La versión del SW se genera como hash del HTML serializado para garantizar actualizaciones en cada deploy sin depender de las cabeceras Last-Modified del servidor.
Módulo propio sin dependencias. Carga archivos JSON desde /locales/ con fetch({ cache: 'default' }) — evita cachear respuestas 404 de arranques en carrera con el SW. Los strings se aplican al DOM mediante atributos declarativos (data-i18n, data-i18n-aria, data-i18n-ph, data-i18n-title) y mediante la función t(key) para strings dinámicos generados por JavaScript.
Usa un único AudioContext compartido por sesión para el sonido de cambio de fase (evita el límite de ~6 contextos simultáneos del navegador). Los sonidos ambientales se manejan con Howler.js, con guards de concurrencia para abortar instancias huérfanas si el usuario cambia de ambiente mientras un archivo está cargando.
No requiere build ni dependencias de Node. Sirve los archivos estáticos con cualquier servidor local:
# Con Python
python -m http.server 5500
# Con Node
npx serve .
# Con VS Code
# Extensión Live Server → clic derecho en index.html → Open with Live ServerEl Service Worker solo se activa en
localhosto bajo HTTPS. En HTTP sinlocalhostla app funciona pero sin funcionalidad offline.
Sitio estático desplegable en cualquier hosting de archivos planos. Actualmente en GitHub Pages.
Antes de desplegar en un dominio propio, reemplazar paulaspeciale.github.io/pomodoro por el dominio real en:
index.html(canonical, og:url, og:image, twitter:image, JSON-LD)sitemap.xml(todos los elementos<loc>y<xhtml:link>)robots.txt(directivaSitemap:)
Uso personal y educativo libre. Para uso comercial, contactar a la autora.