これは、私の新しいポートフォリオサイトの最初のブログ記事です。
このブログでは、個人ポートフォリオサイトを制作していく過程と、その中で得た技術的な学びを記録していきます。 今回制作したポートフォリオは、単にプロフィールや制作実績を並べるための静的なWebサイトではありません。Next.js、Supabase、Tailwind CSS、Framer Motion、React Three Fiber、そして3Dアセットを組み合わせ、フロントエンド、バックエンド、UIアニメーション、3D表現、コンテンツ管理をひとつのWebアプリケーションとして統合することを目指しました。 エンジニアのポートフォリオは、ただ「使える技術」を一覧で見せるだけでは十分ではないと感じています。もちろん、技術スタックを提示することは重要です。しかし、それ以上に大切なのは、どの技術を、なぜ選び、どのように組み合わせ、どのような設計思想で実装したのかを示すことだと思っています。 その意味で、このサイト自体をひとつの実装例として扱っています。 単なる名刺代わりのページではなく、実際にアプリケーションとして構成し、データを管理し、UIを設計し、アニメーションを制御し、3D表現を組み込み、今後も継続的に改善していける構成にする。 そうすることで、ポートフォリオそのものが、自分の技術的な現在地を示す成果物になります。 また、個人サイトだからこそ、技術力だけでなく、自分のスタイルや美意識も反映できます。企業サイトや業務システムでは、要件やブランドガイドラインに沿うことが優先されます。一方で、個人ポートフォリオでは、UIの空気感、アニメーションの速度、余白、色、立体表現、コンテンツの見せ方まで、自分の判断で設計できます。 このサイトでは、技術的な堅実さと、個人開発ならではの表現の自由さを両立させることを大切にしました。
このサイトの基盤には、Next.jsを採用しています。 Next.jsはReactをベースにしながら、ルーティング、メタデータ管理、サーバーサイド処理、静的生成、画像最適化、SEO対応など、実用的なWebアプリケーションに必要な機能を幅広くカバーできるフレームワークです。 ポートフォリオサイトというと、最初はHTMLとCSSだけでも十分に見えるかもしれません。しかし、ブログ、プロジェクト紹介、問い合わせフォーム、OGP、言語切り替え、コンテンツ管理、今後の拡張性まで考えると、単なる静的ページではなく、ひとつのアプリケーションとして設計した方が扱いやすくなります。 特にブログ機能では、URL設計、slug管理、メタデータ、一覧ページ、詳細ページ、公開状態の制御などが必要になります。そのため、このサイトではNext.jsのApp Routerを使い、ページ単位で構造を分けながら、コンテンツを扱いやすい形で管理しています。 ブログコンテンツの管理には、Supabaseを使用しています。 最初は、記事データをコード内に直接書く方法も考えられます。しかし、記事数が増えたり、日本語・英語の切り替え、公開状態の管理、記事詳細のブロック構造、画像ギャラリーなどを扱うようになると、コードだけで管理する構成には限界が出てきます。 そこで、SupabaseのPostgreSQLを使い、ブログ記事をデータベースで管理する構成にしました。 記事には、タイトル、スラッグ、本文、概要、タグ、公開状態、公開日、作成日、更新日などの情報を持たせています。これにより、フロントエンド側では「公開済みの記事だけを取得して表示する」という明確な責務分離ができます。 また、SupabaseではRow Level Securityを利用できるため、公開サイトからは必要なデータだけを読み取れるように制御できます。個人開発であっても、データの公開範囲や権限設計を意識することは重要です。特にブログや問い合わせ機能のように、外部に公開される機能を持つ場合は、「動けばいい」ではなく、「どこまで見せるべきか」「どこから書き込めるべきか」を考える必要があります。 UIの実装には、Tailwind CSSを採用しています。 Tailwind CSSの良さは、コンポーネント単位で見た目を素早く調整できる点にあります。余白、色、ボーダー、グラデーション、レスポンシブ対応、hover表現、backdrop blur、shadowなどを、CSSファイルを行き来せずに管理できます。 このサイトでは、カードUI、ガラス風のレイヤー、グロー表現、ラジアルグラデーション、レスポンシブなレイアウトなどを多く使用しています。ただ見た目を派手にするのではなく、技術ブログとして読みやすく、かつポートフォリオとして印象に残るUIを目指しました。 技術ブログは、文章が読みにくいと意味がありません。一方で、ポートフォリオとしては、最初に見た瞬間の印象も重要です。そのため、読みやすさとビジュアル表現のバランスをかなり意識しています。 文章を読むページでは余白と行間を確保し、カード一覧では情報の整理と視線誘導を優先し、トップページではアニメーションや3D表現によって印象を作る。 このように、ページの役割ごとにUIの密度や動き方を変えています。
このポートフォリオでは、Framer MotionによるUIアニメーションと、React Three Fiberによる3D表現も取り入れています。 Framer Motionは、Reactアプリケーションに自然なアニメーションを組み込むために非常に扱いやすいライブラリです。このサイトでは、セクションの切り替え、カードの表示、hover時の反応、フェードイン、スライド、ページ遷移時の視覚的な補助などに使用しています。 アニメーションは、ただ動けば良いというものではありません。過剰なアニメーションは、ユーザーにとってノイズになります。しかし、適切に設計されたアニメーションは、UIの状態変化を自然に伝え、ユーザーが今どこを見ていて、次にどこへ進めるのかを理解しやすくしてくれます。 つまり、アニメーションは装飾であると同時に、情報設計の一部でもあります。 たとえば、カードが急に表示されるよりも、少し遅延してフェードインした方が、ユーザーはコンテンツのまとまりを認識しやすくなります。hover時にわずかに浮き上がる表現を入れることで、「これはクリックできる要素だ」と直感的に伝えることもできます。セクション遷移に動きを加えることで、ページ全体が単なる静的な情報の集合ではなく、ひとつの体験としてつながります。 さらに、このサイトではReact Three Fiberを使った3D表現も取り入れています。 React Three Fiberは、Three.jsをReactのコンポーネント構造の中で扱えるようにするライブラリです。ただし、実際に使ってみると、通常のReact開発とはかなり考え方が異なります。 Reactの世界では、state、props、component、renderといった概念を中心にUIを組み立てます。一方で、3D表現では、scene、camera、light、mesh、material、geometry、animation loop、buffer、frame updateといった考え方が重要になります。 特に、useFrameを使った毎フレーム更新、refによるオブジェクト制御、パーティクル表現、モデルの配置、カメラ制御などは、通常のDOMベースのUIとは別の感覚が必要です。 React Three Fiberは、「Reactで3Dを簡単に書ける魔法のライブラリ」というよりも、Reactの中にThree.jsの世界を持ち込み、その境界をどう設計するかが問われる技術だと感じています。 Canvasの外側は、通常のReact設計として整理できます。しかし、Canvasの内側では、毎フレーム動くオブジェクト、リアルタイムに変化する座標、バッファ、アニメーション状態を扱うため、無理に通常のReactコンポーネント設計へ寄せすぎると、かえって複雑になる場合があります。 このあたりは、実際に触ってみないと分かりにくい部分です。 3D表現をWebサイトに組み込む場合、見た目のインパクトだけでなく、パフォーマンスも重要になります。モデルデータが重すぎると読み込みが遅くなり、パーティクル数が多すぎると描画負荷が上がります。さらに、スマートフォンやノートPCなど、閲覧環境によって性能差も大きくなります。 そのため、3D表現では、見た目、負荷、演出、操作性のバランスを取りながら設計する必要があります。 このポートフォリオでは、3Dアセットやアニメーションを単なる飾りとしてではなく、自分の技術的な関心や表現の方向性を伝えるための要素として扱っています。 自分がどのような技術に興味を持っているのか。 どのようなUIを美しいと感じるのか。 どこまで作り込むことに価値を感じるのか。 そうした部分まで含めて、サイト全体で表現したいと考えました。 結果として、このポートフォリオは、単なるプロフィールサイトではなく、Next.js、Supabase、Tailwind CSS、Framer Motion、React Three Fiber、3Dアセットを組み合わせた、ひとつの実践的なWebアプリケーションになりました。 今後もこのブログでは、制作過程、技術選定、実装で詰まったポイント、改善の記録、パフォーマンス調整、UI設計、3D表現の試行錯誤などを残していきます。 ポートフォリオは、完成したら終わりではありません。自分の技術力や考え方の変化に合わせて、継続的に育てていくものだと思っています。 このサイトも、今の自分の技術的な現在地を示すと同時に、これからの成長を記録していく場所にしていきます。