Como funciona esta web? - Colophon ✱
Esta web esta armada 100% por mi, voy a documentar y a explicar un poco como funciona, que tecnología utilice, que procesos uso para hacer el deploy, para hacer el build y demás detalles que tiene.
Esta página web es 100% estática, para eso utilizo {{Hugo}}, que me permite buildear la web a partir de archivos Markdown. Esta página se divide en dos partes, por un lado esta mi {{Digital Garden}} que vendría a ser la mayor parte del contenido y por otro lado están las demás secciones como por ejemplo el /now🡭 , /gallery🡭 , /uses🡭 y páginas externas como mi cv🡭 .
La parte de mi {{Digital Garden}} la manejo dentro de {{Obsidian}}, en este documento explico un poco mas en detalle como es el proceso. Lo bueno de Obsidian es que todos los archivos son markdown y configurándolo un poco podemos hacer que soporte Markdown base sin ningún agregado, algo que Hugo puede procesar.
Build
El build de la web tiene dos procesos distintos que cambian según el ambiente, por un lado tengo un proceso de build para desarrollo local y por otro lado tengo un proceso de build para el deploy a prod.
Dev
El build para desarrollo local lo hago utilizando un archivo {{makefile}}. Dentro de este proceso, se ejecutan 3 pasos:
default: server
server:
hugo
npm_config_yes=true npx pagefind --site "public" --output-path static/pagefind
hugo server --disableFastRender --enableGitInfo
El primer paso es hacer el build de Hugo, para eso ejecutamos el comando hugo
, eso agarra todas las paginas y archivos necesarios y los convierte de Markdown a HTML, procesando toda la lógica que tengamos definida.
El segundo paso lo que hace es procesar el output del build (los archivos html) dentro de Pagefind🡭 . Pagefind es un librería que te permite hacer búsquedas en páginas estáticas sin tener que hacer requests a servicios externos ni a API’s. La búsqueda se realiza 100% en el cliente en este caso el navegador.
El tercer paso lo hace es exponer un servidor web muy básico para poder acceder a la web de forma local.
Prod
Actualmente la página esta siendo hosteada en {{Github}}, usando Github Pages y Github Actions para el CI. Esto es una de las cosas que tengo pensado cambiar en un futuro, pero por ahora funciona muy bien.
Dentro del Action que controla el deploy se realizan varios pasos
- primero se hace un checkout del código, con el parámetro
force-depth: 0
para traernos toda la historia de git que vamos a utilizar mas adelante. - instalamos {{Hugo}}, la última versión con el
extended: true
- instalamos {{python}} que lo vamos a usar para calcular metadatos
- corremos el build de {{Hugo}}
- instalamos dependencias de python,
pip install bs4
- comenzamos a calcular metadatos:
- primero ejecutamos el script
calculate_image_size.py
que lo que hace es recorrer los html ya generados por Hugo, calcular el tamaño de las imágenes que tiene (si es que tiene) y actualizar el HTML con el resultado. La actualización la hace buscando en el HTML<span>
con un id especial y dentro le agrega el texto. - segundo ejecutamos el script de
calculate_size.py
que lo que hace es calcular el tamaño de las páginas ya generadas, con imágenes y todo. De la misma forma que el script anterior, va a actualizar el archivo HTML con el resultado.
- primero ejecutamos el script
- como ultimo paso antes del deploy, ejecutamos el comando de {{pagefind}} que va a generar el cache para las búsquedas estáticas.
- una vez que tenemos toda la página procesada y empaquetada, se ejecuta el deploy a Github Pages.
- por último, envío un mensaje a un grupo privado de {{Telegram}} informando que se realizó un nuevo deploy.
Los scripts para calcular el tamaño de la página y el tamaño de las imágenes, fueron copiados de LowTechMagazine🡭 y modificados a mi gusto para sacarle un poco de código que no era necesario.
Hugo .GitInfo
Dentro del proceso y los datos a los que estoy accediendo desde Hugo, estoy configurándolo con el parámetro enableGitInfo = true
de esta forma puedo acceder al hash del commit y a la fecha del commit del último build para mostrarlo en el index.
Dentro del layout se puede acceder a esa información de la siguiente manera.
{{ .GitInfo.AbbreviatedHash }} | {{ .GitInfo.AuthorDate.Format $dateFormat }}
Digital Garden
Dentro de la web existe un {{Digital Garden}}, que vendría a ser como el cerebro de la página. Este vive en un repositorio separado al de la web. Es importado como un sub-modulo de git.
Esto tiene pros y contras, por un lado todos los datos de GitInfo a los que tiene acceso Hugo cuando tenemos un sub-modulo, no los podemos usar, por como funciona git y por como Hugo accede a esos datos.
Por otro lado, la actualización del garden en la web es manual. Cuando decido publicar una nueva versión tengo que hacer un commit con el sub-modulo actualizado y hacer push a main
para que se actualice la web.
Que esten separados me permite escribir y mantener mi jardín actualizado como estoy haciendo ahora, sin tener que andar deployando la web. Muchas veces las cosas que estan en el jardín son privadas y no son procesadas por Hugo ni publicadas en la web.
Todo el jardín esta escrito y relacionado usando {{Obsidian}} y archivos {{Markdown}}. Los archivos md, en su cabecera tiene un listado de propiedades que son 100% compatibles con el front-matter🡭 de Hugo. Por eso este puede procesar todos los archivos como si fueran markdown escritos dentro de Hugo.
Este es un ejemplo del front-matter / properties de esta página:
---
date: 2023-12-14
title: Como funciona esta web? - Colophon
categories:
- matiargs.com
tags:
- matiargs.com
- hugo
- how-to
---
Para manejar que contenido es público y cual no, utilizo dos configuraciones en los markdown y en Hugo. Por un lado puedo marcar un archivo markdown como draft: true
, de esta forma Hugo no le va a dar bola al archivo y no lo va a publicar. Por otro lado y para archivos que tienen una estructura mas privada o personal, directamente tengo configurado en Hugo ignoreFiles= []
con un listado de directorios que no van a ser procesados.
Backlinks
Los backlinks son una parte bastante fundamental del {{Digital Garden}}. Me permiten relacionar conceptos, notas y distintos archivos a través de links en texto. Los backlinks se escriben entre dos corchetes “[[]]” y en el medio va el concepto, palabra o grupo de palabras por la que quiero definir una relación entre lo que estoy escribiendo y otro concepto.
Para los backlinks tengo un proceso definido en Hugo, que los procesa cuando procesa el contenido de una página. En caso de encontrar un backlink, lo que hace es reemplazar el texto con el link a correspondiente a la página. En ese caso los links se ven de la siguiente forma {{Hugo}}. También existen backlinks que no llevan a ningún lugar, por que la página todavía no fue creada, en ese caso los links se ven así {{Digital Garden}}.
![current backlink graph](https://matiargs.com/garden/media/backlinks-graph-2024.png)
current backlink graph (113.2 KB)
Dentro de {{Obsidian}} los backlinks se pueden ver relacionados en formato de gráfico. El gráfico de arriba representa la totalidad de páginas que tiene mi jardín, tanto las públicas como las privadas
Además de los backlinks también existen links externos que son procesados de forma especial y diferente a los otros, por ejemplo OPNsense🡭 .
Tags y Categorías
Si bien la mayoría del contenido se agrupa en categorías que vendría a ser lo mas importante. También existen tags
que me ayudan a relacionar contenido. Por el momento los tags no tienen ninguna función en la web publicada, simplemente son metadatos que sirven del lado de {{Obsidian}}, con la salvedad de 4 tags que si generan un cambio.
Featured
El contenido que esta taggeado con featured
generan que en el listado del garden aparezca una asterisco que pretende informar que ese contenido es “diferente/importante” a los demás.
Blog
El contenido que tiene tiene el tag blog
ademas de aparecer en el listado del garden, también aparece ordenado por fecha y año en la página /blog🡭
.
Wip
Este contenido aparece con un texto al inicio, que pretende informar que es un contenido “work in progress”, que no esta finalizado. Que puede tener cambios a futuro. La idea de este tipo de contenido es poder ir dejando asentado el progreso que tuve con respecto a algo, muchas veces los contenidos WIP son parte de builds donde estoy probando distintas configuraciones, hardware y otras cosas. Es posible que un contenido WIP nunca salga de ese estado, en ese caso es un proyecto que arranque y no termine.
Evergreen
Y por último existe un tag evergreen
que indica que el contenido esta en constante cambio / evolución. Muchas veces este tipo de contenido lo escribo con la idea de contar la evolución de un proceso o historia.
Diseño
El diseño es un template propio, que arme a mi gusto. Por el momento tiene varias cosas pendientes, muchas en lo que respecta a la vista mobile, pero es algo en lo que de a poco voy trabajando y mejorando.
El repositorio del template esta acá: Potus - Hugo theme🡭
Dominio
El dominio es manejado por Cloudflare🡭 . Que ademas actúa como DNS y CDN.
Fonts
Antes utilizaba JetBrains Mono🡭 pero eran casi 40mb de mas que cargaban solo la fuente. Cambié a usar fonts que ya vienen en el navegador. Las que definí son Menlo y monospace.
Analytics
Este sitio no cuenta con ningún tipo de analíticas invasivas por fuera de las de Cloudflare. Las analíticas de Cloudflare se realizan a través del proxy y son 100% privacy first, no registran ningún tipo de dato de los usuarios, solo registra la cantidad de visitas que tuvo la página.
Small-Web
La mayoría de las cosas que hago y tengo pensado hacer en esta web van de la mano con el concepto de {{small-web}}. La idea de que una página web, sea sencilla de usar, no tenga tracking, ni ads, que sea pública y permita a la gente aprender sobre algo o alguien, que no tenga un fin comercial son puntos fundamentales que elijo seguir. La Small Web se trata de eso y de mucho mas, pero también se trata de lo que nosotros queramos que se trate, lo importante es hacer una web que a nosotros mismos nos guste, sin buscar la aprobación de nadie externo.
Cambios a futuro
- Una de las cosas que me gustaría cambiar, es dejar de depender de servicios de terceros / externos para hacer el build / deploy y para el hosting. Junto con eso me gustaría también dejar de depender tanto de {{Cloudflare}}, que si bien dan un servicio excepcional, no esta bueno que este tan centralizado.
- Migrar de {{Github}} a {{forgejo}} en un instancia local y privada (la instancia ya la tengo funcionando, pero estoy en etapa de pruebas todavía)
- Implementar Woodpecker CI🡭 para manejar el CI / CD.
- Hacer deploy a un {{VPS}} personal.