KITKIT 19 ago 2026Aug 19, 2026
Dashboard personal: el patrón general Personal dashboard: the general pattern
Las recetas anteriores son casos particulares de una misma idea: tomar un dato que ya es tuyo, convertirlo en JSON y servirlo en una página estática. Aquí está el patrón completo. The two previous recipes are specific cases of the same idea: take data that's already yours, turn it into JSON, and serve it on a static page. Here is the full pattern.
Los promptsThe prompts
Archivos de texto. Ábrelos, cópialos y pégalos en el asistente que uses. Plain text files. Open them, copy and paste into whichever assistant you use.
Esta receta no es sobre un dato concreto. Es sobre el patrón que hay detrás de casi cualquier dashboard personal: un origen de datos tuyo, un script que lo transforma en JSON, y una página HTML que lo lee. Si entiendes el patrón, puedes aplicarlo a gastos, salud, correos, agenda, lecturas, inversiones o lo que sea.
El patrón en una línea
Tu dato → [script Python] → datos.json → [nginx/GitHub Pages] → index.html
La página es estática. La magia está en que datos.json se reemplaza cada día automáticamente.
Lo que vas a montar
- Un script
extract.pyque baja o lee tus datos. - Un script
build.pyque los transforma endatos.json. - Un archivo
index.htmlque pinta el JSON. - Un cron en tu servidor que corre
extract.py && build.pycada mañana. - Un endpoint de ingesta en tu servidor que recibe el JSON por PUT (opcional, útil si el script corre en tu PC y la página en un VPS).
Tres errores de sistema que no salen en tutoriales
1. El salto de línea que te deja fuera del servidor
Cuando añades tu llave SSH a authorized_keys, si la llave que ya estaba no termina en \n, tu llave se pega a la misma línea. sshd ignora ambas y no puedes entrar. Diez minutos de pánico por un carácter invisible.
Solución: asegúrate de que cada línea termine en newline antes de cerrar el archivo.
2. Windows mete \r por todas partes
Editas scripts en tu PC con Windows, los subes al servidor Linux y de repente /bin/bash^M: bad interpreter. Los finales de línea CRLF rompen el shell.
Solución: configura tu editor para guardar con LF, o corre sed -i 's/\r$//' script.sh en el servidor.
3. El crontab que se borra solo
Instalas un cron con set -e y luego haces grep para ver si ya existe. Si no existe, grep devuelve código de salida 1 y set -e aborta el script, dejando el crontab vacío.
Solución: usa un archivo temporal y || true:
tmp=$(mktemp)
crontab -l 2>/dev/null > "$tmp" || true
grep -q 'mi_script.sh' "$tmp" || \
echo '50 5 * * * /var/www/midominio/mi_script.sh' >> "$tmp"
crontab "$tmp"
rm -f "$tmp"bash
El problema de la “fecha de actualización”
Es tentador poner en el JSON un campo actualizado con la fecha de hoy del sistema. Eso miente. Si tu API o export falló, el archivo se actualizó pero el dato es de ayer.
La regla: actualizado debe ser la fecha real del último dato que entró. En el HTML, compara con hoy y muestra “Hace N días” o “Atrasado” cuando toque.
Acumular, no regenerar
Un error común es borrar datos.json y volverlo a generar cada vez. Si un día falla la extracción, pierdes todo el histórico. Es mejor tener archivos intermedios (historico.json, actividades.json, etc.) que solo crecen, y un merge diario que añade o actualiza.
# Pseudo-código
datos_viejos = leer("historico.json")
datos_nuevos = extraer_hoy()
merge(datos_viejos, datos_nuevos) # actualiza, no borra
escribir("historico.json", datos_viejos)python
Qué puede salir mal
- La tarea vive solo en tu máquina. Si el script corre en tu PC y la apagas, la página no se actualiza. La solución robusta es un VPS o un Raspberry Pi siempre encendido.
- Tokens que caducan. Toda API que requiera OAuth o login con MFA necesita refresco manual cada varios meses. La señal es que
actualizadose congela. - Dependencias externas. Si cargas librerías de gráficas desde un CDN, tu dashboard se rompe si el CDN cae o cambia la URL. Mejor alojarlas tú mismo o, mejor aún, no usarlas.
- Permisos de archivo. El cron corre como otro usuario; el archivo generado puede no ser legible por nginx. Verifica propietario y permisos (
chmod 644,chown www-data).
Límite honesto: si no quieres pagar un VPS ni dejar una máquina encendida, este patrón no es para ti. Puedes correr el script a mano cuando quieras, pero no será “se actualiza sola”.
This recipe is not about a specific dataset. It’s about the pattern behind almost any personal dashboard: a data source of yours, a script that transforms it into JSON, and an HTML page that reads it. If you understand the pattern, you can apply it to expenses, health, emails, calendar, reading, investments or anything else.
The pattern in one line
Your data → [Python script] → data.json → [nginx/GitHub Pages] → index.html
The page is static. The magic is that data.json is replaced automatically every day.
What you will build
- An
extract.pyscript that downloads or reads your data. - A
build.pyscript that transforms it intodata.json. - An
index.htmlfile that renders the JSON. - A cron on your server that runs
extract.py && build.pyevery morning. - An ingest endpoint on your server that receives the JSON via PUT (optional, useful if the script runs on your PC and the page is on a VPS).
Three system errors that tutorials don’t show
1. The line break that locks you out of the server
When you add your SSH key to authorized_keys, if the existing key doesn’t end in \n, your key gets glued onto the same line. sshd ignores both and you can’t log in. Ten minutes of panic over an invisible character.
Solution: make sure every line ends with a newline before closing the file.
2. Windows inserts \r everywhere
You edit scripts on your Windows PC, upload them to a Linux server and suddenly /bin/bash^M: bad interpreter. CRLF line endings break the shell.
Solution: configure your editor to save with LF, or run sed -i 's/\r$//' script.sh on the server.
3. The crontab that deletes itself
You install a cron with set -e and then run grep to check if it already exists. If it doesn’t, grep exits with code 1 and set -e aborts the script, leaving the crontab empty.
Solution: use a temp file and || true:
tmp=$(mktemp)
crontab -l 2>/dev/null > "$tmp" || true
grep -q 'my_script.sh' "$tmp" || \
echo '50 5 * * * /var/www/mydomain/my_script.sh' >> "$tmp"
crontab "$tmp"
rm -f "$tmp"bash
The “last updated” problem
It’s tempting to put today’s system date in the JSON updated field. That lies. If your API or export failed, the file was updated but the data is from yesterday.
The rule: updated must be the real date of the latest data point. In the HTML, compare with today and show “N days ago” or “Stale” when needed.
Accumulate, don’t regenerate
A common mistake is deleting data.json and regenerating it every time. If extraction fails one day, you lose all history. It’s better to have intermediate files (history.json, activities.json, etc.) that only grow, and a daily merge that adds or updates.
# Pseudo-code
old_data = read("history.json")
new_data = extract_today()
merge(old_data, new_data) # updates, does not delete
write("history.json", old_data)python
What can go wrong
- The task lives only on your machine. If the script runs on your PC and you turn it off, the page doesn’t update. The robust solution is a VPS or a Raspberry Pi that’s always on.
- Tokens expire. Any API requiring OAuth or MFA login needs manual refresh every few months. The signal is that
updatedfreezes. - External dependencies. If you load chart libraries from a CDN, your dashboard breaks if the CDN goes down or changes URLs. Better self-host them, or don’t use them at all.
- File permissions. The cron runs as a different user; the generated file may not be readable by nginx. Check owner and permissions (
chmod 644,chown www-data).
Honest limit: if you don’t want to pay for a VPS or leave a machine on, this pattern isn’t for you. You can run the script manually whenever you want, but it won’t be “self-updating.”