simpleblog

Generador estatico minimalista de blog
git clone https://git.fedi.ovh/simpleblog
Log | Files | Refs

objetivo.txt (8920B)


      1 simpleblog — generador estatico minimalista de blog
      2 ====================================================
      3 
      4 OBJETIVO
      5 --------
      6 - Blog simple y minimalista. Minimo espacio, memoria y dependencias.
      7 - Estructura limpia, etiquetas semanticas (head, header, main, article, footer).
      8 - Versatil y facilmente configurable.
      9 - Listado de entradas en la pagina principal con fecha + titulo + descripcion.
     10 - Cabecera personalizable, css simple, logo, favicon, titulo, descripcion.
     11 - Entradas en markdown (con posibilidad de html plano dentro).
     12 - Inspirado en saait (codemadness.org/saait.html) pero comiendo .md.
     13 
     14 
     15 DECISIONES (2026-05-18)
     16 -----------------------
     17 - Lenguaje: shell script POSIX (sh + awk + sed).
     18   Razon: minimo absoluto, sin compilar, facil de iterar. Si se queda corto,
     19   migramos a C reusando saait.
     20 - Conversor markdown: smu (suckless), instalado como paquete aparte
     21   (apk add smu). El comando se configura en `config` (variable
     22   `markdown_cmd`); rutas que empiezan por `./` se resuelven respecto al
     23   directorio del sitio.
     24   Nota: smu solo entiende markdown clasico de Gruber, NO triple backtick.
     25   Bloques de codigo = 4 espacios de indentacion.
     26 - Metadatos: frontmatter dentro del propio .md, formato `key: value`, separado
     27   del cuerpo por una linea en blanco. Un fichero por entrada, sin .cfg aparte.
     28 - Plantillas: ficheros HTML con `{{var}}` sustituido por sed/awk. Sin parser
     29   propio.
     30 - Estilo: estructura semantica + css minimal.
     31 
     32 
     33 ESTRUCTURA (tras refactor 2026-05-18, repo empaquetable, sin make)
     34 ------------------------------------------------------------------
     35 repo/
     36   simpleblog          script principal (sh) -> /usr/bin/simpleblog
     37   dev                 wrapper sh para devs (./dev build|serve|...)
     38   templates/          plantillas DEFAULT -> /usr/share/simpleblog/templates/
     39     header.html, footer.html, post.html, page.html,
     40     index.html, index-item.html, tags.html,
     41     atom-{header,item,footer}.xml
     42   skel/               esqueleto para `simpleblog init`
     43                       -> /usr/share/simpleblog/skel/
     44   example/            sitio funcional de demo (posts, pages, config...)
     45   alpine/APKBUILD     receta para empaquetar a .apk (sin make)
     46   objetivo.txt        este fichero
     47 
     48 sitio del usuario (creado con `simpleblog init`):
     49   config              config global (key: value)
     50   posts/              entradas .md|.html con frontmatter
     51   pages/              paginas estaticas
     52   images/             imagenes originales
     53   static/             se copia tal cual a public/ (css, favicon, etc)
     54   templates/          (opcional) overrides de las plantillas default
     55   public/             salida generada (gitignored)
     56 
     57 
     58 USO
     59 ---
     60 # desarrollo local del repo (sin instalar, sin make)
     61 ./dev build     construye example/public/ con templates/ del repo
     62 ./dev serve     sirve example/public/ (darkhttpd / busybox / python)
     63 ./dev stats     resumen de tamanos
     64 ./dev clean     borra example/public/
     65 
     66 # tarball para empaquetar (lo consume el APKBUILD en alpine/)
     67 git archive --format=tar.gz --prefix=simpleblog-0.1/ HEAD \
     68   -o simpleblog-0.1.tar.gz
     69 
     70 # como usuario final (despues de `apk add simpleblog`)
     71 simpleblog init     inicializa un sitio nuevo en el cwd (copia skel)
     72 simpleblog build    genera public/
     73 simpleblog serve    sirve public/ en :8080
     74 simpleblog stats    resumen de tamanos
     75 simpleblog clean    borra public/
     76 
     77 DEPENDENCIAS DEL PAQUETE
     78 ------------------------
     79 - smu (obligatoria) — conversor markdown
     80 - darkhttpd o busybox-extras (opcional) — solo para `simpleblog serve`
     81 - imagemagick (opcional) — solo para procesar imagenes
     82 
     83 Nada de make/build-base/git para el usuario final. `apk add simpleblog`
     84 y a usar.
     85 
     86 
     87 HECHO (2026-05-18)
     88 ------------------
     89 [x] Estructura de carpetas
     90 [x] Script `simpleblog` (build + clean)
     91 [x] Parseo de frontmatter en .md
     92 [x] Conversion md -> html via comando externo configurable
     93 [x] Plantillas header / footer / post / index / index-item con sustitucion {{var}}
     94 [x] Index ordenado por fecha descendente con titulo + fecha + descripcion
     95 [x] Copia de static/ tal cual al output
     96 [x] CSS minimal de partida
     97 [x] Post de ejemplo (posts/2026-05-18-hola-mundo.md) renderiza correctamente
     98 [x] Integrar smu vendored (vendor/smu/) y compilar via Makefile
     99 [x] Bloques de codigo renderizan como <pre><code> con escapado correcto
    100 [x] Makefile con build / clean / serve / install / distclean
    101 [x] Feed atom (atom.xml) generado, con plantillas atom-header/item/footer
    102 [x] siteurl en config para URLs absolutas del feed
    103 [x] <link rel="alternate"> al feed en el <head> de cada pagina
    104 [x] XML del feed validado con xmllint
    105 [x] Soporte para entradas .html (saltarse smu, usar cuerpo tal cual). El
    106     bucle de posts itera sobre *.md y *.html. Frontmatter funciona igual.
    107 [x] Borradores: frontmatter `draft: true` salta el post y avisa en stdout
    108 [x] Slug en frontmatter: `slug: foo` -> public/foo.html (anula el nombre
    109     del fichero, util para que la URL sea estable independiente del nombre)
    110 [x] favicon.svg y logo.svg minimos en static/, enlazados desde header.html
    111     (favicon como <link rel="icon" type="image/svg+xml">, logo dentro del
    112     .site-brand junto al titulo)
    113 [x] Paginas estaticas en `pages/` (paralelo a posts/). No aparecen en
    114     index ni feed. Frontmatter `menu: true` + `menu_order: N` las anade
    115     al menu del sitio (nav en header.html, ordenado numerico).
    116 [x] Paginacion del index: config `posts_per_page`. index.html lleva los
    117     mas recientes y page/2.html, page/3.html... el resto. Enlaces
    118     prev/next pre-renderizados a HTML por el script.
    119 [x] Tags en posts: frontmatter `tags: foo, bar`. Cada post muestra sus
    120     tags. Se genera una pagina por tag (public/tags/<tag>.html) y un
    121     indice global (public/tags.html) con cuenta de posts por tag.
    122 [x] Refactor del script: funciones `sub_var` / `sub_file` / `render_layout`
    123     eliminan duplicacion entre renders de post / page / index / tag-page.
    124 [x] Imagenes: carpeta images/ con originales, config define
    125     image_sizes (lista de anchos en px) e image_quality. El build genera
    126     public/img/<nombre>-<ancho>.<ext> por cada (imagen, ancho) y copia
    127     el original. En markdown usas `![alt](/img/foo-640.jpg)` directamente.
    128     Sin upscale (-resize "Wx>" de magick). Cache por mtime: la segunda
    129     build solo procesa imagenes nuevas/modificadas. Strip de EXIF.
    130     Fallback: si magick/convert no estan, copia images/ tal cual.
    131 [x] Formatos extra de imagen: config `image_extra_formats: webp` (o avif).
    132     Para cada (imagen, ancho) se genera tambien la variante en el formato
    133     extra. WebP comprime ~70% menos que JPEG en pruebas reales.
    134 [x] Comando `make stats`: resumen de tamanos (originales, salida total,
    135     variantes de imagen) y conteos (posts, pages, tags).
    136 [x] .gitignore + commit inicial. vendor/ excluido (smu se clona via
    137     `make`). public/ excluido (salida generada).
    138 [x] Refactor para empaquetar (2026-05-18): script trabaja sobre cwd,
    139     plantillas con override (./templates -> /usr/share/simpleblog/templates),
    140     nuevo comando `init` que copia skel al cwd. Skel minimo en skel/.
    141     Sitio de demo en example/. APKBUILD en alpine/. smu deja de ser
    142     vendored y pasa a paquete aparte (apk add smu).
    143 [x] Quitar make: no era coherente con la filosofia (en Alpine base no
    144     viene). APKBUILD usa `install -Dm` directamente. Para devs, un
    145     script `./dev` sh de 8 lineas hace de wrapper sobre example/.
    146 
    147 
    148 POR HACER (pendiente, priorizado)
    149 [ ] Ocultar <nav class="pagination"> cuando esta vacia (en tag pages y
    150     cuando hay una sola pagina) — ahora queda un nav vacio en el HTML
    151 [ ] Validacion: avisar si un slug colisiona entre posts/pages/borradores
    152 [ ] Sanitizar tags (caracteres invalidos en nombre de fichero)
    153 
    154 GOTCHAS / NOTAS
    155 ---------------
    156 - smu NO entiende triple backtick. Bloques de codigo = 4 espacios de
    157   indentacion (markdown clasico).
    158 - El feed atom mete el HTML del post dentro de CDATA. Si un post contiene
    159   literalmente `]]>` se rompera el XML; cuando aparezca lo solucionamos.
    160 - siteurl en `config` no lleva / al final; baseurl si (o empieza por /).
    161   Las URLs absolutas del feed se forman como `$siteurl$baseurl<path>`.
    162 - Colision de nombres: si tienes `foo.md` y `foo.html` en posts/, el segundo
    163   procesado sobreescribe al primero en public/. Lo mismo entre posts/ y
    164   pages/ si comparten slug. Usa nombres / slugs distintos.
    165 - Tags: los usamos tal cual para nombre de fichero (public/tags/<tag>.html).
    166   Si una tag tiene espacios, barras o caracteres raros, fallara. Usa solo
    167   [a-z0-9-_] por ahora.
    168 - En las paginas de tag y cuando solo hay una pagina de index, el
    169   <nav class="pagination"> queda vacio (con espacios). No rompe nada
    170   visualmente pero el HTML queda con un nodo vacio.
    171 - La cache de imagenes vive en public/img/. `make clean` borra public/
    172   entera, por lo que tras un clean se regeneran TODAS las imagenes.
    173   Para iterar rapido, usa `make build` directamente (sin clean) — el
    174   check de mtime salta imagenes no modificadas.