Svelte Commerce
A standalone open-source storefront built with SvelteKit, headless across 26 commerce backends. MIT licensed.
翻訳待ち
No updates detected yet. GitHub releases will appear here.
人気のガチャガチャを探して、設置場所や在庫情報をチェックできるガチャ検索・マップアプリ。
Loading the full README. The saved excerpt is shown below.
欲しいガチャを見つける。残っている場所まで分かる。 ガチャガチャの検索と、設置場所・在庫状況の確認ができる Web アプリです。 データは モックデータ(既定) と Cloud Firestore を環境変数で切り替えられます。 Firebase プロジェクトが無くても、モックデータのまま開発・ビルドできます。 • Next.js 16(App Router) • TypeScript • Tailwind CSS v4 • Firebase(Cloud Firestore / Admin SDK)※ Spark プラン(無料枠)前提 • スマートフォン優先のレスポンシブデザイン Node.js 20.6 以上が必要です。 環境変数を設定しない場合は、モックデータ(DATA_SOURCE=mock)で動作します。Read the full README ↗
欲しいガチャを見つける。残っている場所まで分かる。
ガチャガチャの検索と、設置場所・在庫状況の確認ができる Web アプリです。 データは モックデータ(既定) と Cloud Firestore を環境変数で切り替えられます。 Firebase プロジェクトが無くても、モックデータのまま開発・ビルドできます。
Node.js 20.6 以上が必要です。
npm install # 依存パッケージのインストール
npm run dev # 開発サーバー起動 → http://localhost:3000
その他のコマンド:
npm run build # 本番ビルド
npm run start # 本番ビルドの起動
npm run lint # ESLint
npm run typecheck # 型チェック
npm test # テスト(Firestore には接続しない。実データは DATA_SOURCE=local で読み込む)
npm run catalog:build # 収集データから投入予定の内容・カタログ索引をローカルに出力(Firestore には接続しない)
npm run firestore:check # Firestore への接続確認(読み取りのみ)
npm run auth:check # 匿名ログインの動作確認(確認用の匿名ユーザーは自動で削除)
npm run seed:firestore # モックデータを Firestore に投入(Firebase 設定後)
環境変数を設定しない場合は、モックデータ(DATA_SOURCE=mock)で動作します。
| DATA_SOURCE | データ | 在庫報告 |
|---|---|---|
mock(既定) | src/data/mock.ts の架空データ | 保存しない |
local | 収集した実データ data/collected/*.json(約2.3万商品・1,800店舗)。Firestore に接続しない | サーバーのメモリ上のみ |
firestore | Cloud Firestore | 保存する |
DATA_SOURCE=local npm run dev # 実データ規模で画面・検索を確認(Firestore 投入前の確認用)
| パス | 内容 |
|---|---|
/ | トップ。「欲しいガチャを探そう」+検索バー、🔥話題のガチャ / 🆕新着ガチャ / 📍近くで見つかったガチャ |
/search?q=キーワード | 検索結果(画像・商品名・シリーズ・メーカー・価格・設置店舗数・在庫あり報告店舗数)。「在庫ありのみ」フィルタ付き |
/gacha/[id] | ガチャ詳細(画像・商品名・シリーズ・メーカー・価格・発売時期)、「この店で見つけた」報告、「このガチャが見つかった場所」(地図+リスト) |
/locations/[id]?product=[商品ID] | 設置場所詳細(店舗名・住所・営業時間・地図)、対象ガチャの在庫状態・最終確認日時、在庫報告ボタン |
DATA_SOURCE=firestore のときは Firestore に保存され、
mock のときは保存されず画面表示にのみ反映されます(local はサーバーのメモリ上のみ)。src/components/stock/FoundAtStoreReport.tsx)。
店舗の検索は店舗の索引だけで行い、locations は読みません(src/app/actions/locations.ts)。src/
├── app/ # ルーティング(App Router)
│ ├── page.tsx # トップページ
│ ├── search/page.tsx # 検索結果
│ ├── gacha/[id]/page.tsx # ガチャ詳細
│ ├── locations/[id]/page.tsx # 設置場所詳細
│ ├── actions/stockReports.ts # 在庫報告の Server Action
│ └── layout.tsx / globals.css / not-found.tsx
├── components/ # UI コンポーネント(layout / search / gacha / location / stock / map / ui)
├── data/
│ └── mock.ts # ★ モックデータはすべてここに集約(Firestore への初期投入にも使用)
├── lib/
│ ├── data/ # データアクセス層
│ │ ├── source.ts # DataSource インターフェース
│ │ ├── config.ts # DATA_SOURCE による切り替え
│ │ ├── index.ts # 画面から使うクエリ関数(検索・集計)
│ │ ├── mockSource.ts # モック実装
│ │ ├── firestoreSource.ts # Firestore 実装(キャッシュ付き)
│ │ ├── firestore/schema.ts # Firestore のコレクション構造と型変換
│ │ ├── cacheTags.ts # キャッシュのタグ・保持時間
│ │ └── reports.ts # 在庫報告の送信(クライアント → Server Action)
│ ├── firebase/
│ │ ├── adminApp.ts / admin.ts # Admin SDK(サーバー専用)
│ │ └── client.ts # Client SDK(将来のログイン用・現在未使用)
│ ├── auth/reporter.ts # 報告者ID(匿名認証の ID トークンをサーバーで検証して uid を返す)
│ └── format.ts / geo.ts / search.ts / stock.ts
└── types/index.ts # ドメインモデルの型定義
scripts/seed-firestore.ts # モックデータの Firestore 投入スクリプト
scripts/check-firestore.ts # Firestore 接続確認スクリプト
firebase.json # Firebase CLI 設定
firestore.rules # Firestore Security Rules
firestore.indexes.json # Firestore インデックス
storage.rules # Storage Security Rules(現在は未使用)
public/images/gacha/ # 商品画像(SVG)
「ガチャ商品」と「設置場所」は別エンティティとして扱い、多対多の関係を Placement で表します。
GachaProduct 1 ── * Placement * ── 1 Location
│ latestStock(最新在庫のキャッシュ)
│
GachaProduct × Location ── * StockReport(履歴) * ── 1 User
| 型 | 役割 |
|---|---|
GachaProduct | ガチャ商品(名前・シリーズ・メーカー・価格・発売時期・画像など) |
Location | 設置場所(店舗名・住所・緯度経度・営業時間) |
Placement | どの商品がどの場所に設置されているか |
StockReport | ユーザーによる在庫報告(在庫あり / 残りわずか / 売り切れ + 報告日時) |
User | 報告したユーザー |
「在庫あり報告店舗数」は、最新報告が「在庫あり」または「残りわずか」の店舗数です。
| コレクション | ドキュメントID | 主なフィールド |
|---|---|---|
products | 任意(モックは p-001 など) | name, series, maker, price, releaseMonth, imageUrl, description, characters, tags |
locations | 任意(モックは l-001 など) | name, address, area, lat, lng, openingHours |
placements | {productId}__{locationId} | productId, locationId, firstSeenAt, latestStock(status, reportedAt, reportId / 報告なしは null) |
stockReports | 自動ID | productId, locationId, placementId, userId(報告者の Firebase Auth uid), status, reportedAt |
users | Firebase Auth の uid | displayName, createdAt(匿名ユーザーは初回報告時に「ゲスト」として作成) |
users/{uid}/reportThrottles | {productId}__{locationId} | lastReportedAt(連投制限用) |
stockReports は履歴としてすべて残し、更新・削除しません。stockReports への追加」と「placements.latestStock の更新」をまとめて行います。
既存の latestStock より 新しい報告のときだけ 上書きするため、古い報告で最新状態が戻ることはありません。placements.latestStock だけを読み、報告履歴は読みません(読み取り件数の削減)。This is the beginning of the README. Read the rest at the original. Read the full README ↗