時の絵(TOKINOE)Next.jsヘッドレス技術要件仕様書
Next.jsヘッドレスアーキテクチャ概要
アーキテクチャ原則(確定)
- フロント: Next.js(ベース: Vercel Next.js Commerce)
- BFF/Edge: Cloudflare Workers(App→BFFのBFFパターン)
- Queues: Cloudflare Queues + Workers(実装済み / レート制限回避)
- DB: Cloudflare D1(非PIIのみ)
- ストレージ: Cloudflare R2(オリジナル/合成画像・非PII)
- 認証: Firebase Auth(IDトークン検証)
- コマース: Shopify Headless(PIIはShopifyのみに集約)
Next.jsヘッドレス技術スタック
1. フロントエンド技術構成
ベースアーキテクチャ
- フレームワーク: Next.js(Vercel Commerceベース)
- 配置方式: OpenNext + Cloudflare adapterでWorkers配備
- モノレポ構成:
apps/webに配置、アプリとして育てやすく
コア技術
| 技術 | バージョン | 用途 | 特徴 |
|---|---|---|---|
| Next.js | 14+ | RSCフレームワーク | Server Actions, Edge最適化 |
| React | 18+ | UIライブラリ | Server Components対応 |
| TypeScript | 5+ | 型安全性 | 厳格な型チェック |
| Tailwind CSS | 3+ | スタイリング | 日本画特化デザインシステム |
状態管理・データフェッチング
| ライブラリ | 用途 | 特徴 |
|---|---|---|
| ビルトイン useState/useEffect | ローカル状態 | RSCとの統合 |
| SWR/React Query | サーバー状態 | キャッシュ最適化 |
| Zustand | グローバル状態 | 軽量・シンプル |
2. 日本画特化UI/UX設計
バリアント画像表示システム
- 即時合成表示: 額縁・マット色選択がリアルタイムで画像反映
- 高精細プレビュー: 拡大機能で細部まで確認可能
- 日本画特有のUI: 余白を活かした美しいレイアウト
デザインシステム
// brand-configでテーマ・文言切替
const brandConfig = {
tokinoe: {
colors: {
primary: '藍色', // 日本の伝統色
secondary: '銀色',
accent: '金色'
},
typography: {
fontFamily: 'ヒラギノ, serif',
headingWeight: 400 // 上品な細字
}
}
};
レスポンシブ対応 + モバイル最適
- ブレークポイント: mobile(320-768px), tablet(768-1024px), desktop(1024px+)
- タッチ最適化: スワイプジェスチャーで作品閉覧
- パフォーマンス: Core Web Vitals最適化
アクセシビリティ + SEO
- WCAG 2.1 AA準拠 + スクリーンリーダー対応
- キーボードナビゲーション完全対応
- SEO最適化: SSR/メタ情報の整備、画像
alt/構造化データ
3. パフォーマンス要件・SLO
Core Web Vitals + SLO目標
- LCP: 2.5秒未満(Edge最適化)
- FID: 100ms未満(バリアント切替高速化)
- CLS: 0.1未満(画像合成時のレイアウトシフト防止)
- 注文完了表示: 2秒以内(同期処理)
- Queue処理: 30秒以内(非同期処理)
- Shopify 429エラー: 0%(Queues + トークンバケット)
画像最適化 + R2統合
- Next.js Image + Cloudflare R2 CDN統合
- WebP/AVIF自動変換 + オンザフライリサイズ
- バリアント画像合成: R2上で自動生成・キャッシュ
- 遅延読み込み + プリロード最適化
Cloudflare Workers BFFアーキテクチャ
1. BFFパターン設計
App→BFFのBFFアーキテクチャ
- Next.js App → Cloudflare Workers BFF → Shopify/D1/R2
- ブランド分離: Middlewareで
host → brand解決 - PII分離: Shopifyのみ、D1/R2は非PII徹底
API設計パターン
// ブランドコンテキスト付きAPI
GET /api/tokinoe/artworks
Headers:
- X-Brand-Context: tokinoe
- Authorization: Bearer <firebase_jwt>
Query Parameters:
- artist: string // 作家で絞り込み
- technique: string // 技法で絞り込み
- period: string // 時代で絞り込み
- frame_color: string // 額縁色フィルタ
- mat_color: string // マット色フィルタ
Response:
{
"artworks": Array<TokinoeArtwork>,
"brand_context": "tokinoe",
"filters_applied": {...},
"pagination": {...}
}
2. Cloudflare D1データベース設計(非PIIのみ)
データベース選択理由
- Cloudflare D1: Edgeロケーションで高速アクセス
- 非PIIのみ: PIIはShopify、D1はメタデータ・キー情報のみ
- ブランド分離:
brand列でデータ分離実現
主要テーブル設計(非PIIスキーマ)
-- 作品マスタ(非PII)
tokinoe_artworks (
id TEXT PRIMARY KEY,
brand TEXT NOT NULL DEFAULT 'tokinoe',
title TEXT NOT NULL,
artist TEXT,
period TEXT,
technique TEXT, -- 技法(水墨画、油彩等)
description TEXT,
-- R2キー情報(PIIなし)
original_image_key TEXT, -- R2 originals/パス
shopify_product_id TEXT, -- Shopify商品ID
-- メタデータ(JSON)
metadata TEXT, -- JSON: {制作年、サイズ等}
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- バリアント画像キー(非PII)
tokinoe_variant_images (
id TEXT PRIMARY KEY,
artwork_id TEXT REFERENCES tokinoe_artworks(id),
brand TEXT NOT NULL DEFAULT 'tokinoe',
-- バリアント情報
frame_color TEXT,
mat_color TEXT,
size_code TEXT,
-- R2キー(合成画像)
composite_image_key TEXT, -- R2 composites/パス
-- ステータス
generation_status TEXT DEFAULT 'pending', -- pending/complete/error
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Firebase UIDマッピング(非PII)
user_brand_contexts (
firebase_uid TEXT NOT NULL,
brand TEXT NOT NULL,
context_data TEXT, -- JSON: ブランド固有設定
PRIMARY KEY (firebase_uid, brand)
);
3. Firebase Auth + PII分離認証システム
認証フロー設計
- Firebase JWT: IDトークン検証をWorkersで実行
- PII分離:
firebase_uidで権限判定、PIIはShopifyのみ - ブランドコンテキスト: ホスト名から自動判定
権限管理(非PIIベース)
// Workersでの権限チェック
interface AuthContext {
firebase_uid: string; // 非PII識別子
brand: 'tokinoe' | 'neko' | 'inu';
role: 'guest' | 'customer' | 'admin';
permissions: string[];
}
// PIIはShopifyで管理
// D1は非PIIのみ保存
const authResult = await verifyFirebaseToken(request);
if (authResult.valid) {
// firebase_uidでD1からブランドコンテキスト取得
const context = await getUserBrandContext(
authResult.firebase_uid,
brandFromHost(request.headers.get('host'))
);
}
権限レベル
| ロール | 権限 | PIIアクセス |
|---|---|---|
| Guest | 閲覧のみ | なし |
| Customer | 注文・アカウント | Shopify経由のみ |
| Admin | 商品管理 | 管理用途のみ |
| SuperAdmin | システム全体 | 編集権限 |
Cloudflare Edgeインフラストラクチャ
1. ホスティング・デプロイ戦略
Edge最適化環境
- ホスティング: Cloudflare Workers(OpenNext + Cloudflare adapter)
- CDN: CloudflareグローバルEdge (200都市での高速配信)
- ドメイン: サブドメイン別ブランド運用 (
tokinoe.contentsprint.com)
CI/CDパイプライン(モノレポ対応)
# GitHub Actions設定例 (Next.jsヘッドレス)
name: Deploy TOKINOE to Cloudflare Workers
on:
push:
branches: [main]
paths: ['apps/web/**', 'packages/**']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
# Next.jsビルド
- run: npm run build --workspace=apps/web
# OpenNext変換 + Cloudflare Workersデプロイ
- run: npx open-next build
- run: npx wrangler pages deploy .open-next/server-function --project-name=tokinoe
# E2Eテスト(プロダクション後)
- run: npm run test:e2e --workspace=apps/web
2. R2画像管理・自動合成システム
画像ストレージ戦略
- Cloudflare R2: オリジナル/合成画像保存(非PII)
- Shopify商品画像: 表示用マスター画像登録
- CDN: Cloudflare Images自動最適化 + オンザフライ変換
バリエーション事前生成プロセス(印刷用・Web用分離)
// 事前バリエーション生成システム
interface PreGeneratedVariantPipeline {
// データ分離戦略(重要)
dataStrategy: {
shopify_images: 'Web表示用最適化画像(800x600px, 72dpi)',
r2_print_data: '印刷用高解像度データ(300dpi以上, TIFF/PSD)',
r2_display_data: 'Web用データ(Shopify登録前の中間ファイル)',
factory_access: '工場システムはR2から直接印刷用データ取得'
};
// 同時生成プロセス(事前生成方式)
generation: {
input: '高解像度原画(300dpi以上)',
// 同時出力: 印刷用とWeb用
outputs: {
print_version: {
resolution: '300dpi+',
format: 'TIFF/PSD',
color_space: 'CMYK',
destination: 'R2:/print_data/{artwork_id}/{product_type}/{variant_key}_print.tiff'
},
web_version: {
resolution: '72dpi',
format: 'WebP/JPEG',
color_space: 'sRGB',
size: '800x600px',
destination: 'R2:/display_data/{artwork_id}/{product_type}/{variant_key}_web.jpg → Shopify'
}
};
// バリエーション種別
variant_types: {
premium_frame: '16パターン (4色額縁 × 4色マット)',
wooden_frame: '3パターン (3色額縁)',
paper_stand: '3パターン (3色)',
postcard: '1パターン (表面+裏面セット)'
};
};
}
// 事前生成バリエーション取得API
// 瞬時バリアント切替(処理待ちゼロ)
GET /api/tokinoe/artworks/{id}/variants
{
"product_type": "premium_frame",
"variant_key": "natural_white"
}
Response:
{
"web_image_url": "https://shopify-cdn.com/products/{product_id}/natural_white.webp",
"print_data_available": true,
"print_data_key": "print_data/{artwork_id}/premium_frame/natural_white_print.tiff",
"shopify_variant_id": "12345678",
"generation_time_ms": 0, // 事前生成済み
"cached": true
}
// 工場システム向け印刷データ取得API
GET /api/tokinoe/factory/print-data/{artwork_id}/{variant_key}
Response:
{
"print_file_url": "https://r2.factory-access.com/print_data/artwork123/premium_frame/natural_white_print.tiff",
"file_size_mb": 45.2,
"resolution": "300dpi",
"color_space": "CMYK",
"ready_for_production": true
}
3. モニタリング・ログ
システム監視
- APM: Vercel Analytics / Datadog
- エラートラッキング: Sentry
- パフォーマンス: Core Web Vitals監視
ログ管理
- アクセスログ: Cloudflare Analytics
- アプリケーションログ: 構造化ログ (JSON)
- エラーログ: 自動アラート設定
PII分離セキュリティ・コンプライアンス
1. PII完全分離戦略
PII分離ルール(重要)
- PIIはShopifyのみ: 氏名、住所、電話、メール等
- D1/R2/ログは非PII徹底:
firebase_uid、キー情報、メタデータのみ - 工場(Electron)システム: 一時取得・保存ゼロ、キャッシュ禁止
暗号化・アクセス制御
- 転送時暗号化: TLS 1.3(Cloudflare標準)
- Firebase JWT検証: WorkersでIDトークン検証→
firebase_uidで権限判定 - アクセス制御: RBAC + ブランドコンテキスト分離
PCI DSS準拠(Shopify基盤)
- 決済情報: Shopifyで完全管理、直接保存禁止
- トークン化: Shopify Paymentsトークン使用
- 監査ログ: Shopify + Cloudflare Workersログの組み合わせ
2. Cloudflare Edgeセキュリティ対策
脆弱性対策(Edge最適化)
| 脅威 | 対策 | Cloudflare機能 |
|---|---|---|
| XSS | CSP + RSCサニタイズ | Workers自動フィルタリング |
| CSRF | SameSite + Server Actions | Workers CSRF保護 |
| SQLi | D1パラメータ化クエリ | D1組み込み保護 |
| DDoS | レート制限 + Queue制御 | Cloudflare DDoS Protection |
| Bot | キャプチャ + 行動解析 | Cloudflare Bot Management |
継続的セキュリティ監視
- 脆弱性スキャン: GitHub Actions組み込み自動実行
- 依存関係監査: Dependabot + npm audit + Next.jsセキュリティアップデート
- ランタイム監視: Cloudflare Analytics + Workersログ解析
- インシデント対応: PII漏洩ゼロ体制 (D1/R2/Logsは非PIIのみ)
Shopify Headless + Cloudflare Queues統合
1. Shopify Headlessコマース統合
決済システム(Shopify基盤)
| サービス | 用途 | 手数料 | PII管理 |
|---|---|---|---|
| Shopify Payments | メイン決済 | 3.4% | Shopifyのみ |
| PayPal | サブ決済 | 3.6% + 40円 | Shopify経由 |
| 銀行振込 | 高額決済 | 固定手数料 | Shopify経由 |
非同期決済フロー(Queue制御)
// Shopify Headless + Cloudflare Queues統合
interface PaymentFlow {
// 1. 同期処理(2秒以内)
syncProcess: {
shopify_checkout_create: 'Shopifyチェックアウト作成',
payment_intent: 'Shopify Payments決済意図作成',
order_confirmation: '注文完了画面表示'
};
// 2. 非同期処理(30秒以内)
asyncProcess: {
queue_dispatch: 'Cloudflare Queueに出荷タスク送信',
shopify_fulfillment: 'Shopify在庫更新・出荷状態更新',
factory_notification: '工場システムへ通知',
customer_notification: '顧客へのメール通知'
};
}
// レート制限回避 (Shopify 429エラー 0%達成)
const queueConfig = {
shopify_api_calls: {
max_per_second: 4, // 変数化で即時調整可能
retry_policy: 'exponential_backoff',
dlq_enabled: true
}
};
2. 物流・配送
配送API統合
- ヤマト運輸: 配送状況追跡
- 佐川急便: 大型商品配送
- 日本郵便: 小型商品配送
配送管理システム
// 配送追跡API
interface ShippingTracker {
trackingNumber: string;
carrier: 'yamato' | 'sagawa' | 'japanpost';
status: 'preparing' | 'shipped' | 'in_transit' | 'delivered';
estimatedDelivery: Date;
updates: TrackingUpdate[];
}
開発・テスト要件
1. 開発環境
ローカル開発
# 開発環境セットアップ
npm install
npm run dev:db # PostgreSQL起動
npm run dev:redis # Redis起動
npm run dev # アプリケーション起動
開発ツール
- IDE: VS Code + 拡張機能
- デバッガー: Node.js Debugger
- API テスト: Postman / Insomnia
2. テスト戦略
テスト種別
| テスト種別 | カバレッジ目標 | ツール |
|---|---|---|
| Unit Test | 80%+ | Jest + Testing Library |
| Integration Test | 主要フロー | Playwright |
| E2E Test | 重要シナリオ | Cypress |
| Performance Test | Core Web Vitals | Lighthouse |
テスト自動化
# テストパイプライン
test:
parallel:
- run: npm run test:unit
- run: npm run test:integration
- run: npm run test:e2e
- run: npm run test:performance
非機能要件
1. パフォーマンス要件
レスポンス時間
| 操作 | 目標時間 |
|---|---|
| ページ初期表示 | 3秒未満 |
| 検索結果表示 | 2秒未満 |
| 商品詳細表示 | 2秒未満 |
| 注文処理 | 5秒未満 |
同時接続数
- 通常時: 1,000ユーザー同時接続
- ピーク時: 5,000ユーザー同時接続
- 負荷対策: オートスケーリング設定
2. 可用性要件
システム稼働率
- 目標: 99.9% (月間ダウンタイム 44分未満)
- 監視: 24/7監視体制
- 復旧: 障害発生から30分以内復旧
バックアップ・災害対策
- データベース: 日次フルバックアップ + リアルタイム同期
- 画像ファイル: マルチリージョン複製
- 設定ファイル: Git管理 + 自動デプロイ
データプライバシー・コンプライアンス
1. 法的要件
個人情報保護法対応
- 取得・利用: 明示的同意取得
- 第三者提供: オプトイン方式
- 開示・削除: 顧客要求への適切対応
Cookie・プライバシーポリシー
- 必須Cookie: システム動作最小限
- 分析Cookie: 同意ベース
- 広告Cookie: オプトイン
2. データガバナンス
データ分類・管理
| データ種別 | 保存期間 | アクセス制御 |
|---|---|---|
| 顧客情報 | 退会後1年 | 暗号化 + アクセスログ |
| 注文履歴 | 5年間 | ロールベース制御 |
| アクセスログ | 1年間 | 管理者のみ |
| 画像データ | 永続 | 公開データ |
E2Eテスト・監視システム
テスト戦略(Next.js特化)
テスト種別とツール
| テスト種別 | ツール | 目的 |
|---|---|---|
| Unit Test | Jest + Testing Library | RSC/Server Actionsの単体テスト |
| Integration Test | Playwright | バリアント画像切替・Shopify統合テスト |
| E2E Test | Playwright | 「購入→出荷」自動化・SLO検証 |
| Performance Test | Lighthouse + Core Web Vitals | Edge最適化効果検証 |
テスト自動化パイプライン
# E2Eテストパイプライン
test-e2e:
parallel:
- name: "TOKINOE購入フローテスト"
run: npm run test:e2e:purchase --workspace=apps/web
- name: "バリアント画像合成テスト"
run: npm run test:e2e:image-composition
- name: "SLO検証テスト"
run: npm run test:e2e:slo-validation
監視・運用システム
メトリクスとRunbook
- Cloudflare Analytics: Edgeパフォーマンス監視
- Workersログ解析: Queue処理状態・エラー監視
- DLQリプレイ手順: 失敗タスクの自動リトライ整備
- アラート設定: SLO達成状態・セキュリティインシデントの即時通知
今日の技術決定事項(まとめ)
- Vercel Commerceを
apps/webに配置、Cloudflare Workersに配備 - R2に生成系/原板を保存、Shopifyには商品マスター画像を登録
- 複雑なバリアント画像切替はNext.jsコンポーネントで新規作成アプローチを採用
- PIIはShopifyのみ、D1/R2は非PII徹底でコンプライアンス安全性確保
文書作成日: 2025-08-23
最終更新: 2025-08-23
バージョン: 2.0 - Next.jsヘッドレス版