Skip to content

Katamo/migas

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

migas

Analytics propio sin servicios externos. Registra visitas desde cualquier proyecto y visualízalas en un dashboard local.

Tres partes independientes:

  • tracker/ — módulo PHP portable. Se copia en el servidor de cada proyecto a trackear.
  • viewer/ — Vue SPA + proxy PHP. Corre en local con un solo comando; desplegable a servidor sin cambios de código.
  • app/ — wrapper Electron opcional. Empaqueta el viewer como app de escritorio.
[Proyecto A]                    [Proyecto B]
  Vue SPA → POST /tracker/log.php    Vue SPA → POST /tracker/log.php
                  ↓                                  ↓
            visits.log (JSONL)              visits.log (JSONL)
                  ↑ Bearer token                      ↑ Bearer token
            GET /tracker/read.php             GET /tracker/read.php
                       ↑                              ↑
          ┌─────────────────────────────────────────────┐
          │  viewer/api/fetch.php  (secrets server-side) │
          │  viewer Vue SPA  →  GET /api/fetch.php       │
          └─────────────────────────────────────────────┘
              LOCAL:  npm run dev  (Vite intercepta /api/*)
              PROD:   dist/ + api/fetch.php en servidor

Inicio rápido

¿Primera vez con migas? Estos son los pasos esenciales:

  1. Copia tracker/ al servidor del proyecto que quieres monitorizar (por FTP, SCP o el gestor de archivos de tu hosting).
  2. Crea tracker/tracker.config.json con un token secreto, los dominios permitidos y la ruta donde se guardará el log.
  3. Crea el archivo de log vacío con los permisos correctos para que PHP pueda escribir en él.
  4. Añade las reglas nginx para proteger los archivos sensibles y activar PHP en los endpoints del tracker.
  5. Añade el snippet de tracking a las páginas que quieras medir (2 líneas de JavaScript).
  6. Arranca el viewer: cd viewer && npm install && npm run dev, configura tus proyectos en viewer.config.json y abre http://localhost:5173.

Los pasos 1–5 se explican con detalle a continuación en la sección tracker/. El viewer se describe en viewer/.


tracker/

Instalación en un proyecto

  1. Copia la carpeta tracker/ al servidor del proyecto (por ejemplo en /var/www/mi-proyecto/tracker/).

  2. Crea tracker/tracker.config.json a partir del ejemplo:

{
  "read_secret": "TOKEN_ALEATORIO_LARGO",
  "allowed_origins": ["https://mi-proyecto.com", "http://localhost:5173"],
  "log_path": "/var/www/mi-proyecto/visits.log"
}
  • read_secret — token para proteger read.php. Genera uno con openssl rand -hex 32.
  • allowed_origins — dominios autorizados a enviar visitas a log.php. Incluye http://localhost:5173 durante el desarrollo del viewer.
  • log_path — ruta absoluta donde se escribirá visits.log. Puede estar fuera del webroot.
  1. Crea el archivo de log vacío con los permisos correctos:
sudo touch /var/www/mi-proyecto/visits.log
sudo chown www-data:tu-usuario /var/www/mi-proyecto/visits.log
sudo chmod 664 /var/www/mi-proyecto/visits.log

El proceso PHP (www-data en la mayoría de servidores) necesita permiso de escritura. Si log_path apunta fuera del webroot, crea también el directorio con los mismos permisos.

  1. Añade estas reglas a nginx para proteger los archivos sensibles:
location ~* \.log$ { deny all; }
location = /tracker/tracker.config.json { deny all; }
location ~ ^/tracker/(log|read|flush)\.php$ {
    fastcgi_pass unix:/run/php/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}
  1. Añade el snippet de tracking al proyecto (Vue, vanilla JS, o donde sea):
navigator.sendBeacon('/tracker/log.php', JSON.stringify({
  path:     location.pathname,
  referrer: document.referrer,
  screen:   `${screen.width}x${screen.height}`,
  lang:     navigator.language,
}))

O como llamada fetch si prefieres controlar el timing:

fetch('/tracker/log.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    path:     location.pathname,
    referrer: document.referrer,
    screen:   `${screen.width}x${screen.height}`,
    lang:     navigator.language,
  }),
})

Verificar que funciona

# Registrar una visita
curl -X POST https://mi-proyecto.com/tracker/log.php \
  -H "Content-Type: application/json" \
  -H "Origin: https://mi-proyecto.com" \
  -d '{"path":"/","referrer":"","screen":"1920x1080","lang":"es"}'
# → HTTP 204

# Leer el log
curl https://mi-proyecto.com/tracker/read.php \
  -H "Authorization: Bearer TOKEN_ALEATORIO_LARGO"
# → JSONL con las visitas

Endpoints

Endpoint Método Descripción
log.php POST Recibe { path, referrer, screen, lang }, añade ts y ua, escribe en visits.log
read.php GET Devuelve visits.log en JSONL. Requiere Authorization: Bearer <read_secret>
flush.php POST Vacía visits.log. Requiere Authorization: Bearer <read_secret>

flush.php — vaciado del log

Permite truncar el log de visitas desde el viewer sin acceso directo al servidor. El viewer descarga primero los datos como backup local antes de llamar a este endpoint.

# Vaciar el log de un proyecto
curl -X POST https://mi-proyecto.com/tracker/flush.php \
  -H "Authorization: Bearer TOKEN_ALEATORIO_LARGO"
# → HTTP 204

Reutiliza el mismo read_secret que read.php. No hay token separado.


viewer/

Dashboard Vue que lee los logs de todos los proyectos trackeados.

Dependencias

  • Node.js 18+
  • Bedrock — sistema de diseño CSS/Vue

Instalación

cd viewer
npm install

Configuración

Crea viewer/viewer.config.json a partir del ejemplo:

cp viewer.config.example.json viewer.config.json

Edita el archivo con tus proyectos:

{
  "viewer_token": "",
  "projects": [
    {
      "name": "mi-proyecto",
      "read_url": "https://mi-proyecto.com/tracker/read.php",
      "read_secret": "TOKEN_ALEATORIO_LARGO"
    }
  ]
}
  • viewer_token — vacío en local (sin auth). Rellena con un token largo si despliegas el viewer a un servidor.
  • projects — lista de proyectos a monitorizar. Cada uno necesita la URL de read.php y el token correspondiente.
    • hidden: true — oculta el proyecto del selector. Útil para proyectos de prueba. Sigue siendo accesible directamente vía ?project=nombre.

Desarrollo local

cd viewer
npm run dev
# → http://localhost:5173

El servidor de Vite intercepta las peticiones a /api/fetch.php en Node.js, leyendo viewer.config.json y llamando a cada read_url. No hace falta PHP en local.

Build para producción

cd viewer
npm run build
# → dist/

Despliega dist/ y api/ juntos en el mismo servidor. El PHP proxy (api/fetch.php) mantiene los secrets server-side y valida viewer_token si está configurado.

/var/www/migas/
├── index.html         ← dist/
├── assets/            ← dist/assets/
├── api/
│   └── fetch.php
└── viewer.config.json

Autenticación en producción

Cuando el viewer esté en un servidor, activa el viewer_token en viewer.config.json:

{
  "viewer_token": "OTRO_TOKEN_LARGO",
  ...
}

El SPA deberá enviar el header X-Viewer-Token: OTRO_TOKEN_LARGO en cada petición. Añade una pantalla de login o protege el acceso con la autenticación que prefieras.


app/ — App de escritorio (Electron)

app/ es un wrapper de Electron que empaqueta el viewer como una aplicación de escritorio. No modifica ningún archivo de viewer/ — consume su output compilado.

Cómo funciona

  • Levanta un servidor HTTP local en un puerto aleatorio
  • Sirve viewer/dist/ como archivos estáticos
  • Registra los mismos handlers de /api/fetch.php y /api/flush.php que en el dev server de Vite
  • Abre una BrowserWindow apuntando a http://127.0.0.1:{puerto}
  • Lee viewer/viewer.config.json desde su ubicación original — sin duplicar el archivo

Dependencias

  • Node.js 18+
  • Electron (instalado en app/node_modules/)
cd app
npm install

Uso en desarrollo

Compila el viewer si no está compilado y lanza la app directamente con Electron:

cd viewer && npm run build
cd ../app  && npm start

La ventana abre sin terminal visible. viewer/viewer.config.json se lee en caliente — cualquier cambio en el config se aplica en la siguiente acción sin reiniciar.

Generar el ejecutable

# 1. Compilar el viewer
cd viewer && npm run build

# 2. Empaquetar la app
cd ../app && npm run build
# → app/dist/win-unpacked/migas.exe

El exe incluye viewer/dist/ bundleado en resources/viewer-dist/. El viewer.config.json no se bundlea — se lee desde su ruta original en el repositorio.

Estructura del output:

app/dist/win-unpacked/
├── migas.exe
└── resources/
    └── viewer-dist/     ← copia de viewer/dist/ en el momento del build

Si añades proyectos a viewer.config.json no hace falta recompilar. Si cambia el código del viewer hay que repetir los dos pasos.


Estructura de archivos

migas/
├── tracker/
│   ├── log.php                       # Recibe visitas (POST)
│   ├── read.php                      # Devuelve logs (GET, protegido)
│   ├── flush.php                     # Vacía el log (POST, protegido)
│   └── tracker.config.example.json   # Template de configuración
│
├── viewer/
│   ├── src/
│   │   ├── main.js
│   │   ├── App.vue
│   │   ├── router.js                     # Vue Router (hash history)
│   │   ├── views/
│   │   │   ├── OverviewView.vue          # Vista principal — resumen de todos los proyectos
│   │   │   └── ProjectView.vue           # Vista de detalle — visitas + stats de un proyecto
│   │   ├── composables/
│   │   │   └── useProjectData.js         # Estado compartido (proyectos, visitas, caché)
│   │   └── components/
│   │       ├── app-shell/                # Cabecera y layout principal
│   │       ├── c-project-card/           # Tarjeta resumen por proyecto
│   │       ├── c-project-stats/          # Contadores y rankings (paths, referrers, etc.)
│   │       ├── c-visit-table/            # Tabla paginada de visitas
│   │       ├── c-filter-bar/             # Filtros por ruta y fecha
│   │       └── c-confirm-modal/          # Modal de confirmación (usado en flush)
│   ├── api/
│   │   ├── fetch.php                     # Proxy PHP — leer logs (solo en producción)
│   │   └── flush.php                     # Proxy PHP — vaciar log (solo en producción)
│   ├── viewer.config.example.json
│   ├── package.json
│   └── vite.config.js                    # Middlewares dev para /api/fetch.php y /api/flush.php
│
├── app/
│   ├── electron/
│   │   └── main.js                   # Proceso principal: servidor HTTP + BrowserWindow
│   └── package.json                  # electron + electron-builder
│
├── dev/
│   └── visits.log                    # Log de prueba con datos ficticios
│
└── .gitignore                        # Excluye *.config.json, node_modules/, dist/

Seguridad

Activo Protección
visits.log Nunca servido directamente — nginx lo bloquea
tracker/read.php Authorization: Bearer <read_secret>
tracker.config.json Gitignored + bloqueado por nginx
viewer/api/fetch.php X-Viewer-Token — desactivado en local, activable en producción
viewer.config.json Gitignored, nunca llega al bundle JS

Los read_secret de cada proyecto viven únicamente en viewer.config.json (server-side). El SPA nunca los ve.


Releases

El script deploy.ps1 en la raíz del proyecto gestiona el versionado y la publicación en GitHub. No requiere Lanzadera ni acceso a ningún servidor.

.\deploy.ps1 release   # propone versión, crea tag y publica en GitHub
.\deploy.ps1 github    # push + tags sin crear versión nueva

El flujo habitual es:

  1. Completar tareas y actualizar el CHANGELOG con la nueva versión
  2. Hacer commit de los cambios
  3. Ejecutar .\deploy.ps1 release

El script lee la última versión del CHANGELOG para proponerla automáticamente. Si ya tiene tag en git, propone el siguiente patch con opción de elegir minor o major.


Privacidad (LGPD / GDPR)

migas no recopila ni almacena la dirección IP de los visitantes. Los únicos datos que escribe log.php en visits.log son:

Campo Origen Ejemplo
path Enviado por el SPA /mix/001
referrer Enviado por el SPA https://google.es
screen Enviado por el SPA 1920x1080
lang Enviado por el SPA es
ts Generado en el servidor 2026-05-28T10:12:34+02:00
ua $_SERVER['HTTP_USER_AGENT'] cadena del navegador

El User-Agent puede considerarse un dato personal en algunas jurisdicciones — trátalo con las mismas precauciones que cualquier otro dato de analítica.


Instalación con Lanzadera (opcional)

Lanzadera es una herramienta de deploy para proyectos Vue que puede automatizar la instalación del tracker. No es necesaria para usar migas — la instalación manual descrita arriba es el path principal.

Si ya usas Lanzadera en el proyecto destino, añade la sección tracker a tu project.config.json:

{
  "tracker": {
    "enabled": true,
    "read_secret": "TOKEN_ALEATORIO_LARGO",
    "log_path": "/var/log/migas/mi-proyecto/visits.log"
  }
}

Y en machine.config.json, indica dónde está el código fuente del tracker en tu máquina:

{
  "trackerSourcePath": "C:/Users/tu-usuario/WORK/migas/tracker"
}

Con esta configuración, .\deploy.ps1 tracker automatiza lo que los pasos 1–4 de la instalación manual describen:

  • Copia log.php, read.php y flush.php al servidor
  • Genera tracker.config.json con los valores del project config
  • Crea el archivo de log con chown www-data y chmod 664

Las reglas nginx se añaden al ejecutar .\deploy.ps1 nginx o .\deploy.ps1 setup.

About

A short project to track visits to my projects

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors