AINext.jsGemini APICloudflare R2Server Actions画像生成2025/9/2517分で読める
🎨

Next.js × Gemini APIでAI画像生成機能を実装する完全ガイド

Next.js 14 App Routerと Google Gemini APIを活用したAI画像生成システムの実装ガイド。Server Actions、クレジット管理、Cloudflare R2統合、セキュリティ対策まで網羅的に解説。

D

Dev.AI Team

AI開発エンジニア

フォロワー 12.5K

Next.js × Gemini APIでAI画像生成機能を実装する完全ガイド

本記事では、Next.js 14 の App Router と Google Gemini API(gemini-2.0-flash-exp)を使用して、本格的な AI 画像生成機能をダッシュボードに実装する方法を詳しく解説します。Server Actions、クレジット管理システム、Cloudflare R2 との統合など、実践的な実装方法をコード例と共に紹介します。

🚀 デモサイト:

📦 ソースコード: https://github.com/yourrepo/dashboard

📋 目次

  1. 概要とアーキテクチャ
  2. 環境構築とセットアップ
  3. Server Actions の実装
  4. フロントエンド実装
  5. クレジット管理システム
  6. 画像保存と Cloudflare R2 統合
  7. エラーハンドリングとセキュリティ
  8. パフォーマンス最適化
  9. デプロイと本番環境対応
  10. まとめとベストプラクティス

🏗️ アーキテクチャ概要

技術スタック

  • フレームワーク: Next.js 14 (App Router)
  • AI API: Google Gemini API (gemini-2.0-flash-exp)
  • データベース: Supabase (PostgreSQL)
  • 画像ストレージ: Cloudflare R2
  • 認証: Supabase Auth
  • スタイリング: Tailwind CSS + shadcn/ui
  • 状態管理: Server Actions + React Hooks

システム構成図

[ユーザー] → [Next.js App] → [Server Actions]
                ↓                    ↓
         [Supabase Auth]      [Gemini API]
                ↓                    ↓
         [PostgreSQL]         [画像生成]
                ↓                    ↓
         [クレジット管理]      [Cloudflare R2]
plain text

🛠️ 環境構築

1. 必要なパッケージのインストール

npm install @google/generative-ai
npm install @supabase/supabase-js @supabase/ssr
npm install @aws-sdk/client-s3
npm install sonner lucide-react
npm install framer-motion
bash

2. 環境変数の設定

.env.localファイルに以下の環境変数を設定します:

# Gemini API
GEMINI_API_KEY=your-gemini-api-key

# Supabase
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key

# Cloudflare R2
R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=your-r2-access-key
R2_SECRET_ACCESS_KEY=your-r2-secret-key
R2_BUCKET_NAME=your-bucket-name
R2_PUBLIC_URL=https://your-r2-public-domain.com
plain text

💻 実装詳細

Server Action 実装(画像生成ロジック)

以下は、Gemini API を使用した画像生成の Server Action 実装です:

📝 Server Action 実装例

1. Gemini API を使用した画像生成ロジック

app/actions/generate-image-gemini.ts での Server Action 実装:

"use server";

import { GoogleGenerativeAI } from "@google/generative-ai";
import { getCurrentUserWithProfile, consumeUserCredits } from "./user";

const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || "");

export async function generateImageWithGemini(
  prompt: string,
  options: { style?: string; aspectRatio?: string; quality?: number }
): Promise<GenerateImageResult> {
// ユーザー認証const userData = await getCurrentUserWithProfile();
  if (!userData) return { success: false, error: "ログイン必須" };

// クレジット確認const requiredCredits = 5;
  if (userData.credits.total_credits < requiredCredits) {
    return { success: false, error: "クレジット不足" };
  }

// プロンプト強化let finalPrompt = enhancePrompt(prompt, options);

// Geminiモデルで生成const model = genAI.getGenerativeModel({ model: "gemini-2.0-flash-exp" });
  const images = await generateMultipleImages(model, finalPrompt, 4);

// クレジット消費await consumeUserCredits(userData.user.id, requiredCredits);

  return {
    success: true,
    images,
    creditsRemaining: creditResult.balance_after,
  };
}
typescript

2. プロンプト強化ロジック

スタイルごとのプロンプト最適化:

const styleEnhancements: Record<string, string> = {
  realistic: "、写実的、高解像度、詳細、プロ写真",
  anime: "、アニメスタイル、日本アニメ、鮮やかな色彩",
  illustration: "、デジタルアート、イラスト、芸術的",
  watercolor: "、水彩画、柔らかい色合い",
  "3d-render": "、3Dレンダリング、CGI",
};

if (options.style) {
  finalPrompt += styleEnhancements[options.style];
}
finalPrompt += "、傑作、最高品質";
typescript

🎭 フロントエンド UI 実装

React コンポーネントの設計ポイント

  1. リアルタイムフィードバック: 生成状態を即座に表示
  2. アニメーション: Framer Motion で滑らかな UX
  3. エラーハンドリング: Sonner でトースト通知
  4. レスポンシブデザイン: モバイル対応

💾 Cloudflare R2 統合

画像ストレージの最適化

import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const r2Client = new S3Client({
  region: "auto",
  endpoint: process.env.R2_ENDPOINT,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID!,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
  },
});

export async function uploadImageToR2(
  imageData: Buffer,
  fileName: string
): Promise<string> {
  const key = `ai-images/${Date.now()}-${fileName}`;

  await r2Client.send(
    new PutObjectCommand({
      Bucket: process.env.R2_BUCKET_NAME,
      Key: key,
      Body: imageData,
      ContentType: "image/png",
      CacheControl: "public, max-age=31536000",
    })
  );

  return `${process.env.R2_PUBLIC_URL}/${key}`;
}
typescript

🛡️ セキュリティ対策

1. レート制限の実装

import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, "1 h"),
});

export async function checkRateLimit(userId: string) {
  const { success, limit, reset, remaining } = await ratelimit.limit(userId);

  if (!success) {
    throw new Error(`レート制限: ${new Date(reset).toLocaleString()}に再試行`);
  }

  return { limit, remaining };
}
typescript

2. 入力検証

import { z } from "zod";

const generateImageSchema = z.object({
  prompt: z.string().min(1).max(1000),
  style: z.enum(["realistic", "anime", "illustration"]),
  aspectRatio: z.enum(["1:1", "16:9", "9:16", "4:3"]),
  quality: z.number().min(50).max(100),
  numberOfImages: z.number().min(1).max(4),
});

export async function validateInput(input: unknown) {
  return generateImageSchema.parse(input);
}
typescript

📊 パフォーマンス最適化 Tips

  1. 並列処理: Promise.all で複数画像を同時生成
  2. キャッシュ戦略: CDN で画像配信を高速化
  3. 最適化: WebP 形式への自動変換
  4. ストリーミング: 大容量データの効率的転送

🎯 ベストプラクティス

プロンプトエンジニアリング

  • 具体的な説明: 詳細な描写で精度向上
  • スタイル指定: 明確なアートスタイル
  • ネガティブプロンプト: 避けたい要素を明示

ユーザー体験の向上

  • プログレッシブ表示: 順次生成結果を表示
  • プリセット機能: 人気スタイルを保存
  • 履歴機能: 過去の結果を再利用

🚢 デプロイメント

Vercel へのデプロイ手順

# 環境変数設定
vercel env add GEMINI_API_KEY
vercel env add NEXT_PUBLIC_SUPABASE_URL
vercel env add R2_ENDPOINT

# デプロイ実行
vercel --prod
bash

🔮 今後の拡張機能

  1. 他 AI API 統合: DALL-E 3, Stable Diffusion
  2. 高度な編集: 画像修正、スタイル転送
  3. ビジネス機能: API 提供、チーム共有
  4. AI 拡張: プロンプト自動生成

📚 参考リソース

まとめ

本記事では、Next.js 14 と Google Gemini API を使用した AI 画像生成機能の実装方法を解説しました。Server Actions、クレジット管理、Cloudflare R2 統合など、本番環境で即活用できる実践的な実装を紹介しました。

この実装をベースに、さらに高度な機能を追加して、より強力な画像生成サービスを構築できます。


🏷️ #Next.js #Gemini #AI #画像生成 #Supabase #CloudflareR2

💻 Server Action 実装コード例

Gemini API を使用した画像生成のメイン処理部分:

// app/actions/generate-image-gemini.ts"use server";

import { GoogleGenerativeAI } from "@google/generative-ai";
import { getCurrentUserWithProfile, consumeUserCredits } from "./user";

const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || "");

export async function generateImageWithGemini(
  prompt: string,
  options: {
    style?: string;
    aspectRatio?: string;
    quality?: number;
    numberOfImages?: number;
  } = {}
): Promise<GenerateImageResult> {
// ユーザー認証とクレジット確認const userData = await getCurrentUserWithProfile();
  if (!userData) {
    return { success: false, error: "ログインが必要です" };
  }

  const requiredCredits = 5;
  if (userData.credits.total_credits < requiredCredits) {
    return { success: false, error: "クレジット不足" };
  }

// プロンプト強化let finalPrompt = enhancePrompt(prompt, options);

// Geminiモデルで生成const model = genAI.getGenerativeModel({
    model: "gemini-2.0-flash-exp",
  });

// 複数画像を並列生成const images = await generateMultipleImages(
    model,
    finalPrompt,
    options.numberOfImages || 4
  );

// クレジット消費await consumeUserCredits(
    userData.user.id,
    requiredCredits,
    `画像生成: ${prompt.substring(0, 50)}...`
  );

  return {
    success: true,
    images,
    creditsRemaining: userData.credits.total_credits - requiredCredits,
  };
}
typescript

🎨 画像スタイル定義

利用可能な画像スタイル一覧:

  • 📷 リアル - 写実的で高解像度な画像
  • 🎌 アニメ - 日本のアニメスタイル
  • 🎨 イラスト - アート風のイラスト
  • 🖌️ 水彩画 - 柔らかい水彩画風
  • 🎭 油絵 - クラシックな油絵風
  • 🎮 3D レンダー - 3DCG のような表現
  • ⚪ ミニマル - シンプルでモダン
  • 🌀 抽象画 - 抽象的な芸術作品

🔒 セキュリティ対策

レート制限の実装例:

import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, "1 h"),// 1時間に10回まで
});

export async function checkRateLimit(userId: string) {
  const { success, limit, reset, remaining } = await ratelimit.limit(userId);

  if (!success) {
    throw new Error(
      `レート制限に達しました。${new Date(
        reset
      ).toLocaleString()}に再試行してください。`
    );
  }

  return { limit, remaining };
}
typescript

☁️ Cloudflare R2 での画像保存

生成された画像を Cloudflare R2 に保存し、高速配信:

import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const r2Client = new S3Client({
  region: "auto",
  endpoint: process.env.R2_ENDPOINT,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID!,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
  },
});

export async function uploadImageToR2(
  imageData: Buffer,
  fileName: string
): Promise<string> {
  const key = `ai-images/${Date.now()}-${fileName}`;

  await r2Client.send(
    new PutObjectCommand({
      Bucket: process.env.R2_BUCKET_NAME,
      Key: key,
      Body: imageData,
      ContentType: "image/png",
      CacheControl: "public, max-age=31536000",// 1年間キャッシュ
    })
  );

  return `${process.env.R2_PUBLIC_URL}/${key}`;
}
typescript

🎯 ベストプラクティス

💡 プロンプトエンジニアリングの Tips

  • 具体的な説明:「美しい風景」→「夕暮れの山々、紫とオレンジのグラデーション空」
  • スタイル指定:アートスタイル、雰囲気、色調を明確に
  • ネガティブプロンプト:避けたい要素を明示的に指定

🚀 パフォーマンス最適化

  • 並列処理:Promise.all で複数画像を同時生成
  • キャッシュ戦略:CDN で画像配信を高速化
  • 最適化:WebP 形式への自動変換

📊 データベーススキーマ

Supabase でのテーブル構造:

-- ユーザークレジットテーブルCREATE TABLE user_credits (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
  total_credits INT DEFAULT 100,
  used_credits INT DEFAULT 0,
  subscription_tier TEXT DEFAULT 'free',
  updated_at TIMESTAMPTZ DEFAULT now()
);

-- 画像生成履歴CREATE TABLE image_generation_history (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
  prompt TEXT NOT NULL,
  style TEXT,
  image_urls TEXT[],
  credits_used INT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

-- RLSポリシーALTER TABLE user_credits ENABLE ROW LEVEL SECURITY;
ALTER TABLE image_generation_history ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own data"
  ON user_credits FOR SELECT
  USING (auth.uid() = user_id);
sql

🔮 今後の拡張機能

  • 他 AI API 統合:DALL-E 3、Stable Diffusion
  • 高度な編集:画像修正、スタイル転送
  • ビジネス機能:API 提供、チーム共有
  • AI 拡張:プロンプト自動生成

📚 参考リソース

🎯 まとめ

本記事では、Next.js 14 と Google Gemini API を使用した AI 画像生成機能の実装方法を解説しました。Server Actions、クレジット管理、Cloudflare R2 統合など、本番環境で即活用できる実践的な実装を紹介しました。

この実装をベースに、さらに高度な機能を追加して、より強力な画像生成サービスを構築できます。


🏷️ タグ:#Next.js #Gemini #AI #画像生成 #Supabase #CloudflareR2 #React #TypeScript

このドキュメントで一部のコンテンツが無効になっています

著者について

D

Dev.AI Team

AI開発エンジニア。生成AIを活用した開発手法の研究と実践に従事。 最新のAI技術を使った効率的な開発方法を日々探求しています。