Proyecto 01 — Digitale PSM

Una base de datos
en el navegador.

Digitale PSM es una aplicación web gratuita y de código abierto para empresas agrícolas y hortícolas. Permite calcular, registrar y exportar tratamientos fitosanitarios. Sin cuenta, backend ni nube. Todos los datos se guardan en un archivo SQLite en el equipo del usuario, y la base de datos se ejecuta mediante WebAssembly en el navegador.

Por Abbas Hoseiny·Desde 04/2025·Versión 2.0·Licencia MIT

El uso profesional de productos fitosanitarios exige registrar cada tratamiento: producto, cantidad, superficie, cultivo, fecha y plazo de seguridad. En la práctica, esos registros suelen acabar en carpetas de papel o en servicios en la nube con cuenta, suscripción y servidores ajenos. Digitale PSM ofrece otra vía: una aplicación web que se comporta como un programa local, mantiene los datos en un archivo del usuario y funciona sin conexión.

Pantalla inicial de Digitale PSM en un ordenador: crear una base o abrir un archivo existente
Pantalla inicial de Digitale PSM en un teléfono
Fig. 1 — la pantalla inicialdigitale-psm.de en ordenador y teléfono

Sin inicio de sesión ni registro. La aplicación solo pregunta si quieres crear una base de datos o abrir un archivo existente. El archivo es una base SQLite normal en tu ordenador: se puede copiar, respaldar y consultar con cualquier herramienta compatible.

Funciones

Calcular, registrar y justificar.

Cálculo
Dosis por superficie o cantidad, conversión de unidades, perfiles para combinaciones habituales y selección rápida de códigos EPPO y estadios BBCH.
Registro
Registro de cada tratamiento, vista de calendario con filtros y exportación a PDF o CSV.
Autorizaciones oficiales
Tras la importación, la base de autorizaciones del BVL queda en tu propio archivo. Permite buscar por cultivo, plaga y sustancia activa, también sin conexión.
Aplicación de escritorio sin conexión
Instalable desde Chrome o Edge, arranca sin red, recuerda la última base de datos y abre archivos .sqlite con doble clic. Incluye ubicaciones GPS de las parcelas.
Tecnología

Cómo se guardan los datos

El diseño habitual sería un servidor con una base de datos y una cuenta por usuario. Yo quería que los datos quedaran en manos de la empresa, en un único archivo de su ordenador. Para eso, la base de datos tenía que ejecutarse donde están los datos: en el navegador.

1. Un archivo en lugar de un servidor

La aplicación consiste en HTML, CSS y JavaScript estáticos, alojados en GitHub Pages. Ningún servidor recibe los registros. SQLite está compilado como módulo WebAssembly (@sqlite.org/sqlite-wasm) e incluido en la aplicación, con hash y versión asignados durante la compilación, igual que los demás archivos. No se descarga nada de CDN de terceros durante la ejecución; por eso la base de datos también funciona sin conexión.

Un detalle importante: el archivo del usuario es una base de datos SQLite real, no un formato de exportación propio. Se abre con cualquier herramienta SQLite y se puede respaldar, copiar o trasladar a otro equipo.

2. Tres capas

La base de datos no se ejecuta en el hilo principal del navegador, sino en un Web Worker independiente. Así la interfaz sigue respondiendo durante importaciones grandes. Ambos se comunican únicamente mediante mensajes.

Interfaz · hilo principal
Astro, TypeScript, Bootstrap
  • Formularios, calendario, listas y exportación PDF/CSV
  • Estado y bus de eventos
  • Comunicación con la base de datos solo por mensajes
  • Mantiene el acceso al archivo y escribe en él
⇄postMessage
ID, tiempo de espera,
transferencia de búferes grandes
Base de datos · Web Worker
SQLite 3.54 mediante WebAssembly
  • Esquema con migraciones: user_version de 1 a 11
  • WAL, claves externas y caché de páginas de 20 MB
  • Consultas, listas paginadas e importación del BVL
  • Exportación de la base completa como bytes
⇄bytes
exportación · importación
Almacenamiento · del usuario
Un archivo .sqlite
  • File System Access API; identificador de archivo guardado en IndexedDB para el arranque automático
  • Modo OPFS si el navegador lo permite
  • Alternativas: archivo JSON, localStorage y memoria

3. Guardado, paso a paso

  1. Una entrada, por ejemplo un tratamiento nuevo, se envía al worker como mensaje. Cada mensaje lleva un ID y un tiempo límite; la respuesta llega de forma asíncrona.
  2. El worker escribe en su base SQLite, situada en su memoria o, si el navegador lo permite, en Origin Private File System (OPFS).
  3. Después exporta la base completa como una secuencia de bytes (sqlite3_js_db_export) y transfiere el búfer al hilo principal sin copiarlo, mediante Transferable.
  4. El hilo principal escribe los bytes en el archivo .sqlite del usuario mediante su identificador de acceso: createWritable, write y close. El archivo del disco contiene así una base completa y coherente.
  5. Los cambios consecutivos se agrupan. Si ya hay una escritura en curso, la aplicación anota que debe repetirla al terminar. Así se escribe una vez por cada grupo de cambios, no por cada pulsación.

4. Abrir según el contenido del archivo

Al abrir un archivo, la aplicación lee sus bytes y comprueba la firma inicial: SQLite format 3. Decide el contenido, no la extensión. Un archivo llamado .json puede contener una base binaria. Las versiones antiguas guardaban JSON y esa mezcla hizo que una base intacta pareciera «vacía». Desde entonces, la firma determina el formato.

Si es SQLite, el worker convierte el archivo en la base activa con sqlite3_deserialize. En modo OPFS, OpfsDb.importDb lo importa al archivo persistente. Si es JSON, se importa como una instantánea de los datos. Ambas rutas terminan en la misma base y ejecutan las migraciones.

5. Preparación de los datos del BVL

La base oficial de autorizaciones del BVL, la Oficina Federal alemana de Protección del Consumidor y Seguridad Alimentaria, está disponible mediante una API pública. Sin embargo, tiene numerosos endpoints, requiere muchas peticiones y no permite trabajar sin conexión. Por eso preparo los datos por adelantado en un proceso independiente, en el repositorio público pflanzenschutz-db:

  1. Cada dos días, GitHub Actions descarga los datos de todos los endpoints del BVL, los valida y añade información, como indicadores de uso en agricultura ecológica, nombres de sustancias activas e indicaciones de peligro.
  2. El resultado es un archivo SQLite, comprimido con Brotli y ZIP, publicado en GitHub Pages junto con un manifiesto que indica el tamaño y la suma SHA-256 de cada archivo.
  3. La aplicación descarga el manifiesto, elige el formato más pequeño que el navegador pueda descomprimir, muestra el progreso y entrega los bytes al worker.
  4. El worker abre la descarga como una base temporal en memoria y copia sus tablas a la base del usuario dentro de una única transacción. Respeta el orden de dependencias para mantener las claves externas.
  5. El catálogo completo queda en el archivo .sqlite del usuario y se puede consultar sin conexión. Un registro dentro de la base indica qué versión se importó.
Datos del 25 de octubre de 2026Valor
Productos del catálogo2,165
Usos autorizados (producto por cultivo y plaga)30,836
Sustancias activas482
Descarga, Brotli / ZIP6.8 MB / 12.5 MB
Sin comprimir, SQLite113 MB

6. Sin conexión y como aplicación

Al instalarse, un service worker guarda en caché todos los archivos de compilación con hash, incluido el módulo WebAssembly. Después, la aplicación arranca sin red. Cada compilación incorpora una nueva versión de caché al service worker. Sin ese cambio, los usuarios con la aplicación instalada conservarían el código antiguo, porque el navegador no reinstala un service worker idéntico byte por byte.

Como aplicación de escritorio instalada, Digitale PSM se registra mediante File Handling API para .sqlite, .db y .json. Un doble clic en el explorador abre directamente la base. El identificador del último archivo se guarda en IndexedDB; al volver a arrancar, la aplicación solo pide permiso y abre el mismo archivo.

7. Rendimiento y robustez

8. Limitaciones actuales

9. Ficha técnica

Aplicacióndigitale-psm.de — gratuita, sin publicidad ni cuenta
IdiomaAlemán; la aplicación sigue la normativa alemana de autorizaciones y la base del BVL
InicioAbril de 2025; versión actual 2.0
Licencia y códigoMIT, código fuente en GitHub
TecnologíasAstro 5, TypeScript, Bootstrap 5 incluido localmente, SQLite 3.54 mediante WebAssembly, Web Worker, service worker y manifiesto de aplicación web
AlmacenamientoArchivo SQLite del usuario mediante File System Access API; OPFS cuando está disponible; alternativas con archivo JSON y localStorage
Datos de autorizacionesAPI del BVL, preparación en pflanzenschutz-db mediante GitHub Actions cada dos días, distribución en Brotli/ZIP con manifiesto y SHA-256
AlojamientoArchivos estáticos en GitHub Pages; compilación y despliegue con GitHub Actions
Proyecto relacionadost.digitale-psm.de: panel de estadísticas de la base del BVL, con consultas SQL directamente en el navegador