Hello World
Hello World
ShingoLab ブログの最初の記事です。このサイトがどうやって作られているのかを紹介します。
なぜ個人サイトを作ったのか
SNS だけでは自分のアウトプットを整理するのが難しくなってきました。技術記事、プロジェクトの記録、考えたことを一箇所にまとめておける場所が欲しかったのが動機です。
いくつかのプラットフォームを検討しましたが、最終的に自分でゼロから構築する道を選びました。理由はシンプルで、自分の技術力を示すこと自体がポートフォリオの一部になるからです。
技術スタック
このサイトは以下の技術で構築されています。
Astro
フレームワークには Astro を採用しました。静的サイト生成(SSG)をデフォルトとしつつ、必要な箇所だけ React などのインタラクティブなコンポーネントを「アイランド」として埋め込めるのが特徴です。
import { defineConfig } from "astro/config";
import tailwindcss from "@tailwindcss/vite";
import mdx from "@astrojs/mdx";
import react from "@astrojs/react";
export default defineConfig({
site: "https://shingolab.com",
vite: { plugins: [tailwindcss()] },
integrations: [mdx(), react()],
});
ブログ記事は MDX で書いているので、Markdown の中に React コンポーネントを差し込むこともできます。
Tailwind CSS v4
スタイリングには Tailwind CSS v4 を使用しています。v4 からは CSS-first の設定方式になり、tailwind.config.js ではなく CSS ファイル内でテーマを定義します。
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--color-accent: #6929FF;
--color-bg: #FAFAFA;
--color-text: #1A1A1A;
}
ダークモードは class ベースで制御しています。@custom-variant を使うことで、.dark クラスの有無でスタイルを切り替えられます。
ダークモード対応
ダークモードの実装で最も気をつけたのは FOUC(Flash of Unstyled Content)の防止 です。ページ読み込み時に一瞬ライトモードが見えてしまう問題を、<head> 内のインラインスクリプトで解決しています。
<script is:inline>
function applyTheme() {
const theme = localStorage.getItem("theme") ??
(window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark" : "light");
document.documentElement.classList.toggle("dark", theme === "dark");
}
applyTheme();
</script>
このスクリプトは is:inline 指定により、Astro のバンドル処理を通さず <head> 内にそのまま展開されます。ブラウザが最初のレンダリングを行う前に実行されるため、チラつきが発生しません。
View Transitions
Astro の View Transitions API を使って、ページ遷移をスムーズにしています。ただし、SPA ライクなナビゲーションではスクリプトの再実行タイミングに注意が必要です。
astro:after-swap イベントを活用することで、ページ遷移後もテーマの状態やイベントリスナーが正しく維持されるようにしています。
今後の予定
- OGP 画像の自動生成(satori)
- タグ別のフィルタリング機能
- RSS フィードの充実
- パフォーマンス最適化
このブログでは技術的な話題を中心に、学んだことや作ったものを記録していく予定です。