Use Cases

Building a Portfolio Site with Claude Code

Learn about building a portfolio site using Claude Code. Includes practical code examples.

ポートフォリオサイトをClaude Codeで作る

エンジニアやデザイナーにとって、ポートフォリオサイトは自分のスキルを示す最高のツールです。Claude Codeを使えば、デザイン性の高いポートフォリオを短時間で構築できます。

セクション構成を指示する

> Astro + Tailwind CSSでポートフォリオサイトを作って。
> Hero、About、Skills、Projects、Contact の5セクション構成で。
> ダークモード対応とスクロールアニメーションも入れて。

Heroセクションの実装

// src/components/Hero.tsx
import { motion } from 'framer-motion';

export function Hero() {
  return (
    <section className="min-h-screen flex items-center justify-center relative overflow-hidden">
      <div className="absolute inset-0 bg-gradient-to-br from-blue-600 to-purple-700 dark:from-gray-900 dark:to-blue-900" />
      <motion.div
        initial={{ opacity: 0, y: 30 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.8 }}
        className="relative z-10 text-center text-white px-4"
      >
        <h1 className="text-5xl md:text-7xl font-bold mb-4">
          田中 太郎
        </h1>
        <p className="text-xl md:text-2xl text-blue-100 mb-8">
          フルスタックエンジニア
        </p>
        <div className="flex gap-4 justify-center">
          <a href="#projects" className="bg-white text-blue-600 px-8 py-3 rounded-full font-medium hover:bg-blue-50 transition">
            作品を見る
          </a>
          <a href="#contact" className="border-2 border-white px-8 py-3 rounded-full font-medium hover:bg-white/10 transition">
            お問い合わせ
          </a>
        </div>
      </motion.div>
    </section>
  );
}

プロジェクトカードコンポーネント

// src/components/ProjectCard.tsx
import { motion } from 'framer-motion';

interface Project {
  title: string;
  description: string;
  image: string;
  tags: string[];
  demoUrl?: string;
  githubUrl?: string;
}

export function ProjectCard({ project, index }: { project: Project; index: number }) {
  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      whileInView={{ opacity: 1, y: 0 }}
      transition={{ delay: index * 0.1 }}
      viewport={{ once: true }}
      className="bg-white dark:bg-gray-800 rounded-xl overflow-hidden shadow-lg hover:shadow-xl transition-shadow"
    >
      <div className="relative aspect-video">
        <img src={project.image} alt={project.title} className="object-cover w-full h-full" />
      </div>
      <div className="p-6">
        <h3 className="text-xl font-bold mb-2 dark:text-white">{project.title}</h3>
        <p className="text-gray-600 dark:text-gray-300 mb-4">{project.description}</p>
        <div className="flex flex-wrap gap-2 mb-4">
          {project.tags.map((tag) => (
            <span key={tag} className="text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded">
              {tag}
            </span>
          ))}
        </div>
        <div className="flex gap-3">
          {project.demoUrl && (
            <a href={project.demoUrl} className="text-blue-600 hover:underline text-sm" target="_blank" rel="noopener noreferrer">
              デモ →
            </a>
          )}
          {project.githubUrl && (
            <a href={project.githubUrl} className="text-gray-600 hover:underline text-sm" target="_blank" rel="noopener noreferrer">
              GitHub →
            </a>
          )}
        </div>
      </div>
    </motion.div>
  );
}

スキルセクション

// src/components/Skills.tsx
const skills = [
  { name: 'TypeScript', level: 90 },
  { name: 'React', level: 85 },
  { name: 'Node.js', level: 80 },
  { name: 'Python', level: 75 },
  { name: 'AWS', level: 70 },
];

export function Skills() {
  return (
    <section id="skills" className="py-20 px-4 max-w-4xl mx-auto">
      <h2 className="text-3xl font-bold text-center mb-12 dark:text-white">Skills</h2>
      <div className="space-y-6">
        {skills.map((skill) => (
          <div key={skill.name}>
            <div className="flex justify-between mb-1">
              <span className="font-medium dark:text-white">{skill.name}</span>
              <span className="text-gray-500">{skill.level}%</span>
            </div>
            <div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-3">
              <motion.div
                className="bg-blue-600 h-3 rounded-full"
                initial={{ width: 0 }}
                whileInView={{ width: `${skill.level}%` }}
                transition={{ duration: 1 }}
                viewport={{ once: true }}
              />
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

パフォーマンスとSEOの最適化

Claude Codeに画像最適化やメタタグの設定を追加で依頼すると、Lighthouse スコアの高いサイトに仕上がります。画像はWebP形式での配信、フォントはサブセット化を行うのがポイントです。

関連記事

デザイン面ではレスポンシブデザインの実装、アニメーションの詳細はアニメーション実装ガイドが参考になります。またダークモード実装の記事もあわせてご覧ください。

ポートフォリオ用のデザインインスピレーションはDribbbleで探すのもおすすめです。

#Claude Code #portfolio #React #Tailwind CSS #Framer Motion