🎇

Next.js初心者が年賀状LP作ってみた!〜実装振り返り〜

2025/01/01に公開

Next.js初心者が年賀状LP作ってみた!〜実装振り返り〜

こんにちは!
普段はPythonを使ったバックエンドメインで開発している25歳エンジニアです!
新年一発目の開発は、フロントエンド力を上げたくて、Next.jsで2025年の年賀状LPを作ってみました!

技術選定した理由

正直、最初はReactの素のCRAで作ろうと思ってたんですが、先輩に「今どきはNext.jsでしょ!」って言われて、重い腰を上げてNext.js 14を採用することにしました😅

採用した技術スタック:

  • Next.js 14(App Router)
  • TypeScript
  • Tailwind CSS
  • Framer Motion

TypeScriptは型安全性が欲しかったので必須!って感じでしたが、Tailwind CSSとFramer Motionは「みんな使ってるし、なんか良さそう...?」くらいの軽い気持ちで選びました(笑)

実装で詰まったところ

1. App Routerの概念理解

これが一番キツかったです...😭 Pages RouterからApp Routerに移行したばかりで、layout.tsxとかpage.tsxの使い分けがいまいち分からなくて。

特に苦労したのが、この部分です
👇

// layout.tsxの実装
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ja">
      <body
        className={`${geistSans.variable} ${geistMono.variable} ${notoSerifJP.variable} ${zenKakuGothic.variable} antialiased bg-japanese-white`}
      >
        {children}
      </body>
    </html>
  );
}

最初は単純なchildrenの表示だけだと思ってたんですが、実際はフォントの設定とか、背景色とか、結構いろんなものを含める必要がありました。

2. フォント設定の最適化

Next.jsのフォント最適化機能を使って、以下のようなフォントを設定してみました
👇

// Google Fontsの日本語フォント
const notoSerifJP = Noto_Serif_JP({
  subsets: ['latin'],
  variable: '--font-japanese-serif',
  weight: ['400', '700']
})

const zenKakuGothic = Zen_Kaku_Gothic_New({
  subsets: ['latin'],
  variable: '--font-japanese-sans',
  weight: ['400', '700']
})

// ローカルフォント
const geistSans = localFont({
  src: "./fonts/GeistVF.woff",
  variable: "--font-geist-sans",
  weight: "100 900",
});

const geistMono = localFont({
  src: "./fonts/GeistMonoVF.woff",
  variable: "--font-geist-mono",
  weight: "100 900",
});

これらのフォントを組み合わせることで、和風モダンな雰囲気を出そうと頑張りました!特に、Geist FontsとNoto Serif JPの組み合わせで、現代的でありながらも和の趣を感じられるデザインを目指しました。

3. コンポーネントの実装

特に力を入れたのが、以下のコンポーネントです!
👇

Vision コンポーネント(来年の抱負)

抱負カードには、Framer Motionを使って以下のようなアニメーション効果を実装しました:

  • 初期表示時のフェードイン&スライドアップ効果
  • ホバー時の浮き上がり効果
  • 右上の装飾要素のスケールアニメーション
  • カードごとの遅延表示(stagger効果)
// 抱負カードのアニメーション
<motion.div
  key={index}
  className="group relative bg-white/90 backdrop-blur-sm rounded-lg overflow-hidden
           border border-japanese-gold-light hover:shadow-xl transition-all duration-500"
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  whileHover={{ y: -5 }}
  transition={{ duration: 0.6, delay: index * 0.2 }}
>
  <motion.div 
    className="absolute top-0 right-0 w-16 h-16 bg-japanese-red-light rounded-bl-full"
    initial={{ scale: 0.9, opacity: 0 }}
    animate={{ scale: 1, opacity: 1 }}
    transition={{ duration: 0.6, delay: 0.3 + index * 0.2 }}
  />
  // カードの中身
</motion.div>

backdrop-blurを使用することで、背景とカードの間に微妙な透過効果を持たせ、モダンな印象を演出しています!
あと、japanese-goldやjapanese-redといったカスタムカラーを使用することで、和風テイストを表現しています!

Greeting コンポーネント(挨拶文)

<section className="py-32 bg-gradient-to-b from-japanese-gold-light to-white relative">
  <div className="absolute inset-0 bg-[url('/assets/snake-seal.png')] opacity-5"></div>
  <motion.div 
    className="container mx-auto px-4 max-w-3xl"
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    transition={{ duration: 0.8 }}
  >
    <h2 className="font-serif text-3xl md:text-4xl mb-12 text-center text-japanese-ink-dark">新年のご挨拶</h2>
    <div className="bg-white/80 backdrop-blur-sm p-12 rounded-3xl shadow-lg space-y-6 relative
                  border border-japanese-gold-light">
      <div className="absolute -inset-2 bg-japanese-red/5 rounded-[2rem] blur-3xl -z-10"></div>
      <div className="flex flex-col md:flex-row gap-12 items-start">
        // 挨拶文と自己紹介カード
      </div>
    </div>
  </motion.div>
</section>

グラデーション背景と和風の装飾要素を組み合わせ、モダンな雰囲気を演出しました。
背景には蛇の印章をウォーターマークとして配置し、挨拶文カードにはbackdrop-blur-sm効果を適用することで、奥行きのある表現を実現しています。
また、レスポンシブ対応により、画面サイズに応じて1カラム/2カラムレイアウトに切り替わるようにしました!

4. Tailwind CSSの設定

和風デザインを実現するために、こんな感じでカスタム設定を追加してます🧐
👇

theme: {
  extend: {
    colors: {
      'japanese': {
        'red': {
          light: '#FDF2F2',    // 薄い赤 (背景用)
          DEFAULT: '#B91C1C',  // 基本の赤
          dark: '#991B1B',     // 濃い赤 (アクセント用)
        },
        'gold': {
          light: '#F7F3E7',    // 薄い金 (背景用)
          DEFAULT: '#C7B370',  // 基本の金
          dark: '#A69355',     // 濃い金 (アクセント用)
        },
        'ink': {
          light: '#4B5563',    // 薄い墨 (テキスト用)
          DEFAULT: '#1F2937',  // 基本の墨
          dark: '#111827',     // 濃い墨 (見出し用)
        }
      }
    },
    boxShadow: {
      'japanese': '0 4px 20px rgba(0, 0, 0, 0.05), 0 8px 32px rgba(0, 0, 0, 0.05)',
      'japanese-hover': '0 10px 40px rgba(0, 0, 0, 0.12), 0 20px 60px rgba(0, 0, 0, 0.06)',
    }
  }
}

完成したものがこちらです!
年賀状LP
👇
https://2025-nennga-work.vercel.app/

次のプロジェクトに活かしたいこと

  1. コンポーネント設計をもっと考える
    今回、コンポーネントの粒度がバラバラになっちゃって...。もっとちゃんとAtomic Designとか勉強したいです!

  2. パフォーマンス対策
    Lighthouseのスコアが思ったより低くて焦りました😅 画像最適化とかちゃんとやりたい...

モバイルがちょっと低い...

デスクトップはいい感じ

  1. アクセシビリティ対応
    WAI-ARIAの実装とかキーボード操作対応とか、もっとちゃんと考慮したいです!

まとめ

完全な初心者目線での記事になっちゃいましたが、同じように Next.js 始めたての方の参考になれば嬉しいです!

もし「ここ、こうした方がいいよ!」とかアドバイスあれば、ぜひコメントください🙏✨

ソースコードはGitHubに置いてあります!(あんまり綺麗じゃないけど...笑)

Discussion