Documentación Libellus
URLs del sitio (Netlify / dominio)
- Producción (canónica):
https://marconoris.com - Netlify (deploys):
https://marconoris.netlify.app - Aliases:
https://libellus.marconoris.comhttps://marconoris.art
Enlaces de la bóveda de Obsidian
- Los enlaces relativos que salen de este repo (p. ej.
../../../Lecturas/...) se reescriben automáticamente durante el build. - Configura el host de publicación con
obsidian_publish_baseurlen_config.yml(actualmentehttps://lab.marconoris.com). - Cualquier enlace Markdown o atributo HTML
href/srcque empiece por../se reescribe hacia ese host, para que los assets exportados de la bóveda sigan funcionando en la web. - Documentación técnica de los plugins:
OBSIDIAN-PLUGINS.md.
Cómo mantener el sitio
Checklist rápido para que todo funcione bien:
- Front matter mínimo:
layoutcorrecto (post/page/project…),title,date,lang(es/ca/en/it…). Sintitleno aparece en listados; sinlangel pager asumees. - Slugs/URLs: no necesitas tocarlos; el hook genera
sluglatinizados y permalinks por colección. Usaslug/permalinksolo si quieres forzar algo distinto. - H1 y contenido: si el documento incluye un
#(H1) en el cuerpo, los layouts inyectan elmeta-infojusto después de ese H1 (sin tocar el Markdown). Si no hay H1 en el cuerpo, el layout pinta un H1 de fallback contitle/heading. - Índice (TOC): añade
show_toc: trueen el front matter depostopagepara mostrar un índice lateral (H1/H2/H3) en pantallas anchas. - Paginación/pagers: el include
pagination.htmlmuestra anterior/siguiente dentro de la mismacollectionylang. Si no ves pager, compruebalang. - Orden en colecciones:
- Projects: se ordenan por fecha (descendente). Si quieres posicionar manualmente, usa
ordery/o ajustadate. - Resto de colecciones: si tienen
order, se ordenan pororder(ascendente) y, a igualdad, por fecha descendente. Si no hayorder, solo por fecha.
- Projects: se ordenan por fecha (descendente). Si quieres posicionar manualmente, usa
- Callouts: usa sintaxis
> [!tipo] Título(tip, success, warning, danger, quote, cite, question, note, links, abstract, summary, texts…). Mira/callouts-demo/para ejemplos. - Autolink de URLs: cualquier http/https suelto se enlaza automáticamente en el post-render. Si necesitas desactivar en una página/post, pon
autolink_urls: falseen el front matter. - Build limpio: si cambias permalinks/slugs, borra
_sitey.jekyll-cachey ejecutabundle exec jekyll build(sin incremental) para ver los cambios.
Bio site (“link in bio”)
- Documentación técnica:
BIO-SITE.md.
Are.na
- Documentación técnica:
ARENA-README.md. - El build sincroniza automáticamente las páginas con
arena_channelsiARENA_TOKENestá definido.
Embeds de vídeo (YouTube/Vimeo/Bunny) y allowlist
El plugin _plugins/video_markdown_embed.rb convierte URLs de YouTube, Vimeo y Bunny Stream en iframes responsivos cuando:
- Pegas una URL “sola” en una línea (ej.
https://vimeo.com/974390692). - Usas sintaxis de imagen Markdown apuntando a la URL del vídeo: `<div class="video-embed video-embed--vimeo">
</div> (el texto se usa como title` del iframe).
- Para Bunny Stream, la forma canónica es
https://player.mediadelivery.net/play/<library>/<video-guid>.
Cómo funciona la allowlist
Para evitar pasar parámetros arbitrarios al embed, el plugin:
- Lee el querystring de la URL original (lo que va tras
?). - Conserva solo las claves permitidas por plataforma (
ALLOWED_QUERY_PARAMS), normalizando el nombre a minúsculas. - Descarta cualquier otro parámetro.
Allowlist actual:
- YouTube:
autoplay,controls,loop,mute,playsinline,start,end - Vimeo:
autoplay,loop,muted,autopause,playsinline,background,dnt,title,byline,portrait,badge - Bunny Stream:
autoplay,captions,preload,t,chromecast,disableAirplay,disableIosPlayer,showHeatmap,muted,loop,playsinline,showSpeed,rememberPosition,responsive
Además, para Vimeo el plugin añade por defecto title=0&byline=0&portrait=0&badge=0 (puedes sobrescribirlos si los pasas en la URL y están en la allowlist).
Otros iframes responsivos (mapas, álbumes, etc.)
Si necesitas embeds que no sean 16:9 (Lightroom, Mapbox, Sketchfab…), envuélvelos en .embed-frame y marca el ratio con --embed-ratio (fallback 4/3):
<div class="embed-frame" style="--embed-ratio: 4 / 3">
<iframe src="https://…"></iframe>
</div>
El wrapper elimina el margen del iframe, hereda el radio de borde y mantiene la relación de aspecto que definas.
Para colocar varios iframes uno al lado del otro, usa .embed-grid como contenedor:
<div class="embed-grid">
<div class="embed-frame" style="--embed-ratio: 4 / 3">
<iframe src="https://…"></iframe>
</div>
<div class="embed-frame" style="--embed-ratio: 4 / 3">
<iframe src="https://…"></iframe>
</div>
</div>
Portadas con video de fondo
El layout cover (ver portada.md) admite video de fondo desde Vimeo, YouTube o Bunny Stream. Usa cover_video o video_cover (también vale cover_vimeo para compatibilidad) con la URL completa:
layout: cover
title: ...
cover_video: https://vimeo.com/123456789
# o https://youtu.be/abc123
# o https://player.mediadelivery.net/play/617291/d545466f-50c1-4c37-9919-8f2818c78aed
# Opcional: cover (imagen) como fallback estático
El layout ajusta parámetros para autoplay/loop/mute y oculta los controles. No hace falta width/height; el iframe se adapta a la sección hero.
Si quieres random por visita, cover_video también acepta lista (en singular):
cover_video:
- https://vimeo.com/123456789
- https://youtu.be/abc123
cover_videos también funciona por compatibilidad, pero cover_video es la forma recomendada.
Imágenes sociales para páginas con cover o image
cover sigue siendo la propiedad editorial principal. Si un documento usa image, también entra en la misma lógica social. No hace falta añadir otra propiedad para compartir.
Cuando cover o image apunta a una imagen local (.webp, .jpg, .jpeg, .png), la social card busca automáticamente una derivada JPG en el mismo directorio con este patrón:
basename.ext -> basename.social.jpg
Ejemplos:
images/tizas.webp->images/tizas.social.jpgimages/news/assut-riudecanyes.jpg->images/news/assut-riudecanyes.social.jpgimages/news/ElDorado-hor.webp->images/news/ElDorado-hor.social.jpg
Si la derivada existe, se usa para og:image y twitter:image. Si no existe, la plantilla cae a la imagen social global por defecto. Las URLs remotas compatibles (.jpg/.jpeg/.png) se usan tal cual, sin derivada local.
Para generar o regenerar estas derivadas:
python3 script/generate_social_images.py --dry-run
python3 script/generate_social_images.py
El script:
- recorre el contenido y detecta
covereimagelocales referenciados - genera
*.social.jpga1200x630 - no reescribe front matter
- no sobrescribe el archivo original
Usa --force si quieres regenerar todo aunque la derivada ya exista.
Random de cover (video)
Cuando cover_video es una lista, el layout cover puede elegir el video:
visit(por visita/carga de página, default)session(una vez por sesión de navegador)day(una vez por día, según la hora local del usuario)
Configúralo en el frontmatter con cover_video_random: visit|session|day.
Frontmatter para Jekyll
Lo mínimo que necesita cada tipo de documento para que todo funcione sin sorpresas:
- layout: el adecuado para la colección (post, page, project, etc.).
- title: obligatorio (sin título no sale en listados ni en Home/collections).
- date: para ordenar (posts y colecciones); si falta, caen a orden 0 o usan updated.
- lang: consistente (es/ca/en/it…). El pager filtra por lang y si falta asume es.
Opcional según necesidad:
- slug/permalink: los genera el hook a partir de title, así que solo hace falta si quieres forzar algo distinto.
- year: en projects para ordenar por año antes que por fecha.
- order: en projects para ordenar dentro del mismo año.
- publish: false para ocultar.
- hide_h1: true si quieres ocultar el H1 de fallback del layout (cuando el documento no trae H1 en el cuerpo).
- libellus_featured: true para fijar publicaciones en la home de Libellus de Libellus.
- featured: true para incluir el documento en los bloques de destacados del
indexmultilengua y delbiosite. - featured_order: orden manual ascendente dentro de esos bloques. Si falta, se usa
updatedy luegodatecomo fallback. - year_range_sort: en índices con
layout: seriescontrola cómo ordenar rangos enyear(startpor defecto;endusa el último año del rango). -
external_links: lista de enlaces externos (por ejemplo VSCO/Are.na) que se renderizan al final de los layouts
project/project-two-column.external_links: - label: VSCO url: https://vsco.co/... - label: Are.na url: https://www.are.na/...
Clases y estilos rápidos en Markdown (kramdown/Liquid)
- Atributos kramdown al final de un párrafo o imagen:
Texto aquí {: .project-text }o!Alt{: .img-blend }. - Anchos puntuales sin tocar CSS:
!Alt{: style="width: 260px;" }o envolviendo:<div style="width:260px">!Alt</div>. - Múltiples clases o estilos:
{: .project-text .resalte style="max-width: 18rem;" }. - Recuerda que la sintaxis va pegada al elemento anterior (sin línea en blanco) y se procesa antes que el Markdown/HTML del layout.
Portada / home
- Home principal (index
es/ca/en/it): el bloque “Destacado” (vía_includes/home-index-featured.html) mezclasite.pagesy todas las colecciones, filtrando porlangy excluyendopublished: false/publish: false. - Propiedades de selección (home principal):
featured: true= incluye el documento en destacados.featured_order= orden manual ascendente.- deduplicación por
translation_key(ourlsi falta). - si no hay
featured_order, fallback temporal porupdateddesc y, si no hayupdated,datedesc.
- Bloque “Studio shop” (home principal):
- Se renderiza vía
_includes/home-shop.htmlcon datos en/_data/shop_featured.yml. - Por defecto muestra 4 items (2x2 en mobile, 4 columnas en desktop).
- Apagar en una home concreta:
home_shop: falseen el front matter delindex.mdcorrespondiente. - Idiomas: cada item puede llevar
lang: es|ca|en|it; si falta, aparece en todos los idiomas. - Labels i18n:
home_shop_title(título del bloque) yhome_shop_all(CTA “ver tienda”).
- Se renderiza vía
- Home de Libellus:
libellus_featured: truese mantiene para su bloque destacado específico. -
Colapsar colecciones: hay un bloque
collections_statecomentado en_config.yml; por defecto todas quedan cerradas. Lista enopenlas que quieras abrir de inicio:collections_state: open: - posts - versiculipuedes listar las colecciones a ocultar sin borrarlas. Úsalo si decides implementar lógica de cierre en los listados/pagers.
Shop featured data (/_data/shop_featured.yml)
Estructura recomendada (4 items por idioma, títulos localizados; URLs e imágenes pueden reutilizarse):
items:
- title: "Obra original"
url: "https://shop.marconoris.com/category/obra-original"
image: "https://assets.bigcartel.com/product_images/.../foo.jpg"
lang: es
- title: "Original artwork"
url: "https://shop.marconoris.com/category/obra-original"
image: "https://assets.bigcartel.com/product_images/.../foo.jpg"
lang: en
Campos:
title(texto visible)url(destino enshop.marconoris.com)image(URL remota o ruta local/images/...)price(opcional, string)lang(opcional; si falta, aparece en todos los idiomas)
Bio site (layout: biosite)
- El layout está en
_layouts/biosite.htmly se usa enpages/*/bio.md. - Al final del bio (antes del logo de cierre) renderiza el mismo bloque de shop (
_includes/home-shop.html). - Apagar en una bio concreta:
bio_shop: falseen el front matter depages/*/bio.md.
Galerías (PhotoSwipe)
Guía rápida para usar las galerías del layout project y sus opciones:
-
Galería única “suelta” (lo básico): si solo necesitas una galería, puedes definirla directamente en el documento (sin
galleries:). Conlayout: projectse renderiza automáticamente (a menos que usesgallery_render: manual).gallery_style: grid # opcional (default: grid) gallery: - src: /images/projects/mi-proyecto/01.webp caption: "Pie opcional" - src: /images/projects/mi-proyecto/02.webpo bien auto desde carpeta:
gallery_style: masonry # opcional gallery_path: /images/projects/mi-proyecto/ # importante: con barra final gallery_caption_all: "Mi caption" # opcional # gallery_captions: # opcional (mapa filename -> caption) # 01.webp: "Pie 1" # 02.webp: "Pie 2" -
Múltiples galerías (recomendado si quieres títulos/secciones): define
galleries:como lista de bloques. Cada bloque aceptaid,gallery_style(grid,masonry,collage,carousel), ygallery(lista de imágenes consrc; opcionales:thumb,caption,width,heightpara el zoom del lightbox):galleries: - id: uno gallery_style: masonry gallery: - src: ../images/foo/bar.webp thumb: ../images/foo/bar-thumb.webp caption: "Título o pie" width: 1800 height: 1200 - Auto desde carpeta: en lugar de listar imágenes, usa
gallery_path: /images/projects/mi-proyecto/(incluye la barra final) para cargar todos los ficheros de esa carpeta (ordenados por nombre). Puedes añadirgallery_captions:para sobrescribir captions por archivo. Si quieres el mismo caption para todas las auto, usagallery_caption_all: "Mi caption".- Las derivadas técnicas de social card
*.social.jpgse ignoran automáticamente y no entran en la galería, aunque estén en el mismo directorio que las imágenes originales.
- Las derivadas técnicas de social card
- Render: por defecto (
gallery_render: auto) el layout recorregalleries(ogallery/gallery_pathsueltas) y pinta la galería antes del contenido. - Incrustar la galería en el Markdown (manual):
1) En el front matter añadegallery_render: manualy define la galería congalleries:(ogallery:/gallery_path:si solo hay una):gallery_render: manual galleries: - id: swab gallery_style: masonry gallery: - src: ../images/news/swab.webp caption: "Obra en SWAB"2) En el cuerpo del
.mdcoloca el include donde quieras que aparezca:{% include project-gallery.html id="swab" %}Si solo tienes una galería suelta (
gallery:en front matter), no hace faltaid.
3) Títulos y descripciones de la galería: añadetitle:y/odescription:dentro del bloque de la galería (no en el front matter principal); se muestran encima del grid/carrusel sishow_metaestá activo (por defecto lo está). - Lightbox:
- Lightbox:
- Por bloque (default): cada bloque lleva su propio
data-pswp-gallery, el lightbox solo recorre esa galería. -
Global por página: envuelve varias galerías en un contenedor con
data-pswp-gallery="algo"y pasaskip_pswp_container=trueen cada include, para que compartan el mismo lightbox:<div data-pswp-gallery="project-foo"> {% include project-gallery.html id="uno" skip_pswp_container=true %} {% include project-gallery.html id="dos" skip_pswp_container=true %} </div> - Desactivar lightbox: pon
lightbox: falseen el bloque o en el include: `
- Por bloque (default): cada bloque lleva su propio
`.
-
Columnas por breakpoint (grid y masonry): usa
gallery_columns(móvil/base),gallery_columns_md(≥640px) ygallery_columns_lg(≥1024px). Ejemplo:gallery_columns: 1 gallery_columns_md: 2 gallery_columns_lg: 4Si no defines nada, se usan los valores por defecto del CSS (
grid:auto-fit;masonry: 1/2/3 columnas en móvil/≥640/≥1024). -
Notas de estilo: en
masonrylas imágenes no se recortan; si solo hay 1–2 imágenes se ajustan las columnas para ocupar el ancho (a menos que fijes columnas).collageusa filas fijas con spans;carouselcentra y permite scroll horizontal con controles. Puedes mezclargallerymanual congallery_path: las manuales se renderizan primero y luego las auto.
Bloques de logos (sponsors/partners)
Para un bloque de sponsors con logos centrados usa las clases project-sponsors:
<div class="project-sponsors">
<p class="project-sponsors__eyebrow">
Proyecto producido con el apoyo de <strong>BCN Producció 17</strong>. En colaboración con:
</p>
<div class="project-sponsors__grid">
<a class="project-sponsors__logo" href="https://lacapella.barcelona" target="_blank" rel="noopener">
<img src="https://lab.marconoris.com/images/logos/lacapella.png" alt="La Capella">
</a>
<div class="project-sponsors__logo">
<img src="/images/logos/mume.png" alt="MUME. Museu Memorial de l'Exili">
</div>
<div class="project-sponsors__logo">
<img src="https://lab.marconoris.com/images/logos/598.png" alt="Mojones de los Pirineos">
</div>
</div>
</div>
Usa rutas relativas a tus imágenes y ajusta los alt de cada logo. Todos los logos son HTML puro para evitar problemas de parsers Markdown mezclados.
Intervención selectiva logo por logo:
- Para el logo principal destacado existe
project-sponsors__logo--hero. - Para ajustes finos del resto, evita categorías genéricas (
small,wide,large) y modifica solo el logo concreto con variables CSS en eldiv.project-sponsors__logo.
Variables disponibles:
--sponsor-basis: ancho base que reserva la caja del logo dentro del flex.--sponsor-min-height: altura mínima de la caja.--sponsor-img-max-height: altura máxima visible de la imagen.
Ejemplo de ajuste puntual:
<div class="project-sponsors__logo" style="--sponsor-basis: 300px; --sponsor-img-max-height: 130px;">
<img src="/images/logos/Logoriusiurana.png" alt="Plataforma pel Riu Siurana">
</div>
Ejemplo de logo principal:
<div class="project-sponsors__logo project-sponsors__logo--hero">
<img src="/images/logos/logo-terradart.png" alt="Terra d'Art">
</div>
Regla práctica:
- Si un logo horizontal se ve pequeño, sube primero
--sponsor-img-max-heighty solo después--sponsor-basissi sigue faltándole presencia. - Si un logo necesita más aire vertical, sube
--sponsor-min-height. - Si el problema es solo un caso concreto, toca solo ese logo en el HTML del proyecto.
Referenciar un proyecto desde páginas/posts
- Añade en el front matter
project_ref: <translation_key-del-proyecto>(ej.project_ref: lugares-remotos). - En los metadatos se mostrará
AÑO · Proyecto <link>(etiqueta traducida segúnlang). Busca el proyecto ensite.proyectosportranslation_keyy prioriza el mismolang; si no existe, usa el primero disponible. - Si quieres relacionar un contenido con una serie, usa
series_ref: <translation_key-de-la-serie>(acepta string o lista).project_refqueda reservado para proyectos.
Márgenes de texto en proyectos (override desde Markdown)
En páginas con layout project, el CSS aplica en desktop (≥768px) un margen lateral a los bloques de texto dentro de .project-content:
- Se aplica por defecto a
p,ulyolcomo hijos directos de.project-content. - Los párrafos que contienen contenido “media/interactive” (por ejemplo
img,iframe) se excluyen por defecto para evitar layouts raros (lospque envuelvenbuttonno se excluyen).
Si necesitas control fino desde Markdown (kramdown), puedes añadir clases a un bloque:
- Forzar el estilo “texto con márgenes” (aunque sea un bloque especial):
{:.project-text}(también usable enseries/page) - Quitar márgenes (ancho completo):
{:.project-text--full}
Ejemplos:
Este párrafo irá con margen lateral en desktop.
{:.project-text}
- Esta lista irá a ancho completo
- (sin margen lateral)
{: .project-text--full}