lism.blog
Menu

blog-astro-personal の構成

Lism CSS リポジトリの templates/blog/astro/personal/ には、Lism CSS と @lism-css/ui を使った個人ブログ(エッセイ・日記)向けの Astro テンプレートが入っている。文章中心の読み心地を重視した最小構成で、カテゴリのような階層的な分類軸は持たず、年月アーカイブタグ で過去記事をたどれるようにしている。

依存関係

package.json の依存は最小限。Astro と Lism CSS / @lism-css/ui だけを使う。

{
  "dependencies": {
    "@lism-css/ui": "workspace:*",
    "astro": "^6.1.9",
    "lism-css": "workspace:*"
  }
}

astro.config.mjs では @/src にエイリアスしているだけで、それ以外のインテグレーションは入れていない。記事は .md で書く前提。

ディレクトリ構成

src/
├── components/      # Astro コンポーネント
├── config/          # サイト設定・ナビ
├── content.config.ts
├── layouts/         # ページレイアウト
├── lib/             # 純粋ロジック(OG 画像・年月アーカイブ集計)
├── pages/           # ルーティング
├── posts/           # 記事 Markdown(フラットに配置)
└── styles/
    └── global.css

Content Collections

src/content.config.ts で記事用コレクションを定義している。タグやカテゴリは持たず、title / excerpt / date のみを必須とする。

import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';

const posts = defineCollection({
  loader: glob({ base: './src/posts', pattern: '**/*.md' }),
  schema: z.object({
    title: z.string(),
    excerpt: z.string(),
    date: z.string(),
  }),
});

export const collections = { posts };

記事ファイルは src/posts/ 直下にフラットに置く。記事 ID はファイル名(拡張子なし)で、それがそのまま URL の slug として使われる。

ルーティング

src/pages/ 配下のファイル構成は次の通り。

パス内容
[...page].astroトップ(全記事一覧)+ページネーション
posts/[slug].astro記事詳細
archive/index.astro年月アーカイブの目次(年月ごとの件数を一覧)
archive/[year]/[month]/[...page].astro年月別の記事一覧+ページネーション
404.astro404

ページネーションには Astro の paginate() を使い、1ページあたりの件数は siteConfig.pagination.postsPerPage(デフォルト 6)を参照する。記事詳細では getStaticPaths 内で記事を日付降順にソートし、prev / next を index で受け渡している。

年月アーカイブ

src/lib/archive.ts に年月集計のヘルパーを置いている。getArchiveSummaries() は記事一覧から { year, month, count } の配列を新しい順で返し、getPostsByArchive(year, month) で対象月の記事だけを抽出する。

import { getArchiveSummaries, getPostsByArchive } from '@/lib/archive';

const posts = await getCollection('posts');
const summaries = getArchiveSummaries(posts); // [{ year, month, count }, ...]

archive/index.astro ではこの集計結果をそのままリスト表示し、各行から /archive/{year}/{month}/ にリンクしている。

OGP

Layout.astro に Open Graph / Twitter Card のメタタグを組み込んでいる。OG 画像は loos.tools/ogimg-maker の API を src/lib/ogImage.ts から呼び出して生成する。デフォルトのスタイルは siteConfig.ogImage で調整可能。

const ogImage = buildOgImageUrl({
  title: post.data.title,
  foot: siteConfig.name,
});

サイト設定

src/config/site.ts にサイト名・キャッチコピー・ページネーション件数・ナビ・OG 画像のデフォルト等をまとめている。テンプレートをカスタマイズする際の入口はここ。

export const siteConfig = {
  name: 'lism.blog',
  tagline: '読む、書く、考える、日々の記録',
  description: '読書、暮らし、考えごと。ゆっくり書き留めるパーソナルブログ。',
  lang: 'ja',
  pagination: { postsPerPage: 6 },
  nav: [
    { label: 'Home', href: '/' },
    { label: 'Archive', href: '/archive/' },
    { label: 'About', href: '/about/' },
  ],
  ogImage: { type: '1-5', frame: '1', bg: 'fill' },
  // ...
} as const;

レイアウト

レイアウトは 2 つ。

  • Layout.astro<html> から <body> までの土台。OGP メタタグ・Web フォント(Noto Serif JP)の読み込み・<Container> の中に <Stack min-h="100svh"> で Header / Main / Footer を縦積みする。
  • ArchiveLayout.astroLayout を基盤に、本文を <Group isWrapper isContainer hasGutter> で囲んだ一覧用レイアウト。

記事詳細ページでは本文の後に ShareButtonsArticleNav を置き、X投稿・URLコピー・前後記事への移動を提供している。

スタイル

src/styles/global.css で Lism CSS の CSS 変数を上書きし、紙面のような淡いクリーム色と明朝体(Noto Serif JP)を基調にしたトーンを作っている。

@layer lism-base {
  :root {
    --base: hsl(45, 32%, 98%);
    --text: hsl(45, 8%, 10%);
    --brand: hsl(10, 56%, 50%);
    --ff--base: 'Noto Serif JP', 'Hiragino Mincho ProN', 'Yu Mincho', serif;
    --lts--base: 0.025em;
    --headings-fw: 500;
  }
}

記事本文のタイポグラフィ(h2 の下線、blockquote の左ボーダーなど)は .c--articleBody 配下の子孫セレクタとして @layer lism-custom に書いている。Markdown から生成される要素にはクラスを直接付けられないため、こうした装飾は CSS 側で記述する。