Cellarion Wine Registry について
Cellarion Wine Registryは、ワインコレクター向けのオンラインセラー管理サービスで、セルフホストにも対応しています。共有ワインレジストリやAIソムリエを備え、MCPサーバーを通じて対応クライアントからセラーを管理できます。
主な機能
- 01ボトル、ラック、開栓状況の記録
- 02ワイン検索とラベルスキャン
- 03飲み頃アラートとコレクション統計
- 04オフライン利用と再接続後の同期
- 05AIセラーチャットと共有機能
活用シーン
- 01複数のセラーにあるボトルの整理
- 02ラベルを読み取りワイン情報を補完
- 03オフラインでボトル位置や注いだ量を記録
- 04AIに個人コレクションについて質問
MCP 対応
組み込みのMCPサーバーは`/api/mcp`で利用できます。ClaudeなどのMCP対応クライアントからセラーを読み取り、管理できます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://cellarion.app/api/mcp/publicclaude mcp add --transport http app-cellarion-wine-registry https://cellarion.app/api/mcp/public{"mcpServers":{"app-cellarion-wine-registry":{"type":"http","url":"https://cellarion.app/api/mcp/public"}}}Cursor で開く{"servers":{"app-cellarion-wine-registry":{"type":"http","url":"https://cellarion.app/api/mcp/public"}}}VS Code で開く{"mcpServers":{"app-cellarion-wine-registry":{"type":"http","url":"https://cellarion.app/api/mcp/public"}}}{"mcpServers":{"app-cellarion-wine-registry":{"serverUrl":"https://cellarion.app/api/mcp/public"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
7このツールにパラメーターはありません。
詳細
Cellarion
Cellarion は、すぐに使えるオンラインサービス cellarion.app として提供されている、ホスト型のワインセラーアプリです。 無料アカウントを作成して、ボトルの記録、セラーやラックへの整理、共有ワインレジストリの検索、ソムリエが厳選した飲み頃のおすすめの確認、コレクションについて AI ソムリエとのチャットを始めましょう。インストールも、サーバーも、セットアップも不要です。登録するだけですぐに使えます。すべての機能を、いつまでも無料でご利用いただけます。
Cellarion を使ってみたいだけですか? cellarion.app にアクセスして登録してください。このリポジトリのクローン、Docker の実行、自分でのホスティングは不要です。公開されている デモアカウント(ランディングページでデモをお試しください)と、Google Play の Android アプリもご利用いただけます。
Cellarion は AGPL-3.0 のオープンソースでもあるため、独自のプライベートインスタンスを運用したい場合は、セルフホストできます。この README の残りの部分では、セルフホスティングについて説明します。クイックスタートをご覧ください。ほとんどの方には、cellarion.app のホスト型サービスのご利用をおすすめします。
ホスト型サービス(おすすめ)
Cellarion は次の場所で公開され、どなたでもご利用いただけます。
こちらが Cellarion の主な利用方法です。アカウントを作成して、今日からサービスの全機能をご利用ください。すべての機能を、いつまでも無料でご利用いただけます。 クレジットカードも、お試し期間の期限も、有料機能もありません。インストールやメンテナンスも不要です。開発を支援したい場合は、任意のサポーター、パトロン、ベネファクターの各ティア(月額または年額)やGitHub Sponsorsからご支援いただけます。追加機能はありませんが、感謝の気持ちをお伝えします。
機能
あなたのセラー
- ボトルの記録 — ヴィンテージ、生産者、産地、価格、評価、テイスティングノートとともに、すべてのボトルを記録できます。すでに所有しているボトルをワンクリックで追加することもできます
- セラーとラックの管理 — カスタマイズ可能なラックグリッド(最大 20×20)を備えた複数のセラーと、実際のボトルの配置を確認できる 3D セラールームビュー
- 開栓ボトルの記録 — ボトルを開け、数日にわたってグラスに注ぎ、閉じるか飲み切ることができます。保存状態を考慮した、早めに飲むための通知もあります
- オフラインモード — セラー、ラック、ボトルのコピーをデバイスに保存するため、電波の届かないセラーでもアプリを利用できます。閲覧、ラック内のボトル検索、消費・開栓・注ぐ操作、ボトルの配置・移動、ノートや評価の編集が可能です。オンラインに戻ると変更が同期され、冪等性キーによって一度だけ適用されます。また、他のユーザーの変更を上書きすることはありません(競合は要確認に表示されます)。ユーザーが選択するまでオフのままです。インストール済みアプリで一度だけ確認され、設定からいつでも切り替えられます
- 取り置きボトル — ボトルに「取り置き」の印を付けられます(誕生日や夕食会など)。おすすめや消費フローにも反映されます
- 飲み頃アラート — ワインとヴィンテージごとに、ソムリエが厳選した熟成の飲み頃期間を確認できます。ボトルがピークに近づいたとき、飲み頃に入ったとき、または飲み頃を過ぎつつあるときに通知します
- 充実した統計 — チャート、世界の階級区分図、国、ブドウ品種、価格、飲み頃の状態ごとの内訳
- インポートとエクスポート — Vivino(飲酒履歴を含む)、CellarTracker、Ploc、汎用 CSV、または Cellarion 独自の JSON からコレクションを取り込めます。すべてのデータを JSON、または画像を含む ZIP でエクスポートできます
共有レジストリ
- スマート検索 — Meilisearch を活用した、あいまい検索と高度な重複排除、正規キーによる照合
- ラベルのスキャン — ワインラベルを撮影するだけで、AI が詳細を入力します
- 地域ごとのブドウ品種名 — ブドウ品種ごとに正規の品種をひとつ定め、ラベルに記載されている名前で表示します(ドウロのポートワインはTinta Roriz、アレンテージョの赤ワインはAragonezと表示されます。どちらも Tempranillo として保存されます)
- レジストリ品質管理ツール — 重複・断片化の確認キュー、フィールド間のドメインチェック、名称チェック、ソムリエによる修正提案ワークフローによって、共有データを適切な状態に保ちます AI
- AI セラーチャット — コレクションについて質問できます。料理とのペアリング、シーンに合わせたおすすめ、セラーの状態などに対応します(Claude + Voyage の埋め込みを使用し、MongoDB で検索します。実際に所有しているワインについてのみ回答します)
- 独自の AI を接続 — 組み込みの MCP サーバーを使うと、Claude や MCP 対応クライアントから、会話形式でセラーの情報を読み取り、管理できます
- 独自のモデルを利用 — セルフホストする場合、Anthropic/Voyage の代わりに、OpenAI 互換エンドポイント(Ollama、vLLM、LM Studio)をすべての AI 機能に指定できます
コミュニティと共有
- セラーの共有 — 他のユーザーを招待し、ロールベースのアクセス制御でセラーの閲覧や共同管理ができます
- ワインリスト、レビュー、ディスカッション — 共有可能なリストを作成し、ワインをレビューして話し合ったり、他のユーザーをフォローしたり、再入荷通知を受け取ったりできます
- テイスティングジャーナルとウィッシュリスト — 非公開のメモと、試してみたいワインのリストを管理できます
プラットフォーム
- 環境モニタリング — セラーの温度・湿度センサーを接続できます(Home Assistant に対応した取り込み API)。セラーごとのダッシュボードも利用できます
- シングルサインオン — メールアドレスとパスワードに加えて、Google SSO、または独自の OIDC プロバイダー(Pocket ID、Authentik、Keycloak、Zitadel、Authelia)を任意で利用できます
- インストール可能なアプリ — プッシュ通知とオフライン対応を備えた PWA(サービスワーカーは各ビルドをオフライン利用向けに保持します)と、Google Playの Android アプリを提供しています
- 多言語対応 — Weblate を通じてコミュニティが翻訳しています(翻訳に協力する)
- プライバシーと GDPR — データの完全エクスポート、猶予期間付きのアカウント削除、ワンクリックでのメール配信停止、任意で利用できるセルフホスト型の Cookie を使用しない分析機能(Umami)を備えています
- すべて無料 — 任意のサポーター/パトロン/ベネファクターの各ティア(Stripe、月払いまたは年払い)と GitHub Sponsors が開発を支援します。いずれも追加機能はありません
- ソムリエ・管理者向けツール — 熟成度/価格の管理機能、ワインのリクエスト、品質レポート、レジストリの稼働状況監視、監査ログ、スーパー管理者ダッシュボード
技術スタック
- MongoDB 7 — データベース(Mongoose 8)
- Express 4 — バックエンド API
- React 19 — フロントエンド(React Router 6、Vite 7 でビルド)
- Node.js 24 — ランタイム
- Meilisearch — あいまい検索エンジン
- Voyage AI — ワインの埋め込み生成(任意の OpenAI 互換エンドポイントに切り替え可能)。ベクトルは MongoDB に保存され、バックエンドで比較されます。ベクトルデータベースは不要です
- Anthropic Claude — ラベルスキャンと AI チャット(同じ仕組みで切り替え可能)
- MCP — AI アシスタント向けの OAuth 対応 Model Context Protocol サーバー(
/api/mcp) - Stripe — 任意のサポーター向け決済(ホスト型の Checkout + Portal)
- nginx — React SPA を配信し、
/api/をバックエンドにプロキシします(内部) - Traefik — 外部リバースプロキシ(ご自身で用意してください。この Compose ファイルには含まれていません)
- Docker Compose — コンテナー化
- rembg — Python/Flask による背景除去マイクロサービス
- Umami — 任意で利用できるセルフホスト型の Cookie を使用しない分析機能(compose
--profile analytics)
セルフホスト(クイックスタート)
このセクションは、独自のプライベートインスタンスを実行したい方向けです。Cellarion を利用したいだけの場合は、セットアップ不要の cellarion.app をご利用ください。
前提条件
- Docker + Docker Compose
アプリを実行する
アプリは Traefik 経由でルーティングされるため、最初の up を実行する前に外部 Docker ネットワーク web を作成してください(compose では外部ネットワークとして宣言されているため、作成しないと最初のコマンドは失敗します)。
git clone https://github.com/jagduvi1/Cellarion.git
cd Cellarion
cp .env.example .env
# Edit .env and set JWT_SECRET and MEILI_MASTER_KEY to strong random strings
docker network create web # once; skip if it already exists
docker-compose up --build
| URL | 説明 |
|---|---|
| http://localhost | フロントエンド(React SPA)。Traefik 経由で配信 |
| http://localhost/api/health | バックエンドのヘルスチェック |
自分を管理者にする
新規インストール時には管理者がいません。アプリで自分のアカウントを登録してから、次を実行してください。
docker exec cellarion-backend node src/scripts/make-admin.js <your username or email>
管理者向けページを表示するには、一度サインアウトしてから再度サインインしてください。--remove を指定すると、ロールを再び取り消せます。
デモデータの投入
コンテナの実行後:
docker exec cellarion-backend node src/seed-demo.js
これにより、デモアカウントに加えて、初期タクソノミー、ワイン登録情報、サンプルボトル入りのデモセラーが作成されます。
| アカウント | メールアドレス | パスワード | ロール |
|---|---|---|---|
| 管理者 | [email protected] | Admin1234!demo | admin |
| デモユーザー | [email protected] | User1234!demo | user |
これらはローカル開発用の認証情報です。公開環境にデプロイする前に変更してください。
停止
docker-compose down # keep data
docker-compose down -v # also remove all volumes (wipes database)
アップグレード
git pull
docker-compose up -d --build
v1.241.0 以前からのアップグレード:Qdrant は廃止されました。 AI セラーチャット、再入荷の提案、MCP 類似性ツールで使用するワインのベクトルは、現在 MongoDB に保存され、バックエンドが独自に比較します。今後はベクトルデータベースを実行する必要はありません。アップグレード後、古い qdrant コンテナは孤立コンテナとして実行され続けるため、再埋め込みも埋め込みコストもなしで、ベクトルを一度だけコピーできます。
# dry run (counts only), then the real copy
docker-compose exec -e QDRANT_URL=http://qdrant:6333 backend node src/scripts/migrate-vectors-from-qdrant.js
docker-compose exec -e QDRANT_URL=http://qdrant:6333 backend node src/scripts/migrate-vectors-from-qdrant.js --apply
# then remove the old container, and later its volume
docker-compose up -d --remove-orphans
docker volume ls | grep qdrant # e.g. cellarion_qdrant-data → docker volume rm cellarion_qdrant-data
QDRANT_API_KEYを設定していた場合は、両方のコマンドに-e QDRANT_API_KEY=<your key>を追加してください(新しい Compose では渡されません)。- コピーの代わりに、SuperAdmin → AI で完全な埋め込みジョブを実行し、埋め込みプロバイダーを使ってすべてのワインを再埋め込みできます。
- 埋め込みを設定したことがない場合(
VOYAGE_API_KEY/EMBEDDING_PROVIDERがない場合)、コピーするものはありません。古いコンテナを削除してください。 - その後 v1.241.0 に戻すことはできますが、ダウングレード後と、もう一度アップグレードした後に、完全な埋め込みジョブを実行してください。
アーキテクチャ
以下のツリーは、コードベースの構成を示しています。主な部分を示しており、すべてのファイルを列挙しているわけではありません。バックエンドには 57 個の Mongoose スキーマと約 65 個のルートモジュール(トップレベル 44 個 + admin/ + somm/)があり、MCP サーバーも含まれます。
Cellarion/
├── backend/
│ ├── server.js # Entry point
│ └── src/
│ ├── app.js # Express app setup, mounting, rate limiters
│ ├── config/ # db, plans, upload, aiConfig (models, prompts, limits)
│ ├── middleware/
│ │ ├── auth.js # JWT + role middleware (requireAuth, requireAdmin, requireSomm)
│ │ └── bottleAccess.js # requireBottleAccess(minRole) factory
│ ├── models/ # 57 Mongoose schemas — core: User, WineDefinition,
│ │ # Bottle, Cellar, Rack, WineVintageProfile/Price,
│ │ # WineRequest, WineCorrectionProposal, BottleImage,
│ │ # AuditLog, Country/Region/Appellation/Grape;
│ │ # community: Discussion*, Review, JournalEntry,
│ │ # WishlistItem, WineList, Follow, RestockAlert;
│ │ # infra: Notification, PushSubscription, SupportTicket,
│ │ # ImportSession, StripeWebhookEvent, WineEmbedding,
│ │ # ClimateDevice/Reading, OAuth*, McpActionLog, …
│ ├── routes/ # ~44 top-level route modules: auth (incl. Google SSO),
│ │ # cellars, bottles, wines (public read), racks, chat,
│ │ # stats, import, export, wineRequests, wineReports,
│ │ # discussions, reviews, journal, wishlist, wineLists,
│ │ # follows, recommendations, restockAlerts, climate,
│ │ # notifications, support, stripe, blog, og, sitemap,
│ │ # users, settings, images, health, superadmin, …
│ │ ├── admin/ # /api/admin/* — registry curation, taxonomy, users,
│ │ │ # tickets, proposals, fragmentation/cross-field queues
│ │ └── somm/ # /api/somm/* — maturity windows, prices, wine profiles
│ ├── mcp/ # MCP server: registry, tools (read/write/somm/admin),
│ │ # OAuth, action ledger with undo
│ ├── services/ # search (Meili), embedding (Voyage/OpenAI-compatible),
│ │ # vectorStore (wine vectors in MongoDB, compared in memory),
│ │ # aiChat (RAG), labelScan, enrichmentJob, audit,
│ │ # findOrCreateWine, imageProcessor, taxonomyMerge,
│ │ # registryHealthJob, crossFieldScan, statsService, …
│ ├── utils/ # normalize (dedup), cellarAccess, drinkWindow,
│ │ # grapeDisplay (regional names), nameChecks,
│ │ # crossFieldChecks, ratingUtils, maturityUtils, …
│ ├── data/ # Taxonomy reference JSON
│ └── seed-demo.js
├── frontend/
│ ├── src/
│ │ ├── api/ # Typed API client modules (one per resource)
│ │ ├── components/ # Reusable UI (Layout, Modal, BottleCard, rack grids, …)
│ │ ├── pages/ # App screens (cellars, bottles, stats, chat, admin, …)
│ │ ├── contexts/ # Auth, Theme, Notifications
│ │ ├── locales/ # i18n (Weblate-managed except en)
│ │ └── utils/
│ ├── nginx.conf # nginx config (SPA + /api/ proxy)
│ └── Dockerfile # Multi-stage: Node build → nginx-unprivileged
├── rembg/ # Python background-removal service
└── docker-compose.yml
サービス
外部からのすべてのトラフィックは Traefik(この Compose ファイルの外部にある共有 web Docker ネットワーク上で実行)を経由します。この Compose ファイル内のすべてのサービスは内部専用です。
| サービス | ホストポート | 説明 |
|---|---|---|
| Traefik | 80 | 外部リバースプロキシ(外部) |
| nginx | 内部 | React SPA の配信 + /api/ のプロキシ |
| Backend | 内部 | Express REST API(ポート 5000) |
| MongoDB | 内部 | データベース(ポート 27017) |
| Meilisearch | 内部 | あいまい検索エンジン(ポート 7700) |
| rembg | 内部 | 背景除去(ポート 5000) |
| Umami (+db) | 内部 | オプションの分析 — --profile analytics |
Traefik の背後での実行
Cellarion は、web という名前の共有 Docker ネットワーク上にある Traefik リバースプロキシの背後で稼働するよう設計されています。Traefik はポート 80 で受信する HTTP を処理します(SSL 終端は Cloudflare などの上流で処理されます)。
要件:
- 外部 Docker ネットワーク
webに接続された、実行中の Traefik インスタンス - Cellarion の起動前に
webネットワークが存在している必要があります:docker network create web
フロントエンドサービスでは、docker-compose.yml に次の Traefik ラベルを宣言しています。
traefik.enable: "true"
traefik.docker.network: "web"
traefik.http.routers.cellarion.rule: "Host(`cellarion.app`)"
traefik.http.routers.cellarion.entrypoints: "web"
traefik.http.services.cellarion.loadbalancer.server.port: "8080"
上流ポートは 8080 です(80 ではありません)。フロントエンドイメージは
nginxinc/nginx-unprivileged をベースにビルドされており、非 root の nginx は 1024 未満のポートにバインドできないためです。
Host(...) ルールを、ご自身のドメインに合わせて更新してください。
AI を接続する(MCP)
Cellarion には Model Context Protocol サーバーが組み込まれているため、AI アシスタントは会話形式でセラーを閲覧・管理できます。「今夜は何を開ければいい?」「この6本を追加して」「このヴィンテージの飲み頃期間を設定して」といった操作が可能です。
- 個人用サーバー —
https://cellarion.app/api/mcp(OAuth;自分のセラー、読み取り/書き込み/消費スコープ、該当するロール向けのソムリエ用および管理者用ツール、操作履歴、undo_lastを利用できます) - 公開レジストリサーバー —
https://cellarion.app/api/mcp/public(サインアップ不要;読み取り専用の共有ワインレジストリ) - セットアップガイド — cellarion.app/connect-ai には、Claude(Web/Desktop/Code)やその他の MCP クライアント向けのコピー&ペースト可能な設定が掲載されています
- npm の
cellarion-mcpと 公式 MCP レジストリ(app.cellarion/cellarion、app.cellarion/wine-registry)でも公開されています
セルフホスト可能なインスタンスでは、同じエンドポイントを独自のオリジンから提供します。/connect-ai ページには、インスタンス固有の設定例が自動的に表示されます。
セルフホストユーザー向け共有ワインレジストリ(Registry Bridge)
セルフホスト可能な Cellarion のワインレジストリは、空の状態から始まります。Registry Bridge を使うと、一度に1種類ずつ、cellarion.app の共有レジストリに接続できます。共有レジストリの候補はボトル追加時の検索結果に表示され、選んだワインはテイスティングプロフィールと飲み頃期間とともに自分のデータベースにコピーされます。コピーは毎週更新されます(コピーに加えた変更は保持されます。また、REGISTRY_BRIDGE_REFRESH=off を設定すると更新は停止します)。ユーザーから寄せられた訂正や評価は、インストール元のクレジット付きで共有キューに送られます。レジストリ自体が cellarion.app の外に出ることはありません。大量ダウンロードやスナップショットはありません。
- cellarion.app にサインインし、設定 → セルフホストの Cellarion を接続を開いて、Registry Data Terms に同意し、キーを作成します(アカウントあたり2つまで作成でき、キーは一度だけ表示されます)。
- 次の2行を
.envに追加し、バックエンドを再起動します。
REGISTRY_BRIDGE_URL=https://cellarion.app
REGISTRY_BRIDGE_KEY=cbr_…
クォータ、月ごとのインポート期間、プロトコルについては docs/registry-bridge.md をご覧ください。利用規約は cellarion.app/terms にあります。
コアコンセプト
| エンティティ | 説明 |
|---|---|
| WineDefinition | 共有レジストリに登録される、ヴィンテージに依存しないワイン情報です。管理者が管理し、ユーザーからのワインリクエスト、インポート、ソムリエによる訂正提案を通じて増えていきます。訂正提案は管理者がワンクリックで確認できます。 |
| Bottle | ユーザーのボトルです。WineDefinition を参照し、ヴィンテージ、価格、評価、メモ、ラックの場所、開封済み/予約済みの状態を追加します。 |
| Cellar | ユーザーが所有する、Bottle をまとめた名前付きの保管場所です。ロールベースのアクセス権を通じて他のユーザーと共有できます。 |
| Rack | Cellar 内でボトルを実際に配置するための、カスタマイズ可能なグリッド(最大20×20、デフォルトは8×4)です。3Dの部屋ビューも利用できます。 |
| WineVintageProfile | ワインとヴィンテージごとにソムリエが選定した飲み頃期間(熟成度)のデータです。飲み頃アラートの情報源となります。 |
| WineRequest | ユーザーが送信したワインの提案です。管理者が確認し、WineDefinition を作成して対応します。 |
| Taxonomy | 自由記述の乱立を防ぐために管理者が管理する、国、地域、アペラシオン、ブドウ品種の分類です(地域ごとの表示名も設定できます)。 |
| Notification | ワインリクエストへの対応、画像の承認、セラーの共有、再入荷などのイベントを知らせる、アプリ内通知およびプッシュ通知です。 |
| SupportTicket | 管理者の返信状況を追跡できる、ユーザーからのサポートチケットです。 |
| WineReport | ユーザーが送信する、ワインの品質に関する報告です(情報の誤り、重複、不適切なコンテンツなど)。 |
ユーザーロール
| ロール | 説明 |
|---|---|
| user | 標準ユーザー — 自分のセラー、ボトル、リクエストを管理します |
| sommelier | 共有レジストリ向けに、飲み頃の期間、価格データ、テイスティングプロファイル、修正案を管理します |
| admin | フルアクセス — ワインライブラリ、分類体系、ユーザー管理、画像レビュー、レジストリ品質キュー、監査ログ |
| super admin | プラットフォームレベルのアクセス — システムモニター、サービスの健全性、レート制限、AI 設定、埋め込み管理 |
API の概要
バックエンドには約 65 個のルートモジュールがあります。以下は主要なエンドポイントであり、網羅的なリファレンスではありません。ワインレジストリの読み取り(/api/wines、公開ワインページ、OG 画像、サイトマップ)は公開されています。個人に関する操作にはすべて JWT が必要です(Authorization: Bearer <token>)。
認証 — /api/auth
| メソッド | パス | 説明 |
|---|---|---|
| POST | /register | アカウントを作成します(Mailgun が設定されている場合は認証メールを送信します) |
| POST | /login | ログインして JWT を返します(Mailgun が設定されている場合、メール認証が完了するまでログインできません) |
| GET | /google → /google/callback | Google SSO(GOOGLE_CLIENT_ID/SECRET が設定されている場合) |
| GET | /oidc → /oidc/callback | 独自プロバイダーを使用した OIDC SSO(OIDC_* 変数が設定されている場合) |
| GET | /sso/providers | このデプロイで設定されている SSO プロバイダー |
| GET | /verify-email?token= | メールアドレスを認証し、成功すると JWT を返します |
| POST | /resend-verification | 認証メールを再送信します |
| POST | /forgot-password | パスワードリセットメールをリクエストします |
| POST | /reset-password | トークンを使ってパスワードをリセットします |
セラー — /api/cellars (認証が必要)
| メソッド | パス | 説明 |
|---|---|---|
| GET | / | ユーザーのセラー一覧を取得します |
| POST | / | セラーを作成します |
| GET | /:id | セラーとボトルを取得します |
| PUT | /:id | セラーを更新します |
| DELETE | /:id | セラーを削除します |
| GET | /:id/statistics | 集計統計を取得します |
ボトル — /api/bottles (認証が必要)
| メソッド | パス | 説明 |
|---|---|---|
| POST | / | セラーにボトルを追加します |
| PUT | /:id | ボトルを更新します |
| DELETE | /:id | ボトルを削除します |
| POST | /:id/consume · /:id/open · 注ぐ/閉じる | 飲用追跡のライフサイクル |
| POST | /import/validate | インポートデータを検証し、ワインと照合します(レジストリ読み取り専用) |
| POST | /import/confirm | 検証済みのインポートデータからボトルを作成します |
/api/bottles と /api/racks への書き込みでは、任意の Idempotency-Key ヘッダーを使用できます。同じキーで再度リクエストすると、再適用されずに最初の応答が返されます(保持期間は 8 日間)。オフラインキューに登録された書き込みでは、事前条件(ifActive、ifUnchanged、expectOccupant/expectFrom/expectTo、?expect=)も送信され、セラーがその間に変更されていた場合は 409 が返されます。
オフライン — /api/offline (認証が必要)
| メソッド | パス | 説明 |
|---|---|---|
| GET | /snapshot | オフラインモード用に、ユーザーのセラー(自分のものと共有されたもの)、未消費のボトル、ラックを 1 つのドキュメントで取得します(no-store、レート制限あり) |
ワインレジストリ — /api/wines
公開読み取り。一般ユーザーの検索には上限があります。admin/sommelier は全件を参照できます。
| メソッド | パス | 説明 |
|---|---|---|
| GET | / | ワインを検索/フィルタリングします。パラメーター:search、type、country、region、grapes、sort、limit、offset |
| GET | /:id | 1 件のワイン定義を取得します(ブドウ品種には地域ごとの表記を示す displayName が含まれます) |
チャット — /api/chat (認証が必要)
| メソッド | パス | 説明 |
|---|---|---|
| POST | / | AI セラーチャット(RAG パイプライン)に質問を送信します |
MCP — /api/mcp と /api/mcp/public
AI の接続方法を参照してください。個人用サーバーでは動的クライアント登録を伴う OAuth 2.0 を使用します。公開サーバーでは認証は不要です。
コミュニティ (認証が必要)
/api/discussions、/api/reviews、/api/journal、/api/wishlist、/api/wine-lists、/api/follows、/api/recommendations、/api/restock-alerts — リスト、レビュー、ディスカッション、ジャーナル、ウィッシュリスト、フォロー、再入荷通知。
気候 — /api/climate (認証が必要)
セラーセンサーの登録、測定値の取り込み(Home Assistant に適したトークン認証)、セラーごとのダッシュボード。
通知 / 統計 / サポート / ワインレポート / ワインリクエスト (認証が必要)
従来どおり:/api/notifications、/api/stats/overview、/api/support、/api/wine-reports、/api/wine-requests。
ソムリエ — /api/somm/* (somm または admin ロール)
| メソッド | パス | 説明 |
|---|---|---|
| GET/PUT | /maturity | ワインとヴィンテージごとの飲み頃の段階を管理します |
| GET/POST | /prices | 価格データを管理します |
| PUT | /profile/:wineId | ワインのテイスティングプロフィール、種類、ブドウ品種を修正します |
管理者 — /api/admin/* (admin ロールが必要)
ワインの定義と統合、ワインリクエスト、修正提案、分類体系(ブドウ品種の地域名を含む)、レジストリの品質キュー(重複、細分化、名称チェック、フィールド間チェック)、画像、ユーザー、チケット、監査ログ。
スーパー管理者 — /api/superadmin/* (スーパー管理者のみ)
プラットフォーム分析、レート制限、AI モデル/プロンプト設定、告知バナー、埋め込みジョブ。
環境変数
.env.example を .env にコピーします — すべてコメント付きで、正式なリファレンスです。 主な値:
| 変数 | 必須 | デフォルト | 説明 |
|---|---|---|---|
JWT_SECRET | はい | — | JWT の署名に使用する長いランダム文字列 |
MEILI_MASTER_KEY | はい | — | Meilisearch の認証に使用する長いランダム文字列 |
MONGO_URI | いいえ | mongodb://mongo:27017/winecellar | MongoDB 接続先 |
ACCESS_TOKEN_EXPIRES_IN | いいえ | 15m | アクセストークンの有効期間(セッションはローテーションされる 30 日間の Cookie を使って更新されます) |
PORT | いいえ | 5000 | バックエンドのポート |
FRONTEND_URL | いいえ | http://localhost | CORS オリジン — 本番環境ではドメインを設定してください |
MEILI_URL | いいえ | http://meilisearch:7700 | Meilisearch の URL |
REMBG_URL | いいえ | http://rembg:5000 | 背景除去サービス |
ANTHROPIC_API_KEY | いいえ | — | ラベルスキャンと AI セラーのチャットを有効にします(キーを取得) |
VOYAGE_API_KEY | いいえ | — | AI セラーのチャットの埋め込みに必要です(キーを取得) |
SUPER_ADMIN_EMAIL | いいえ | — | スーパー管理者アカウントのメールアドレス |
MAILGUN_API_KEY / MAILGUN_DOMAIN | いいえ | — | メール認証とトランザクションメールを有効にします |
オプションの連携機能(各項目の詳細は .env.example を参照してください):
| グループ | 変数 | 有効になる機能 |
|---|---|---|
| セルフホスト型 AI | AI_PROVIDER、OPENAI_BASE_URL、OPENAI_API_KEY、AI_MODEL、AI_VISION_MODEL、EMBEDDING_PROVIDER、EMBEDDING_MODEL、EMBEDDING_DIMENSION、… | Anthropic/Voyage の代わりに、OpenAI 互換の任意のエンドポイントを使用します — セルフホスト型 AIを参照してください |
| Google SSO | GOOGLE_CLIENT_ID、GOOGLE_CLIENT_SECRET、GOOGLE_CALLBACK_URL | Google でサインイン |
| OIDC SSO | 必須: OIDC_CLIENT_ID、OIDC_CLIENT_SECRET、OIDC_ISSUER、OIDC_AUTHORIZATION_URL、OIDC_TOKEN_URL、OIDC_USERINFO_URL · オプション:OIDC_PROVIDER_NAME、OIDC_CALLBACK_URL、OIDC_SCOPES、OIDC_TRUST_EMAIL_VERIFIED | 独自の ID プロバイダー(Pocket ID、Authentik、Keycloak、Zitadel、Authelia)を使ってサインインします。Google と併用できます。エンドポイントはプロバイダーの /.well-known/openid-configuration から取得します。クライアントは client_secret_post を使用するように登録してください — 認証情報は HTTP Basic ではなく、トークンリクエストの本文に含めます |
| Registry Bridge | REGISTRY_BRIDGE_URL、REGISTRY_BRIDGE_KEY、REGISTRY_BRIDGE_REFRESH | cellarion.app の共有レジストリでワインを検索し、セルフホスト環境にコピーします。REGISTRY_BRIDGE_REFRESH=off にすると、コピーはコピーした時点の状態で保持されます — Registry Bridgeを参照してください |
| サポーター向け決済 | STRIPE_SECRET_KEY、STRIPE_WEBHOOK_SECRET、STRIPE_{SUPPORTER,PATRON,BENEFACTOR}_PRICE_ID および _ANNUAL_ 版 | オプションの各ティア向けに Stripe Checkout を有効にします。各ティアには専用の Stripe Product(月額価格と年額価格を 1 つずつ)を割り当ててください。そうしないと、カスタマーポータルでティアを切り替えられません。各価格変数にはカンマ区切りのリストを指定します — 現行価格を先頭にし、その後に、有効なサブスクライバーが残っている廃止済み価格を続けます |
| プッシュ通知 | VAPID_PUBLIC_KEY、VAPID_PRIVATE_KEY、VAPID_EMAIL | 飲み頃通知とイベント向けの Web プッシュ |
| 気候モニタリング | CLIMATE_RETENTION_DAYS、CLIMATE_MAX_DEVICES_PER_USER、CLIMATE_MAX_READINGS_PER_DAY、… | センサーデータ取り込みの上限と GDPR に準拠したデータ保持 |
| アナリティクス | UMAMI_DB_PASSWORD、UMAMI_APP_SECRET、VITE_UMAMI_URL、VITE_UMAMI_WEBSITE_ID | Cookie を使用しない Umami のセルフホスト(--profile analytics。VITE_* はビルド時に設定します) |
| 運用 | TRUST_PROXY_HOPS、COOKIE_SECURE、BACKEND_URL、MEILI_SEARCH_KEY、LOG_LEVEL、AUDIT_TTL_DAYS、VITE_SITE_URL、INDEXNOW_KEY、SUPER_ADMIN_IPS | プロキシの信頼設定、Cookie、ログ、SEO、監査ログの保持期間 |
AI Cellar Chat
AI チャット機能には、次の 2 つのサービスが必要です。
- Anthropic Claude(
ANTHROPIC_API_KEY)—セラーの情報に基づいた会話形式の応答を生成します - Voyage AI(
VOYAGE_API_KEY)—セマンティック検索用のワインの埋め込みを作成します ワインのベクトルは MongoDB に保存され、バックエンド自体で比較されます。別途実行するベクトルデータベースはありません。(v1.241 までは Cellarion は Qdrant を使用していました。既存のベクトルを一度だけコピーする方法については、アップグレードを参照してください。)
両方を設定すると、ユーザーはコレクションについて自然言語で質問できます(料理とのペアリング、シーンに合わせたおすすめ、セラーに関する分析情報など)。システムが提示するのは、ユーザーが実際に所有しているワインのみです。架空のおすすめはありません。
ユーザーのサポーター階層に関係なく、全員に共通する 1 日あたりの使用量上限を SuperAdmin が設定できます(デフォルトは 1 日 50 件)。
セルフホスト型 AI(OpenAI 互換エンドポイント)
Anthropic API キーを使いたくないセルフホストユーザーは、LLM を使用するすべての機能(セラーチャット、ラベルスキャン、インポート時の検索、飲み頃・価格・プロフィールの提案)を、OpenAI の Chat Completions API に対応する任意のエンドポイント(Ollama、LM Studio、vLLM、LiteLLM、または OpenAI 自体)に接続できます。
AI_PROVIDER=openai
OPENAI_BASE_URL=http://host.docker.internal:11434/v1 # your endpoint's /v1 root
AI_MODEL=llama3.1:70b # any model your server hosts
AI_VISION_MODEL=qwen2.5-vl:32b # optional — used for label scanning
ワインの埋め込み(セラーチャットのセマンティック検索部分)も、同じ方法で Voyage AI から独立して切り替えられます。
EMBEDDING_PROVIDER=openai
EMBEDDING_MODEL=nomic-embed-text # any embedding model your server hosts
EMBEDDING_DIMENSION=768 # MUST be that model's real vector size
# EMBEDDING_BASE_URL / EMBEDDING_API_KEY default to OPENAI_BASE_URL / OPENAI_API_KEY
注意事項:
- どちらの切り替えもオプトインです。有効にしない限り変更はなく、デフォルトは Anthropic + Voyage のままです。また、それぞれ独立して切り替えられます(例:ローカル LLM + Voyage の埋め込み)。
host.docker.internalは Docker Desktop(Windows/macOS)でのみ、そのまま解決されます。Linux サーバーでは、compose ファイルのバックエンドサービスにextra_hosts: ["host.docker.internal:host-gateway"]を追加するか、OPENAI_BASE_URLにホストの LAN IP アドレス、または compose ネットワーク上のサービスを指定してください。- AI の使用量上限(ユーザーごと/全体の日次上限、インポートのリクエストごとの上限、チャットの日次上限)は、Anthropic の有料利用料金を一定範囲に抑えるために調整されています。自前のハードウェアを使う場合にも適用されます。ローカルエンドポイントに対する使用量を計測したくない場合は、SuperAdmin → Rate limits で上限を引き上げるか、無効にしてください(
0/-1= 無制限)。 - 管理パネルの Claude モデル設定は openai モードでは無視されます(モデルは
AI_MODELで指定します)。設定可能な AI プロンプトは引き続き適用されます。 - ラベルスキャンには、画像認識に対応したモデルが必要です。抽出品質はホストするモデルに大きく左右されます。小規模なローカルモデルでは、Claude よりもラベルの読み取りミスが多くなります。
- 保存されているベクトルには埋め込みの次元数が設定されています。
EMBEDDING_PROVIDER、EMBEDDING_MODEL、またはEMBEDDING_DIMENSIONを変更した後は、埋め込み処理を全件実行してください(SuperAdmin → AI)。すべてのワインをその場で再埋め込みし(その間も検索は引き続き動作します)、その後、古いベクトルを削除します。返される各ベクトルはEMBEDDING_DIMENSIONと照合されるため、値が間違っている場合は検索データを破損せず、明確にエラーになります。 - **複数ユーザーで利用する場合のプライバシーに関する注意:**同梱のプライバシーポリシーでは、AI のサブプロセッサとして Anthropic と Voyage AI が記載されています。これらの変数を自分のローカルエンドポイント(自前のハードウェア上の Ollama/vLLM)に向けると、サードパーティによる AI 処理を完全になくせます。ただし、リモートのサードパーティサービス(OpenAI やホスト型プロキシなど)に向ける場合は、インスタンスのプライバシーポリシーとユーザーの同意を適切に更新する責任があります。
メール認証
MAILGUN_API_KEY と MAILGUN_DOMAIN の両方が設定されている場合、メール認証が有効になります。
- 新規ユーザーは登録後に認証リンクを受け取り、リンクをクリックするまでログインできません。
- リンクの有効期限は 24 時間です。ログインページと
/verify-emailページから再送信できます。 - Mailgun が設定されていない場合、登録時にトークンがすぐ発行されます。これは以前と同じ動作です。
**既存ユーザー:**稼働中のインスタンスで認証を有効にすると、既存アカウントの emailVerified: false となり、ログインできなくなります。アクセスを復旧するには、MongoDB シェルで次の処理を一度実行してください。
db.users.updateMany({ emailVerified: { $exists: false } }, { $set: { emailVerified: true } })
ボトルのインポート
ユーザーは、ほかのワインセラーアプリ(Vivino — 飲酒履歴を含む、CellarTracker、Ploc — スロット位置と購入履歴を含む、または一般的な CSV)からボトルをインポートできます。インポートの流れは次のとおりです。
- アップロード — CSV ファイルをドロップすると、システムがソース形式を自動検出し、標準スキーマにマッピングします
- 検証 — 各アイテムを、あいまい検索(Meilisearch、MongoDB のテキスト検索、正規化キーの検索)と組み合わせた類似度スコアを使って、ワインライブラリと照合します
- 確認 — ユーザーには照合結果が表示されます。完全一致(自動選択済み)、あいまい一致(候補から選択)、一致なし(手動で検索するかスキップ)があります
- インポート — 確認済みのアイテムが、対象のセラーにボトルとして作成されます(確認するまでは共有レジストリには何も書き込まれません)
インポートセッションは保存されるため、中断した場合も後から再開できます。各セラーのオーバーフローメニュー(⋯ → ボトルをインポート)からインポート画面を開けます。編集者またはオーナーのアクセス権が必要です。
マスターインポート JSON 形式
ボトルは JSON としてもインポートできます。各アイテムは次の情報に対応しています。
{
"wineName": "Albe",
"producer": "G.D. Vajra",
"vintage": "2019",
"country": "Italy",
"region": "Piedmont",
"appellation": "Barolo",
"type": "red",
"price": 299,
"currency": "SEK",
"bottleSize": "750ml",
"quantity": 2,
"purchaseDate": "2024-03-15",
"purchaseLocation": "Systembolaget",
"notes": "Beautiful nebbiolo",
"rating": 4.2,
"ratingScale": "5",
"rackName": "Rack A",
"rackPosition": 5,
"addToHistory": false
}
すでに消費したボトルを履歴に直接インポートするには、次を追加します。
{
"addToHistory": true,
"consumedReason": "drank",
"consumedAt": "2025-12-24",
"consumedNote": "Opened for Christmas",
"consumedRating": 4.5,
"consumedRatingScale": "5",
"dateAdded": "2024-06-01"
}
セラーのエクスポート
セラーのオーナーは、セラーのオーバーフローメニュー(⋯ → エクスポート)または設定からデータをエクスポートできます。JSON 形式、またはアップロード済みのボトル画像も含む ZIP 形式を選べます。エクスポートには、ラック配置(rackName、rackPosition)、ラックの形状、3D ルームレイアウト、自分のレビューが含まれます。JSON 形式のデータはそのまま再インポートできます。(すべてのデータカテゴリーを含むアカウント全体のエクスポートは、GDPR に基づき、設定 → プライバシーから利用できます。)
ワインの重複排除
ワインが作成される際、システムは次の方法で重複に近い項目を確認します。
- レーベンシュタイン距離(40%) — 文字単位の類似度
- トライグラム Jaccard(30%) — 3 文字の連続部分文字列の重なり
- トークン Jaccard(30%) — ワイン分野のストップワードを除去した後の、単語単位の類似度
スコア:name × 0.45 + producer × 0.45 + appellation × 0.10
しきい値(デフォルトは 0.75)を超える候補は、「これを使用」オプション付きの警告として表示されます。その裏側では、管理者向けの品質チェックキューが稼働しています。重複グループ、生産者名の分断ペア、名前のチェック、フィールドをまたいだ分野チェック(実際にはアペラシオンである生産者名、国である地域名など)があり、スキャンのたびに最新の分類体系と照合して再チェックされます。
テスト
フロントエンド
cd frontend && npm test
React Testing Library と Vitest(vitest run — ウォッチなしで 1 回実行)を使用します。フロントエンドは Create React App ではなく Vite で構築されているため、--watchAll=false のような CRA 形式のフラグは追加しないでください。未知のフラグを指定するとエラーになります。
バックエンド
cd backend && npm test
Jest を使用します。約 124 のテストスイートで、認証ミドルウェア、セラーのアクセス制御、ワインの正規化と重複排除、レジストリのチェック、評価の変換、飲み頃期間、MCP ツールなどをカバーしています。
プルリクエストを作成する前に、両方のテストスイートを実行してください。テストに失敗するプルリクエストはマージされません。
コントリビューション
バグ修正、機能、ドキュメント、翻訳などのコントリビューションを歓迎します。CONTRIBUTING.md に、セットアップ方法、ブランチとテストのワークフロー、コードベースで採用している規約、すべての機能で確認が必要な個人データのチェックリスト、コミットへの署名方法を含む完全なガイドがあります(Cellarion は Developer Certificate of Origin を採用しているため、git commit -s でコミットしてください)。要点は次のとおりです。
- リポジトリをフォークし、
mainからブランチ(feat/、fix/、docs/…)を作成します - テストを追加して変更を加えます
- 両方のテストスイートを実行します:
cd frontend && npm testとcd backend && npm test - Docker で動作確認します:
docker compose up --buildを実行し、変更した機能を使います mainを対象にプルリクエストを作成します — テンプレートに説明とチェックリストがあります
参加するすべての方に、行動規範の遵守をお願いしています。
翻訳
Cellarion のインターフェースは、Weblate を使ってコミュニティが翻訳しています。Weblate はウェブエディターで、Git もコーディングも必要ありません。英語版は開発者がコードとともに管理し、それ以外の言語はすべてボランティアが翻訳しています。
必要な作業は言語によって異なります。
| 言語 | 必要な作業 |
|---|---|
| フランス語、ドイツ語 | 翻訳者ではなく、レビュアーが必要です。 どちらも一括して機械翻訳されたため、すべての項目がすでに入力されています。既存の翻訳を読み、修正する作業が必要です。確認するのは未翻訳の項目ではなく、state:translated NOT state:approved の項目です。 |
| スウェーデン語 | ネイティブの読者が必要です。ほぼ完成していますが、レビューはほとんど行われていません。 |
| エストニア語、または一覧にない言語 | 最初から翻訳する翻訳者が必要です。Weblate で言語をリクエストして翻訳を始めてください。翻訳率が約 10 % に達するとアプリに表示され、それまでは ?lng=<code> でプレビューできます。 |
ガイドライン、ワイン用語の用語集、言語がベータ版を卒業するための条件については、TRANSLATING.md をご覧ください。
(en は例外ですが、translation.json ファイルを直接編集するプルリクエストは作成しないでください。Weblate の双方向同期と競合します。)
脆弱性の報告
セキュリティ上の問題について、公開のイシューを作成しないでください。GitHub の非公開の脆弱性報告を利用するか、件名に「SECURITY」と記載して [email protected] にメールを送ってください。対応時間、対象範囲、現在のセキュリティ状況に関する率直な説明は SECURITY.md に記載されています。
ライセンス
GNU Affero General Public License v3.0 (AGPL-3.0)
このソフトウェアは自由に使用、変更、セルフホストでき、サービスとして提供することもできます。唯一の条件であり、Cellarion が MIT ではなく AGPL を採用している理由は、変更したバージョンを他の人に利用させる場合、その人たちが変更後のソースコードを入手できるようにしなければならないことです。
コントリビューションも同じライセンスのもとで受け付けています。CONTRIBUTING.md をご覧ください。
謝辞
このコードベースは、Anthropic の Claude Code とともに開発されました。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。