はじめに
ブログや成果物を載せていきたいなーと思った時に いろんなサービスを横断的に使うのもいいですけど、 集約するのがいいなと思いましたのでポートフォリオサイトを構築してみることにしました。
ポートフォリオサイトにあるといい機能を洗い出すと、現時点では下記となります。
- 自己紹介 / Profile
- ブログ / Blog
- 成果物情報 / Products
- お問い合わせ / Contact
- プライバシーポリシー等
ブログではメディア媒体を扱いますし、何よりMarkdownなどで書きやすくしておくう必要があります。
今回はAstro + Cloudflareを使い構築していくことにします!
- Blog / Products
- [Astro] png,jpegなど画像を
astro build実行時に webpに変換できる。
毎回画像変換なんてやってられません! - [Astro] @astrojs/mdxで
コンポーネントを埋め込むことができる!
Markdownファイルで気軽に書くことができ、自分で関数を作り拡張できるのがいい!
- [Astro] png,jpegなど画像を
- Contact
- [Cloudflare] お問合せ受付メールとサクッとメール連携できると楽でいい!
Astro
Astro builds fast content sites, powerful web applications, dynamic server APIs, and everything in-between.
Connect, protect, and build everywhere
Make employees, applications and networks faster and more secure everywhere, while reducing complexity and cost.
このポートフォリオサイトを構築する過程で学んだTipsをまとめます。
全体構成
src配下はざっくりこのように配置しました。
基本的にAstroベースでシンプル構成です。
src
├── components
│ ├── Blog.astro
│ ├── Contact.astro
│ ├── ContactCTA.astro
│ ├── Footer.astro
│ ├── Nav.astro
│ ├── Products.astro
│ ├── Profile.astro
│ ├── ShareButtons.astro
│ ├── TableOfContents.astro
│ └── mdx
│ ├── AffiliateLink.astro
│ ├── ExternalLink.astro
│ ├── LinkCard.astro
│ └── Video.astro
├── content
│ ├── blog
│ │ ├── 2026-04-13_astro_cloudflare-portfolio
│ │ │ ├── assets1.jpg
│ │ │ ├── cover.png
│ │ │ └── index.mdx
│ │ └── 2026-04-xx_xxxxxxxxx
│ │ ├── assets1.jpg
│ │ ├── cover.png
│ │ └── index.mdx
│ ├── config.ts
│ └── products
│ ├── Product1.mdx
│ └── Product2.mdx
├── layouts
│ └── Layout.astro
└── pages
├── api
│ └── contact.ts
├── blog
│ ├── [slug].astro
│ └── index.astro
├── contact.astro
├── index.astro
├── privacy-policy.astro
├── products
│ ├── [slug].astro
│ └── index.astro
└── rss.xml.ts
ブログ/成果物ページを手軽に更新する仕組みにする
フォルダ構成でアセットを管理する
フォルダごとに記事をまとめると、画像・動画を同じ場所に置けてスッキリします。
src/content/blog/
└── 2026-04-13_astro_cloudflare-portfolio/
├── index.mdx ← 記事本文
├── cover.png ← カバー画像
└── assets1.jpg ← カバー以外の画像
Content Collectionsを活用して、簡単に一覧ページに反映
Markdownファイルをコレクションとして管理することで、型安全なフロントマターが使えます。
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: ({ image }) =>
z.object({
title: z.string(),
date: z.string(),
tags: z.array(z.string()),
excerpt: z.string(),
emoji: z.string(),
cover: image().optional(),
draft: z.boolean().default(false),
}),
});
const products = defineCollection({
type: 'content',
schema: z.object({
name: z.string(),
description: z.string(),
emoji: z.string(),
tags: z.array(z.string()),
link: z.string().optional(),
repo: z.string().optional(),
status: z.enum(['Released', 'Beta', 'WIP']),
draft: z.boolean().default(false),
order: z.number().default(0),
}),
});
export const collections = { blog, products };
これを各mdxの最初に追加するだけで、反映完了です!
---
title: Astro+CloudflareでポートフォリオサイトをゼロからつくるTips
date: '2026-04-13'
tags: ['Astro', 'Cloudflare']
excerpt: コンテンツ駆動型フレームワーク「Astro」を「Cloudflare」で構築して簡易ポートフォリオサイトを公開する!
emoji: 🖌️
cover: './cover.png'
---
静的パスを生成する
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
---
まとめ
Astroは静的サイトの構築に非常に優れたDXを提供しています。Content Collectionsを使えばブログ管理も型安全になります。
ぜひ試してみてください!
