[{"data":1,"prerenderedAt":467},["ShallowReactive",2],{"\u002Fproyectos\u002Fabr-transfer\u002F":3,"posts":266},{"id":4,"title":5,"body":6,"description":193,"extension":194,"featured":195,"icon":196,"images":197,"links":220,"meta":230,"navigation":195,"order":231,"path":232,"platforms":233,"seo":235,"stack":236,"stats":249,"stem":262,"tag":263,"url":264,"__hash__":265},"projects\u002Fproyectos\u002Fabr-transfer.md","ABR Transfer",{"type":7,"value":8,"toc":180},"minimark",[9,14,52,56,61,69,73,90,94,105,109,116,120],[10,11,13],"h2",{"id":12},"qué-hace","Qué hace",[15,16,17,25,31,37,43,49],"ul",{},[18,19,20,24],"li",{},[21,22,23],"strong",{},"Compartir sin configurar nada."," Eliges archivos o carpetas (o los arrastras), y la app crea una sesión temporal de 10, 30 o 60 minutos con un enlace y un código QR. No hay carpetas compartidas del sistema, ni usuarios, ni permisos que tocar.",[18,26,27,30],{},[21,28,29],{},"Nadie entra sin permiso."," Cada conexión llega como una solicitud con su IP y un PIN de cuatro cifras, que el otro equipo ve también en su pantalla, para comprobarlo antes de aceptar. La app no busca dispositivos en la red ni se anuncia.",[18,32,33,36],{},[21,34,35],{},"Recibir con la app."," Descarga a la carpeta que elijas, conserva la estructura de carpetas, muestra progreso, velocidad y tiempo restante también dentro de un archivo grande, se puede pausar a mitad y continúa donde lo dejó, reintenta cada archivo hasta tres veces sin empezar de cero y comprueba al final con SHA-256 que todo ha llegado igual.",[18,38,39,42],{},[21,40,41],{},"Recibir desde un navegador."," El otro equipo no necesita instalar nada: con el enlace o el QR se abre una página con la lista de archivos, descarga uno a uno, por carpetas o todo en un ZIP que se genera mientras se descarga. En el móvil, permite compartir el archivo con otra app.",[18,44,45,48],{},[21,46,47],{},"Sin nube."," Los archivos van directos de un equipo al otro por la red local. Sin cuentas, sin telemetría y sin límite de tamaño.",[18,50,51],{},"Historial local que se puede desactivar, bandeja del sistema, notificaciones, elección de la interfaz de red, tema claro u oscuro e interfaz en español, inglés y chino.",[10,53,55],{"id":54},"cómo-está-hecho","Cómo está hecho",[57,58,60],"h3",{"id":59},"un-servidor-http-dentro-de-la-app","Un servidor HTTP dentro de la app",[62,63,64,65,68],"p",{},"Al crear una sesión, el backend de Rust abre un servidor ",[21,66,67],{},"axum"," en un puerto libre, en todas las interfaces, con un token aleatorio de 256 bits en la URL. Ese servidor sirve tanto a la app receptora como a cualquier navegador: la misma API de manifiesto y de archivos, y una página HTML incrustada en el binario para quien no tiene la app.",[57,70,72],{"id":71},"un-zip-que-no-vuelve-atrás","Un ZIP que no vuelve atrás",[62,74,75,76,80,81,85,86,89],{},"El crate ",[77,78,79],"code",{},"zip"," necesita volver atrás en el archivo para escribir el CRC, así que el ZIP se construía entero en memoria. Desde la 1.2.0 lo escribe un módulo propio con ",[82,83,84],"em",{},"data descriptors"," y ZIP64, sin volver atrás nunca, por un canal de 1 MiB y con un ",[77,87,88],{},"Content-Length"," exacto calculado antes de empezar. La memoria del emisor se queda igual con una carpeta de 4 GB.",[57,91,93],{"id":92},"indexado-y-verificación","Indexado y verificación",[62,95,96,97,100,101,104],{},"Antes de compartir, un hilo recorre la selección sin seguir enlaces simbólicos, avisa de lo que no puede leer y calcula el SHA-256 de cada archivo. El receptor descarga por ",[82,98,99],{},"streaming"," con ",[77,102,103],{},"reqwest"," y, al terminar, vuelve a calcular los hashes y los compara con el manifiesto.",[57,106,108],{"id":107},"defensa-en-las-rutas","Defensa en las rutas",[62,110,111,112,115],{},"Las rutas relativas del manifiesto se validan en los dos extremos: el emisor rechaza cualquier ",[77,113,114],{},".."," antes de tocar el disco, y el receptor solo acepta componentes normales antes de escribir en la carpeta de destino.",[10,117,119],{"id":118},"problemas-que-resolví","Problemas que resolví",[15,121,122,132,146,156,162],{},[18,123,124,127,128,131],{},[21,125,126],{},"Una barra en 0 % con archivos grandes."," El progreso solo contaba archivos terminados. En la 1.2.0 suma los bytes del archivo en curso, y la pausa corta la conexión y continúa con una petición ",[77,129,130],{},"Range",".",[18,133,134,137,138,141,142,145],{},[21,135,136],{},"Un QR en blanco en producción."," La política de seguridad de contenido solo permitía imágenes de ",[77,139,140],{},"'self'",", y el QR se generaba como ",[77,143,144],{},"data:",". En desarrollo se veía y en el instalador no.",[18,147,148,151,152,155],{},[21,149,150],{},"Nuxt que no arrancaba en Windows."," Un fallo del socket IPC de ",[77,153,154],{},"vite-node"," en Windows obligó a bajar Nuxt a la 3.16.2 y a arrancar el servidor de desarrollo aparte de Tauri.",[18,157,158,161],{},[21,159,160],{},"La interfaz de red equivocada."," En un equipo con VPN, VirtualBox o WSL, la primera IP no es la de la red de casa. La versión 1.1 deja elegir la interfaz y regenera el enlace y el QR.",[18,163,164,167,168,171,172,175,176,179],{},[21,165,166],{},"Mutex envenenados."," Si un manejador del servidor entra en pánico con el bloqueo de las conexiones cogido, el ",[77,169,170],{},"Mutex"," queda envenenado y un ",[77,173,174],{},"lock().unwrap()"," haría fallar todas las peticiones siguientes. Los manejadores recuperan el estado con ",[77,177,178],{},"into_inner()"," en vez de propagar el error.",{"title":181,"searchDepth":182,"depth":182,"links":183},"",2,[184,185,192],{"id":12,"depth":182,"text":13},{"id":54,"depth":182,"text":55,"children":186},[187,189,190,191],{"id":59,"depth":188,"text":60},3,{"id":71,"depth":188,"text":72},{"id":92,"depth":188,"text":93},{"id":107,"depth":188,"text":108},{"id":118,"depth":182,"text":119},"Aplicación de escritorio para pasar archivos y carpetas entre dispositivos de la misma red local, sin configurar carpetas compartidas ni permisos del sistema y sin subir nada a la nube. Quien envía crea una sesión temporal con enlace y QR y acepta cada conexión con un PIN. Quien recibe descarga con la app, con pausa y reanudación a mitad de archivo y verificación SHA-256, o desde cualquier navegador, también el del móvil. Para Windows y Linux, hecha con Tauri y Rust.","md",true,"\u002Fimages\u002Fprojects\u002Fabr-transfer.svg",[198,203,207,211,215],{"src":199,"alt":200,"width":201,"height":202},"\u002Fimages\u002Fposts\u002Fabr-transfer\u002Fsesion.webp","Una sesión activa de ABR Transfer con el código QR, la interfaz de red elegida y el enlace para copiar",1024,360,{"src":204,"alt":205,"width":201,"height":206},"\u002Fimages\u002Fposts\u002Fabr-transfer\u002Fsolicitud.webp","Una solicitud de conexión desde 192.168.1.129 con su PIN de cuatro cifras y los botones de aceptar y rechazar",540,{"src":208,"alt":209,"width":201,"height":210},"\u002Fimages\u002Fposts\u002Fabr-transfer\u002Fprogreso.webp","Una descarga en curso al 30 %, a 644 MB\u002Fs y con 5 segundos restantes",220,{"src":212,"alt":213,"width":201,"height":214},"\u002Fimages\u002Fposts\u002Fabr-transfer\u002Fverificado.webp","El resumen de una descarga de 4 GB y la verificación de integridad correcta de 21 archivos",470,{"src":216,"alt":217,"width":218,"height":219},"\u002Fimages\u002Fposts\u002Fabr-transfer\u002Fnavegador.webp","La página que ve un navegador al conectarse, con la lista de archivos y los botones de descargar y descargar todo en ZIP",560,720,[221,224,227],{"label":222,"url":223},"Descargas","https:\u002F\u002Fgithub.com\u002Fabdell1999\u002Fabr-transfer-public\u002Freleases",{"label":225,"url":226},"Cómo se usa","\u002Farticulos\u002Fabr-transfer-pasar-archivos-por-la-red-local",{"label":228,"url":229},"Por dentro","\u002Farticulos\u002Fabr-transfer-por-dentro",{},17,"\u002Fproyectos\u002Fabr-transfer",[234],"escritorio",{"title":5,"description":193},[237,238,67,239,103,240,241,242,243,244,245,246,247,248],"Tauri 2","Rust","tokio","sha2","crc32fast","Nuxt 3","Vue 3","TypeScript","Pinia","Tailwind CSS","Vitest","GitHub Actions",[250,253,256,259],{"value":251,"label":252},"3,3 MB","instalador de Windows",{"value":254,"label":255},"450","tests (Vitest)",{"value":257,"label":258},"78","tests de Rust",{"value":260,"label":261},"119","commits","proyectos\u002Fabr-transfer","abr-transfer",null,"saSdO6pnhh379VxQTQ6C1s0-dF7i8YP35XjC2Z84ch4",[267,278,288,297,305,313,321,327,334,339,347,352,359,365,372,378,385,390,397,402,411,417,422,429,434,442,448,454,460],{"title":268,"description":269,"date":270,"path":271,"tags":272,"type":277},"Traducir novelas con una RTX 3080: lo que aprendí tras enfrentar cinco modelos locales al japonés y al inglés","De una skill de Claude a cinco versiones de un traductor EPUB, 96 traducciones controladas, dos modelos especializados y un fallo que duplicaba al fantasma de Oscar Wilde.","2026-11-04","\u002Farticulos\u002Ftraducir-novelas-con-una-rtx-3080",[273,274,275,276],"ia","traduccion","japones","python","tecnico",{"title":279,"description":280,"date":281,"path":282,"tags":283,"type":277},"SubFetch for YouTube por dentro: el PoToken, el mundo MAIN y una SPA que no avisa cuando cambia de vídeo","Cómo funciona una extensión de Chrome que descarga en .srt los subtítulos de YouTube y proyecta los tuyos sobre el reproductor. Respuestas 200 vacías por culpa del PoToken, dejar que el reproductor pida la pista y escuchar la respuesta desde el mundo MAIN, todo lo que se rompe cuando YouTube cambia de vídeo sin recargar la página y un overlay de subtítulos sincronizado fotograma a fotograma.","2026-11-02","\u002Farticulos\u002Fsubfetch-por-dentro",[284,285,286,287],"subfetch","arquitectura","typescript","vue",{"title":289,"description":290,"date":291,"path":292,"tags":293,"type":277},"YouTube Like Shortcut 1.5.1: tests con el HTML real de YouTube","La versión 1.5.1 cumple lo que dejé pendiente. Tests que cargan capturas reales de YouTube, el botón de los Shorts encontrado por su componente y no por su texto, y seis fallos que salieron al mirar con lupa. También lo que las capturas revelaron sobre cómo funcionaba la extensión hasta ahora.","2026-10-30","\u002Farticulos\u002Fyoutube-like-shortcut-tests-con-capturas-reales",[294,295,296,286],"youtube-like-shortcut","youtube","testing",{"title":298,"description":299,"date":300,"path":301,"tags":302,"type":277},"DualRoute por dentro: abrir pestañas desde el service worker y que tres contextos no se pisen al guardar","Cómo funciona una extensión de Chrome que abre grupos de páginas en modo normal, incógnito o ambos y lleva la cuenta de cuándo se abrió cada una. Un planificador puro, lanzamientos que viven en el service worker, el fallback cuando no hay permiso de incógnito, recordatorios con chrome.alarms, escrituras serializadas con Web Locks y un estado que no puede crecer sin límite.","2026-10-29","\u002Farticulos\u002Fdualroute-por-dentro",[303,285,286,304],"dualroute","react",{"title":306,"description":307,"date":300,"path":308,"tags":309,"type":312},"DualRoute: abrir las páginas de cada día con un clic y saber cuándo las miraste por última vez","Una extensión de Chrome para abrir de golpe las páginas que revisas a diario, cada una en modo normal, incógnito o los dos. Cómo se crean las rutas, cómo se abren en bloque, los recordatorios por horas, las notas con historial, el registro de aperturas y la exportación a JSON.","\u002Farticulos\u002Fdualroute-tus-paginas-de-cada-dia",[303,310,311],"productividad","privacidad","guia",{"title":314,"description":315,"date":316,"path":317,"tags":318,"type":312},"BlueDrop: saber dónde aparcaste sin acordarte de apuntarlo","Una app de Android que guarda la ubicación del coche en cuanto el móvil se desconecta de su Bluetooth, sin pulsar nada. Cómo se configura, qué pasa al aparcar y al volver, cómo corregir el sitio si no había GPS, y el historial, las estadísticas y el widget.","2026-10-28","\u002Farticulos\u002Fbluedrop-donde-aparque-el-coche",[319,320,310,311],"bluedrop","android",{"title":322,"description":323,"date":316,"path":324,"tags":325,"type":277},"BlueDrop por dentro: guardar la ubicación en los milisegundos que da un BroadcastReceiver","Cómo funciona una app de Android que guarda dónde aparcas cuando el móvil se desconecta del Bluetooth del coche. Un receptor que tiene que terminar enseguida, un foreground service para el trabajo lento, desconexiones duplicadas, un aparcamiento sin GPS que acababa en el océano, el cambio de Google Maps a OpenStreetMap y Clean Architecture en 10 módulos Gradle.","\u002Farticulos\u002Fbluedrop-por-dentro",[319,320,326,285],"kotlin",{"title":328,"description":329,"date":330,"path":331,"tags":332,"type":312},"Reddit Archive: ver lo que se borró de Reddit y exportar la actividad de un usuario","Una extensión de Chrome que recupera del archivo público de Arctic Shift los posts y comentarios borrados o editados de Reddit y los enseña en la misma página, marcados como archivados. Perfiles, posts con su árbol de comentarios, estadísticas y exportación a JSON, Markdown o CSV. Qué hace y cómo se usa.","2026-10-27","\u002Farticulos\u002Freddit-archive-lo-borrado-de-reddit",[333,310,311],"reddit-archive",{"title":335,"description":336,"date":330,"path":337,"tags":338,"type":277},"Reddit Archive por dentro: un visor de archivo encima de una web que no es tuya","Cómo funciona una extensión de Chrome que muestra contenido borrado de Reddit desde la API pública de Arctic Shift. Validar respuestas que no controlas, que lo archivado nunca parezca original, caché en dos niveles, rate limit, paginar por cursor para exportar la historia entera de un usuario, Markdown de terceros en Shadow DOM y un CSV que no ejecuta fórmulas.","\u002Farticulos\u002Freddit-archive-por-dentro",[333,285,286,287],{"title":340,"description":341,"date":342,"path":343,"tags":344,"type":312},"Video Accessibility: los atajos de YouTube en cualquier vídeo de la web","Una extensión de Chrome que añade los atajos de teclado de YouTube a cualquier página con un vídeo HTML. Pulsas 3 y saltas al 30 %, cambias la velocidad, haces un bucle o pulsas el botón de \"me gusta\" con una tecla. Solo en las webs que eliges y sin enviar ningún dato. Qué hace y cómo se usa.","2026-10-26","\u002Farticulos\u002Fvideo-accessibility-atajos-de-youtube-en-cualquier-video",[345,310,346,311],"video-accessibility","accesibilidad",{"title":348,"description":349,"date":342,"path":350,"tags":351,"type":277},"Video Accessibility por dentro: una capa de teclado encima de reproductores que no son tuyos","Cómo funciona una extensión de Chrome que añade atajos de teclado a cualquier vídeo HTML. Un permiso amplio con una inyección mínima, encontrar el vídeo correcto entre shadow DOM e iframes, no quedarse con teclas que no son suyas, pulsar botones ajenos con un selector CSS y un aviso en pantalla que pasó de 4,6 MB a 1 KB.","\u002Farticulos\u002Fvideo-accessibility-por-dentro",[345,285,286,287],{"title":353,"description":354,"date":355,"path":356,"tags":357,"type":277},"DevExtractor por dentro: lo que hay detrás de una extensión que parece simple","Cómo funciona una extensión de Chrome que extrae imágenes, SVG inline, enlaces y fuentes de cualquier web y sustituye imágenes en vivo. Manifest V3 con WXT, descargas desde un documento offscreen, reglas de red que no se salen de su sitio, un motor de reemplazo que se puede deshacer y botones de Instagram que no dependen del idioma.","2026-10-25","\u002Farticulos\u002Fdevextractor-por-dentro",[358,285,286,287],"devextractor",{"title":360,"description":361,"date":355,"path":362,"tags":363,"type":312},"DevExtractor: descarga SVG inline, imágenes y fuentes de cualquier web, y cambia imágenes en vivo","Una extensión de Chrome para quien hace webs. Saca todos los SVG incrustados, las imágenes, los fondos CSS, los enlaces y las fuentes de una página, los descarga en un ZIP y te deja sustituir imágenes en vivo para enseñar alternativas a un cliente. Qué hace y cómo se usa.","\u002Farticulos\u002Fdevextractor-svg-imagenes-y-fuentes-en-un-clic",[358,310,311,364],"proyectos",{"title":366,"description":367,"date":368,"path":369,"tags":370,"type":312},"ABR Offline Converter: convierte imágenes, vídeo, PDF y datos sin subir nada a ningún servidor","Un conversor de archivos que funciona entero en tu navegador. Imágenes, vídeo a GIF, vídeo a audio, CSV a JSON, PDF, fuentes y subtítulos, y un Taller del libro que convierte tus capítulos en Markdown en un EPUB con portada e índice. Qué hace y cómo se usa.","2026-10-24","\u002Farticulos\u002Foffline-converter-convierte-sin-subir-nada",[371,311,310,364],"offline-converter",{"title":373,"description":374,"date":368,"path":375,"tags":376,"type":277},"ABR Offline Converter por dentro: un conversor sin servidor, de ffmpeg.wasm a un EPUB hecho a mano","Cómo funciona un conversor de imágenes, vídeo, PDF, fuentes, subtítulos, texto y datos que no tiene backend. Workers, ffmpeg compilado a WebAssembly, codificadores BMP, ICO y TIFF escritos a mano, 811 páginas prerenderizadas y un Taller del libro que genera EPUB3 sin pandoc.","\u002Farticulos\u002Foffline-converter-por-dentro",[371,285,286,377],"nuxt",{"title":379,"description":380,"date":381,"path":382,"tags":383,"type":312},"Simple TTS: escucha cualquier artículo de la web en voz alta, sin salir de tu navegador","Una extensión gratuita para Chrome y Edge que lee en voz alta lo que selecciones o el artículo entero con las voces del propio navegador. Sin cuentas, sin servidores y sin APIs externas. Qué hace y cómo se usa.","2026-10-23","\u002Farticulos\u002Fsimple-tts-escucha-cualquier-web",[384,311,310,364],"simple-tts",{"title":386,"description":387,"date":381,"path":388,"tags":389,"type":277},"Simple TTS por dentro: mi primera extensión, de JavaScript a WXT con Vue","Cómo pasó Simple TTS de tres archivos de JavaScript a una extensión Manifest V3 con WXT, Vue 3 y TypeScript. Qué me hizo cambiar en cada etapa, cómo se mantiene vivo un service worker durante una lectura larga, por qué leía la frase del día anterior y cómo se consigue que el resaltado vaya a la par de la voz.","\u002Farticulos\u002Fsimple-tts-por-dentro",[384,285,286,287],{"title":391,"description":392,"date":393,"path":394,"tags":395,"type":277},"TranscribeLocal por dentro: Whisper en el navegador y cómo dejó de inventarse frases","Cómo ejecuta TranscribeLocal Whisper, la separación de hablantes y un modelo de lenguaje dentro del navegador con Transformers.js, por qué Whisper se inventaba frases en los silencios, qué hace falta para transcribir audios largos y por qué un service worker cortaba las descargas a los cinco minutos.","2026-10-22","\u002Farticulos\u002Ftranscribe-local-por-dentro",[396,273,285,286,377],"transcribe-local",{"title":398,"description":399,"date":393,"path":400,"tags":401,"type":312},"TranscribeLocal: transcribe y saca subtítulos de cualquier vídeo, sin salir de tu navegador","Una app web que convierte audio y vídeo en texto y subtítulos con Whisper, distingue quién habla y hace resúmenes, todo en tu ordenador. Sin subir nada a ningún servidor, sin límites de duración y gratis. Qué hace y cómo se usa.","\u002Farticulos\u002Ftranscribe-local-subtitulos-en-tu-navegador",[396,273,311,364],{"title":403,"description":404,"date":405,"path":406,"tags":407,"type":312},"PokeStore: un tema de WordPress a medida para tiendas de cartas coleccionables","Un tema de WordPress y WooCommerce hecho desde cero para tiendas de Pokémon y One Piece TCG. Un recorrido por la tienda como la ve quien compra, de la portada a la lista de deseos, y por lo que puede ajustar quien la lleva.","2026-10-21","\u002Farticulos\u002Fpokestore-tema-wordpress-para-tiendas-tcg",[408,409,410,364],"pokestore","wordpress","woocommerce",{"title":412,"description":413,"date":414,"path":415,"tags":416,"type":312},"YouTube Like Shortcut: da like con una tecla, como en TikTok","Una extensión de Chrome que da like al vídeo o Short de YouTube que estás viendo al pulsar la L. Cómo se instala, qué opciones tiene y por qué no se dispara mientras escribes.","2026-10-20","\u002Farticulos\u002Fyoutube-like-shortcut-like-con-una-tecla",[294,295,310,364],{"title":418,"description":419,"date":414,"path":420,"tags":421,"type":277},"YouTube Like Shortcut por dentro: pulsar un botón en una web que cambia sin avisar","Cómo una extensión de una sola función llega antes que el reproductor de YouTube, encuentra el botón de like entre variantes ocultas y layouts que cambian con el ancho de la ventana, y se asegura de que el like ha entrado aunque YouTube esté reconstruyendo la página.","\u002Farticulos\u002Fyoutube-like-shortcut-por-dentro",[294,295,285,286],{"title":423,"description":424,"date":425,"path":426,"tags":427,"type":312},"AI Upscaler: amplía imágenes y quita fondos con IA, sin salir de tu navegador","Una extensión de Chrome que amplía imágenes ×2 o ×4 y elimina fondos con inteligencia artificial, todo en tu equipo. Sin subir nada a ningún servidor, sin cuentas y gratis. Qué hace y cómo se usa.","2026-10-19","\u002Farticulos\u002Fai-upscaler-imagenes-con-ia-en-tu-navegador",[428,273,311,364],"ai-upscaler",{"title":430,"description":431,"date":425,"path":432,"tags":433,"type":277},"AI Upscaler por dentro: dos redes neuronales en una extensión de Chrome","Cómo ejecuta AI Upscaler Real-ESRGAN y U²-Net dentro del navegador con ONNX Runtime Web, por qué la imagen se procesa en mosaicos con margen, qué hubo que parchear en el modelo de quitar fondos y qué obstáculos pone una extensión Manifest V3 a los workers y al WebAssembly.","\u002Farticulos\u002Fai-upscaler-por-dentro",[428,273,285,286,287],{"title":435,"description":436,"date":437,"path":438,"tags":439,"type":312},"ABR Cipher: cifrado seguro, completamente en tu navegador","Una suite de cifrado que no envía nada a ningún servidor. Cifrar textos y archivos, compartir secretos con un enlace que caduca, guardar contraseñas y destruir archivos. Qué hace y cómo se usa.","2026-10-18","\u002Farticulos\u002Fabr-cipher-cifrado-en-tu-navegador",[440,441,311,364],"cipher","seguridad",{"title":443,"description":444,"date":437,"path":445,"tags":446,"type":277},"ABR Cipher por dentro: criptografía sin servidor, de la URL al disco","Por qué ABR Cipher solo usa la Web Crypto API, cómo viaja un secreto en el fragmento de una URL, cómo se cifra un archivo de varios GB en el navegador y qué hace falta para destruir un archivo de verdad, con un compañero en Rust que lee NTFS.","\u002Farticulos\u002Fabr-cipher-por-dentro",[440,441,285,286,447],"rust",{"title":449,"description":450,"date":437,"path":451,"tags":452,"type":277},"ABReader por dentro: el lector que no encontré, construido a mi medida","Voces neuronales que se ejecutan en el navegador, sincronización entre dispositivos sin servidor y once formatos detrás de un mismo contrato. Las decisiones técnicas de ABReader y por qué las tomé.","\u002Farticulos\u002Fabreader-por-dentro",[453,285,286,377],"abreader",{"title":455,"description":456,"date":437,"path":457,"tags":458,"type":312},"ABReader: tu biblioteca de libros electrónicos en el navegador","Un lector de libros electrónicos que funciona en el navegador, sin cuentas ni servidores. Qué hace, cómo se usa y cómo probarlo en un minuto.","\u002Farticulos\u002Fabreader-tu-biblioteca-en-el-navegador",[453,459,364],"lectura",{"title":461,"description":462,"date":437,"path":463,"tags":464,"type":277},"Cómo construí este blog: estático, sin servidor y sin coste de hosting","Por qué elegí Nuxt y Markdown en lugar de WordPress, cómo separo el código privado del sitio publicado, qué se rompió en el primer despliegue y cómo funcionan los artículos programados, el buscador sin servidor y los filtros.","\u002Farticulos\u002Farquitectura-de-este-blog",[377,287,465,466],"devops","meta",1793761190266]