このサイトについて
このポートフォリオサイトの技術構成と選定理由、実験場としての使い方を紹介します。
このサイトは個人のポートフォリオとして、SvelteKit と Cloudflare のスタックで作っています。方針は「運用負荷を最小に、必要になったら育てる」です。
このページでは技術構成と選定理由、それと実験場としての使い方を紹介します。各技術の実装手順やコードの解説はしません。
技術構成
- フレームワーク: SvelteKit 2 / Svelte 5(runes)
- ホスティング: Cloudflare Pages + Workers(adapter-cloudflare)
- データ: Cloudflare D1 + Drizzle ORM
- 記事: MDsveX(Markdown と Svelte を共存させる仕組み)
- お問い合わせ: Resend(メール送信)+ Turnstile(スパム対策)
- テスト: Vitest(ユニット)+ Playwright(E2E)
なぜこの構成にしたのか
個人サイトでまず避けたかったのは、放っておくと壊れる構成と月々の固定費でした。個人サイトは作る時間より維持する時間の方が長くなります。
Cloudflare Pages + Workers なら無料枠で十分動きます。D1(SQLite ベース)も同じプラットフォームに収まるので、DB サーバーを別に持つ必要がありません。固定費はドメイン代だけです。
SvelteKit + Svelte 5 は学習コストとバンドルの軽さのバランスで選びました。$state / $derived といった runes でリアクティビティが素直に書けます。
コンテンツの管理
記事は二系統で管理しています。自前記事は src/posts/*.svx を Git で管理し、draft: true で下書きにできます。Zenn や技術ブログなど外部の記事は D1 に登録してリンクします。表示時は両者をマージして公開日の降順に並べるだけです。
ボツにしたのは CMS の導入です。管理画面があれば更新は楽になりそうですが、CMS はそれ自体の運用が発生します。楽をするための仕組みの世話に追われるのは方針に反するのでやめました。運用は Git と wrangler CLI で完結させています。
デザイン
配色は CSS Variables の二層トークンで管理しています。--blue-500 のような Primitive トークンの上に、--color-primary のような意味づけ(Semantic)トークンを重ねる構成です。コンポーネントは必ず Semantic 経由で参照するので、テーマ変更が一箇所で済みます。
Tailwind は使わず、各コンポーネントのスコープ付き <style> でスタイルを閉じています。
実験場として
このサイトにはもう 1 つ役割があります。新しい技術や開発スタイルを小さく試す実験場です。
仕事のプロダクションコードでは試しにくいものを、まずここで転がします。Svelte 5 の runes や D1 もその類でした。ほかにも Paraglide での日英 2 言語対応や、nonce ベースの厳格な CSP をここで試しています。
あと、開発は AI エージェント(Claude Code)と進めています。指示の出し方やリポジトリ側のルール整備を試す場としても使っています。壊れて困るのは自分だけ。なので思い切って試せます。
失敗と学び
一番ハマったのは Playwright の E2E でした。ある時から click がタイムアウトするようになりました。
原因は wrangler のローカルキャッシュです。旧ビルドの JS ハッシュを参照する HTML がキャッシュに残り、ページのハイドレーションが成立していませんでした。テストの前にキャッシュを削除する形で回避しています。
学びは 1 つです。E2E が不可解に落ちたら、アプリのコードより先にローカルの状態を疑う。
おわりに
デプロイ前は make preflight(型チェック + テスト + E2E + ビルド)を一括で走らせ、緑になってから push する運用です。アクセス解析は外部トラッカーを入れず、Cloudflare Web Analytics だけにしています。
小さく作って、必要になったら育てる。この方針は今のところ機能していると感じています。書く場所と試す場所ができたので、あとは中身を積んでいきます。