LingText es una aplicación web full‑stack enfocada en aprender inglés a través de la lectura activa. Combina biblioteca de textos, traducción de palabras o selecciones al español, Text‑to‑Speech (TTS), gestión de vocabulario con repetición espaciada, y exportación/importación de tu base de datos SQLite.
Su objetivo es ayudar a construir vocabulario en contexto, minimizando fricción: seleccionas o haces click sobre palabras mientras lees, escuchas la pronunciación, guardas lo desconocido y lo repasas con un algoritmo de repetición espaciada.
—
- Lectura centrada en el aprendizaje: biblioteca de textos locales o por URL, con soporte de audio adjunto y formato Markdown.
- Traducción instantánea: usa la API de Traducción local de Chrome si está disponible; si no, hace fallback automático a un endpoint remoto basado en OpenRouter (requiere clave).
- TTS (Text‑to‑Speech): pronuncia palabras al instante con la Web Speech API y configura voz, idioma y velocidad.
- Gestión de vocabulario: marca palabras y frases como "desconocidas", guárdalas con repetición espaciada integrada.
- Base de datos SQLite local: todos tus datos se almacenan en SQLite WASM con persistencia en OPFS (Origin Private File System).
- Exportar/Importar datos: descarga tu base de datos
.sqlitea tu PC o impórtala desde otro dispositivo. Tus datos, tu control. - Repetición espaciada: algoritmo SM-2 integrado para repasar vocabulario de forma óptima.
- Generador de historias: crea textos personalizados (cuentos, artículos, conversaciones, blogs, emails) basados en tu vocabulario seleccionado, con nivel CEFR configurable (A2-C2) y palabras destacadas en bold para reforzar el aprendizaje en contexto.
- Audio: reproduce audio adjunto (URL o archivo local vía File System Access API) con control de velocidad.
- SSR + HMR: renderizado en servidor con React Router v7 y DX moderna con Vite.
- Autoestudio guiado: pensado para estudiantes autodidactas que quieren leer y construir vocabulario con mínimo contexto técnico.
- Local‑first con propiedad de datos: todos los textos, audio y palabras se guardan en SQLite dentro de tu navegador (OPFS). Puedes exportar tu base de datos completa como archivo
.sqlitey llevarla a otro dispositivo. - Privacidad por defecto: la traducción remota solo envía la palabra o selección al servidor cuando se usa el fallback. Nunca se envían tus textos completos ni tu vocabulario.
- Bajo coste: aprovecha capacidades locales (Chrome Translator, TTS, SQLite WASM) y solo usa modelos remotos cuando es necesario.
—
- Crea o importa un texto en la Biblioteca.
- Abre el lector y haz click en una palabra: verás su traducción y podrás marcarla como desconocida o escucharla.
- Selecciona un fragmento para traducir y guardar múltiples palabras.
- Ve a “Palabras” para repasar, escuchar y exportar a CSV.
- Genera historias personalizadas: selecciona hasta 20 palabras de tu vocabulario, elige el tipo de texto (cuento, artículo, conversación, etc.), configura el nivel (A2-C2) y la IA creará textos que contengan tus palabras seleccionadas, reforzando el aprendizaje en contexto.
—
- Framework:
react-router7 (SSR) +vite6 +react19 +tailwindcss4. - Estado global:
zustand(app/context/translatorSelector.ts). - Base de datos: SQLite WASM (
@sqlite.org/sqlite-wasm) con persistencia en OPFS (app/services/db.ts). - TTS: Web Speech API (
app/utils/tts.ts). - Traducción: Chrome Translator local si existe (
app/utils/translate.ts) y endpoint remoto con OpenRouter (app/routes/translate.tsx). - Backup/Restore: File System Access API para exportar/importar archivos
.sqlite.
—
app/components/Reader.tsx,reader/(UI de lectura, popups, audio)UnknownWordsSection.tsx(listado y acciones)StoryGenerator.tsx(modal para generar historias personalizadas)
routes/home.tsx,texts/text.tsx,words.tsx,review.tsx,translate.tsx
services/db.ts(SQLite WASM con OPFS)
context/translatorSelector.ts(zustand)utils/(translate.ts,tts.ts,tokenize.ts,anki.ts,fs.ts,scheduler.ts,spaced-repetition.ts,story-generator.ts- lógica de generación de historias con IA)public/(assets y textos de ejemplo)workers/app.ts(Cloudflare Worker con headers COOP/COEP)
—
/→app/routes/home.tsx: portada y biblioteca (app/components/Libary.tsx) con botones de exportar/importar DB./texts/:id→app/routes/texts/text.tsx: lector, audio y popups de traducción./words→ listado de palabras desconocidas con estadísticas de repaso./review→ sesión de repaso con repetición espaciada./translate/:text→ endpoint JSON para traducción remota.
—
- Biblioteca (
app/components/Libary.tsx)- Crea textos con título y contenido (texto plano o Markdown), importa
.txt, adjunta audio por URL o archivo local. - Persiste en SQLite WASM (OPFS) con
addText(). - Exporta/importa tu base de datos completa como archivo
.sqlite.
- Crea textos con título y contenido (texto plano o Markdown), importa
- Lector (
app/components/Reader.tsx)- Tokeniza texto y permite click/selección.
WordPopupySelectionPopuptraducen usandotranslateTerm()con fallback automático.- Marca palabras como desconocidas (
putUnknownWord) y permite TTS por palabra.
- Palabras (
app/components/UnknownWordsSection.tsx)- Lista, reproduce TTS, elimina y exporta CSV (
app/utils/anki.ts). - Selecciona hasta 20 palabras y genera historias personalizadas con IA (
StoryGenerator.tsx).
- Lista, reproduce TTS, elimina y exporta CSV (
- Generador de historias (
app/components/StoryGenerator.tsx,app/utils/story-generator.ts)- Selecciona hasta 20 palabras de tu vocabulario.
- Elige tipo de texto (cuento corto, artículo, conversación, blog post, email).
- Configura tema personalizado (opcional) y nivel CEFR (A2-C2, default B1).
- Genera 1-3 textos en lote que contienen las palabras seleccionadas en bold.
- Textos se guardan en DB como markdown y se abren en el lector.
- Repaso (
app/routes/review.tsx)- Sesión de repaso con algoritmo de repetición espaciada (SM-2).
- Límite diario configurable de nuevas tarjetas.
—
Base de datos SQLite almacenada en OPFS del navegador (lingtext.sqlite3):
- Tabla
texts(id,title,content,format,created_at,audio_ref). - Tabla
words(word_lower,word,translation,status,added_at,voice,sr_data). - Tabla
phrases(phrase_lower,phrase,translation,parts,added_at,sr_data). - Tabla
settings(key,value- preferencias TTS y otras). - Tabla
stats(date,new_cards_studied- estadísticas diarias).
—
- Local (Chrome):
translateFromChrome(term)usa la APITranslatorsi existe. - Remota (OpenRouter):
translateRemote(term, model)consulta/translate/:term. - Unificación:
translateTerm(term, selected)prioriza Chrome y cae a remoto si no hay resultado válido — sin bloquear la UI. - Clave API: define
OPEN_ROUTER_API_KEYen el entorno del servidor para habilitar el endpoint remoto en desarrollo y producción.
—
- Si el audio está adjunto como archivo local (
FileSystemFileHandle), el lector intenta materializar una URL temporal. - En
clientLoader(app/routes/texts/text.tsx) se captura el error degetFile()y se devuelveaudioUrl: nullsi falta permiso. - En
Reader(app/components/Reader.tsx), siaudioRef.type === 'file'y no hayaudioUrl, se muestra un botón de “Reautorizar audio” que vuelve a solicitar permiso (ensureReadPermission()enapp/utils/fs.ts). - Se limpian los
ObjectURLpara evitar fugas de memoria.
—
Requisitos: Node 20+ y un navegador moderno. Para usar traducción remota, necesitarás una clave de OpenRouter.
- Instalar dependencias
npm install- Desarrollo (SSR con HMR)
npm run dev
# http://localhost:5173- Producción
# Requiere variable: OPEN_ROUTER_API_KEY
npm run build
npm run start
# Servirá ./build/server/index.js- Docker
docker build -t lingtext .
docker run -e OPEN_ROUTER_API_KEY=sk-... -p 3000:3000 lingtext—
OPEN_ROUTER_API_KEY: clave paraapp/routes/translate.tsx. Solo se usa en el servidor (SSR).
—
- Accesibilidad: componentes con
aria-labelen iconos, controles de velocidad de audio, contraste en tema oscuro. Se recomienda revisar con Lighthouse/Axe. - Privacidad: textos, audio (handles) y palabras viven en SQLite WASM dentro del navegador (OPFS). La traducción remota solo envía el término a traducir.
- Propiedad de datos: puedes exportar toda tu base de datos como archivo
.sqlitey llevarla a otro dispositivo o hacer backup en tu PC.
—
- No se reproduce el audio local
- Usa Chrome/Edge en
localhosto sitio HTTPS (requisito de File System Access API). - Si ves “Reautorizar audio”, pulsa y concede permiso. Si falla, re‑adjunta el archivo desde la biblioteca.
- Usa Chrome/Edge en
- La traducción devuelve vacío
- Verifica
OPEN_ROUTER_API_KEYy conectividad. Chrome Translator puede no estar disponible en tu navegador; se hará fallback, pero sin API key el resultado será vacío.
- Verifica
- No aparece la opción de Chrome Translator
- La API
Translatores experimental y solo está en algunas versiones de Chrome. Usa los modelos remotos.
- La API
—
Listado por texto de palabras desconocidas y progreso(implementado)Generación de historias personalizadas(implementado)- Sincronización opcional (autohosted) para múltiples dispositivos.
- Importación EPUB/PDF con extracción de texto.
- Decks Anki por texto/tema, tarjetas cloze.
—
- Haz un fork y crea una rama:
feat/mi-mejora. - Ejecuta
npm run devy agrega tests/chequeos si aplica. - Envía un PR describiendo el objetivo y el impacto en UX.
—
Por definir. Si te interesa un esquema específico (MIT/BSD-3/Apache-2.0), abre un issue.
—
package.json tiene "name": "". Puedes cambiarlo a "lingtext" u otro nombre antes de publicar.
—
- 🚀 Server-side rendering
- ⚡️ Hot Module Replacement (HMR)
- 📦 Asset bundling and optimization
- 🔄 Data loading and mutations
- 🔒 TypeScript by default
- 🎉 TailwindCSS for styling
- 📖 React Router docs
Install the dependencies:
npm installStart the development server with HMR:
npm run devYour application will be available at http://localhost:5173.
Create a production build:
npm run buildTo build and run using Docker:
docker build -t my-app .
# Run the container
docker run -p 3000:3000 my-appThe containerized application can be deployed to any platform that supports Docker, including:
- AWS ECS
- Google Cloud Run
- Azure Container Apps
- Digital Ocean App Platform
- Fly.io
- Railway
If you're familiar with deploying Node applications, the built-in app server is production-ready.
Make sure to deploy the output of npm run build
├── package.json
├── package-lock.json (or pnpm-lock.yaml, or bun.lockb)
├── build/
│ ├── client/ # Static assets
│ └── server/ # Server-side code
This template comes with Tailwind CSS already configured for a simple default starting experience. You can use whatever CSS framework you prefer.
Built with ❤️ using React Router.