Business Overview

🎯

ターゲットユーザー

トレーディングカードのコレクター・トレーダー。価格相場の把握、トレンド分析、オリパサービスの比較を求めるユーザー層

📝

CMS駆動コンテンツ

Contentful CMSでLPページを管理。非エンジニアでもページの追加・編集・公開が可能。コンテンツとコードの分離

📈

自動価格更新

スクレイピングアダプターで複数サイトから価格データを自動取得。Cloud Schedulerで定期実行し、常に最新の相場情報を提供

📄

シリーズ別LPページ

カードシリーズごとに個別のLPページを生成。SEO最適化されたメタ情報、価格サマリー、トレンドチャートを各ページに表示

System Architecture

Contentful CMS
LPページ・コンテンツ管理
Delivery API / Webhook
Next.js 16
App Router / Cloud Run
Prisma ORM
Cloud SQL
PostgreSQL / Prisma
価格データ書き込み
Scraping
Cloud Scheduler + アダプター
External
TCGdex API

LP Page Structure

各LPページは以下のコンポーネントで構成される。

🎨

Hero

シリーズ名、メインビジュアル、キャッチコピー。Contentfulのhero画像とテキストから生成

💰

価格サマリーカード

現在の平均価格、最高値、最安値、前日比をカード形式で表示。スクレイピングデータから自動算出

📈

トレンドチャート

Rechartsで価格推移をグラフ表示。期間切り替え(1週間/1ヶ月/3ヶ月)に対応

🎲

オリパサービスセクション

関連オリパサービスの比較表示。評価、URL、サービス画像をContentfulから取得

🔗

関連LP

同カテゴリの他シリーズLPへのリンク。内部回遊を促進しSEO効果を向上

🔎

SEOメタ

title, description, OGP画像をContentfulから動的生成。構造化データ(JSON-LD)対応

CMS Data Model (Contentful)

Contentful上で3つのContent Typeを定義し、LPページを構成する。

Content Type フィールド 説明
lpPage title Short Text LPページタイトル
slug Short Text URLスラッグ(一意)
description Long Text ページ説明(SEO用)
heroImage Media ヒーロー画像
sections References (many) lpSection への参照リスト
oripaService name Short Text サービス名
url Short Text サービスURL
image Media サービス画像
rating Number 評価スコア(1-5)
lpSection title Short Text セクションタイトル
body Rich Text セクション本文
layout Short Text レイアウト種別(full / two-column / card)

リレーションシップ

lpPage
LPページ本体
sections (1:N)
lpSection
コンテンツセクション
lpPage は oripaService を別途参照(N:N)
oripaService
オリパサービス情報

Price Scraping Flow

1
Cloud Scheduler
定期トリガー
2
Adapter実行
サイト別スクレイパー
3
データ正規化
共通スキーマ変換
4
PostgreSQL保存
価格履歴テーブル
5
Next.js描画
SSR / ISR
💡
Adapterパターン

各スクレイピング対象サイトごとにAdapterを実装。共通インターフェースで正規化し、新しいデータソース追加時もコア処理に影響を与えない設計。

Database Schema

v1 (Legacy)

テーブル 主要カラム 説明
cards id, name, series, rarity, image_url カード基本情報
prices id, card_id, price, source, fetched_at 価格データ(単一テーブル)

v2 (Current)

テーブル 主要カラム 説明
card_series id, name, slug, release_date カードシリーズ(LPページと1:1)
cards id, series_id, name, rarity, card_number, image_url 個別カード情報
price_snapshots id, card_id, source, price, condition, fetched_at 価格スナップショット(履歴保持)
price_aggregates id, series_id, date, avg_price, min_price, max_price シリーズ別日次集計
scraping_sources id, name, base_url, adapter_key, active スクレイピングソース管理
🛠
Migration Strategy

v1からv2への移行はPrisma Migrateで段階的に実施。card_seriesテーブル追加 → 既存cardsにseries_id追加 → price_snapshotsで履歴保持 → price_aggregatesで集計パフォーマンス最適化。

LP Publication Flow

1
Contentful編集
エディター
2
Publish
Contentful
3
Next.js Fetch
Delivery API
4
ページ生成
SSR / ISR
存在しないslug → 404 Not Found
dynamicParams制御ではなくContentful APIでの存在チェック

存在しないslugへのアクセスは、dynamicParams設定ではなくContentful Delivery APIでの存在チェックで制御する。APIレスポンスが空の場合にnotFound()を返すことで、Contentful側のコンテンツ状態が唯一の真実となる。

Tech Stack

技術 用途 備考
Next.js 16 フロントエンド / SSR App Router、React Server Components
Contentful ヘッドレスCMS Delivery API、Management API、Webhook
Cloud SQL データベース PostgreSQL、価格データ・履歴保存
Prisma ORM スキーマ管理、マイグレーション、型安全クエリ
Cloud Run ホスティング コンテナデプロイ、オートスケール
Tailwind CSS スタイリング ユーティリティファースト CSS
Recharts チャート描画 価格トレンドグラフ
Vitest テスト ユニットテスト、統合テスト
TCGdex API カードデータ カード情報の外部データソース

External Integrations

🔌

Contentful Webhooks

コンテンツ公開時にWebhookでNext.jsのISRを再検証。リアルタイムなコンテンツ反映を実現

Publish / Unpublish イベント
🃏

TCGdex API

トレーディングカードのマスタデータ(カード名、レアリティ、画像)を取得。カード情報の正確性を外部APIで担保

REST API / オープンソース
🕷

Price Scrapers

複数のカード販売サイトから価格データを収集。Adapterパターンでサイトごとの差異を吸収し、統一フォーマットで保存

Cloud Scheduler による定期実行

Cloud Run

Next.jsアプリケーションのコンテナホスティング。トラフィックに応じたオートスケール、ゼロスケールダウンでコスト最適化

GCP マネージドサービス