Карточки превью для статей Quartz 4

В Quartz 4 легко накопить много заметок, проектных разборов и технических статей. Но если страницы папок и тегов остаются простым списком ссылок, читателю приходится угадывать по названиям, что внутри и с чего начать.

В текущем сайте Smirnoff эту задачу решает компонент PagePreviewList: он показывает материалы карточками с картинкой, заголовком, описанием, датой, тегами и кнопкой Preview.

Так разделы с проектными материалами становятся не складом файлов, а понятной витриной. Автор может заранее подсказать контекст статьи, а читатель быстрее считывает маршрут: что это за материал, насколько он ему нужен и куда перейти дальше.

Где включены карточки

Режим включается в quartz.config.ts у emitters:

Plugin.FolderPage({
  usePreviewList: true,
})
 
Plugin.TagPage({
  usePreviewList: true,
})

После этого карточки используются для страниц папок и тегов автоматически. Это важная часть удобства: не нужно вручную вставлять PagePreviewList в каждую Markdown-страницу и помнить о дополнительной разметке. Достаточно настроить эмиттеры и аккуратно заполнить данные у самих статей.

Что берётся из frontmatter

Карточка не придумывает содержание сама. Она собирает короткое представление статьи из QuartzPluginData, поэтому качество карточек напрямую зависит от того, насколько внимательно заполнен frontmatter:

  • title — заголовок карточки;
  • description — короткий текст;
  • dates — дата через getDate;
  • tags — список тегов;
  • slug — путь страницы;
  • preview_image — картинка превью.

Минимальный frontmatter для нормальной карточки:

---
publish: true
title: "Название статьи"
description: "Короткое описание для карточки."
tags:
  - blog
draft: false
preview_image: /images/quartz-example.webp
---

Если preview_image не указан, компонент показывает placeholder с текстом No image или локализованной строкой из i18n. Такой вариант технически рабочий, но для обзорных страниц он слабее: карточка теряет визуальный якорь, по которому читатель быстрее отличает один материал от другого.

Как резолвится картинка

Важная деталь текущей реализации: preview_image берётся из frontmatter, а потом путь проходит через resolveRelative. Это не просто техническая мелочь — от этого зависит, появится ли картинка на карточке после сборки и перехода на страницу папки или тега:

<img
  src={resolveRelative(fileData.slug!, preview.previewImage as FullSlug)}
  alt={preview.title}
  class="preview-image"
/>

Поэтому для материалов проще использовать абсолютные пути от корня сайта: /images/name.webp. Такой формат уже принят в проектных статьях и меньше зависит от глубины текущей папки. Для автора это снижает риск сломать превью при переносе заметки между разделами, а для читателя означает одно: карточка открывается с ожидаемой картинкой, без пустого места.

Как выглядит карточка

Сейчас карточка рендерится примерно так. Вся кликабельная верхняя часть ведёт на статью, а служебная информация вынесена ниже, чтобы карточка оставалась читаемой и не превращалась в набор мелких ссылок:

<article class="preview-card">
  <a href={href} class="preview-link">
    <div class="preview-image-container">...</div>
    <div class="preview-content">
      <h3 class="preview-title">...</h3>
      <p class="preview-description">...</p>
    </div>
  </a>
  <div class="preview-meta">...</div>
</article>

В meta-блоке отдельно находятся элементы, которые помогают не только открыть материал, но и понять его место в системе сайта:

  • ссылка-кнопка Preview;
  • дата;
  • теги со ссылками на страницы тегов.

Стили сейчас inline

Раньше было легко написать, что для карточек нужен отдельный CSS-файл. В текущей реализации это не так: CSS лежит прямо в PagePreviewList.css внутри компонента. Это стоит знать до редизайна, чтобы не искать стили там, где их нет, и не менять глобальную тему без необходимости.

Там описаны:

  • grid-сетка repeat(auto-fill, minmax(280px, 1fr));
  • hover-подъём карточки;
  • aspect-ratio: 16 / 10 для изображения;
  • object-fit: cover;
  • обрезка описания до трёх строк;
  • адаптация под мобильные экраны.

Если нужно поменять внешний вид только этого компонента, править придётся сам PagePreviewList.tsx или аккуратно переопределять классы глобальными стилями.

Практические правила для статей

Карточки работают лучше всего, когда каждая статья заранее подготовлена как самостоятельный вход в материал. Для этого достаточно нескольких привычек:

  1. Пиши нормальный description, не длиннее одного-двух предложений: это короткое обещание читателю, что он найдёт внутри.
  2. Добавляй preview_image почти в каждую опубликованную статью, особенно если материал должен быть заметен на странице папки или тега.
  3. Используй изображения с широким соотношением сторон, потому что контейнер сейчас 16 / 10.
  4. Не рассчитывай, что компонент сам найдёт первую картинку в тексте: в коде оставлен комментарий про такую возможность, но сейчас логика берёт только frontmatter.
  5. Проверяй теги: они становятся ссылками, видны на карточке и помогают читателю перейти к связанным материалам.

Итог

PagePreviewList — небольшая, но заметная часть сайта. Она превращает папки и теги в нормальные обзорные страницы, где у каждой статьи есть лицо, короткий смысл и понятная точка входа.

Источник данных остаётся простым: frontmatter статьи. Главное — не забывать description и preview_image, потому что именно они делают карточку полезной для навигации. Хорошая карточка не заменяет статью и не рекламирует её слишком громко; она спокойно объясняет, почему материал стоит открыть.