Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
コーヒー体験を記録し、知識グラフとして育て、自分の味覚やコーヒーの知識を自然に発見できるアプリ。 Live Demo — デモアカウントでログインすると、すぐに試せます(Demo 参照)。 1. Overview 2. Screenshots 3. Demo 4. Core Experience 5. Features 6. Architecture 7. Tech Stack 8. Data Model 9. Knowledge Graph 10. Setup 11. Environment Variables 12. Testing 13. Design Decisions 14. Future Work 一般的なコーヒー記録アプリは、記録が時系列に並ぶだけで、体験同士の関連や自分の味覚傾向を発見しにくいという課題があります。このアプリは、コーヒーを単に保存する対象ではなく、記録するほど理解が深まる個人知識ベースへ変えることを目指しています。 主な対象は、スペシャルティコーヒーに興味を持ち始めた人、自宅とカフェの両方でコーヒーを飲む人、詳しい専門知識はないが自分の好みを知りたい人です。豆を購入するECサイトや、専門家向けの厳密なカッピング管理システムではありません。 詳しくは docs/product.md を参照してください。README 전문 보기 ↗
コーヒー体験を記録し、知識グラフとして育て、自分の味覚やコーヒーの知識を自然に発見できるアプリ。
Live Demo — デモアカウントでログインすると、すぐに試せます(Demo 参照)。
一般的なコーヒー記録アプリは、記録が時系列に並ぶだけで、体験同士の関連や自分の味覚傾向を発見しにくいという課題があります。このアプリは、コーヒーを単に保存する対象ではなく、記録するほど理解が深まる個人知識ベースへ変えることを目指しています。
主な対象は、スペシャルティコーヒーに興味を持ち始めた人、自宅とカフェの両方でコーヒーを飲む人、詳しい専門知識はないが自分の好みを知りたい人です。豆を購入するECサイトや、専門家向けの厳密なカッピング管理システムではありません。
詳しくは docs/product.md を参照してください。
| Home | Records |
|---|---|
| Record Detail | Graph |
|---|---|
| Stats | World Map |
|---|---|
Coffee Diagnosis
ローカルで起動後、以下のデモアカウントでログインすると、15件のサンプル記録と知識グラフをすぐに確認できます。
Email: [email protected]
Password: coffeedemo123
デモデータは npm run seed:demo で投入します(Setup 参照)。エチオピア・ケニアを中心に、産地・フレーバーが記録をまたいで重なるように構成してあり、Graph画面でノードが自然にクラスタ化される様子を確認できます。
中心体験は Record → Connect → Discover(記録する → つながる → 発見する)です。
すべての機能は、この循環のどこを改善するかを説明できる必要があります(docs/product.md)。
MVPの中心機能
MVP完成後に追加した機能(docs/features.md)
notesは読まず、構造化データの集計のみで組み立てる(AI・自然言語処理ではない)Out of Scope(MVPでは扱わない): AI推薦、自然言語による味覚分析、SNS・フォロー、カフェ口コミ、EC連携、画像認識。詳細は docs/mvp.md を参照してください。
flowchart LR
Frontend["React / Vite<br/>(画面表示・フォーム・知識グラフ描画)"]
Express["Express API<br/>(認証・CRUD・入力検証)"]
Mongo[("MongoDB")]
FastAPI["FastAPI<br/>(DB非依存の計算。MVPでは未使用)"]
Frontend -->|HTTPS / JSON| Express
Express --> Mongo
Express -.-> FastAPI
routes → controllers → services → repositories/models)backend/core/graph)で行っており、実装済みの機能は無い(下記 Design Decisions 参照)frontend は FastAPI へ直接アクセスせず、MongoDB へも直接接続しません。FastAPI は MongoDB へ接続せず、認証も行いません。責務の詳細は docs/architecture.md を参照してください。
coffee-app/
├── docs/ 仕様・設計ドキュメント(仕様の正)
├── frontend/src/
│ ├── features/
│ │ ├── coffee-records/ 記録機能のAPI・hooks・components
│ │ ├── graph/ 知識グラフのAPI・hooks・components(react-force-graph-2d)
│ │ ├── insights/ discover/ search/ stats/ diagnosis/ map/
│ │ │ similarRecords/ profile/ 個別機能ごとに同じ構成
│ ├── pages/ ルート単位の画面
│ └── components/ 複数機能で共有するUI
├── backend/
│ ├── core/graph/ insights/ discover/ search/ stats/
│ │ diagnosis/ similarRecords/ shared/ 機能ごとの純粋関数(DB/HTTP非依存)
│ ├── routes/ controllers/ services/ repositories/ models/ validators/
│ └── seeds/ マスターデータ・デモデータの投入
├── fastapi-service/ FastAPI(ヘルスチェックのみの最小構成)
└── docker-compose.yml
| レイヤー | 技術 |
|---|---|
| Frontend | React 19 / Vite / React Router / Tailwind CSS |
| 知識グラフ描画 | react-force-graph-2d(canvas描画 + d3-force) |
| Backend | Node.js / Express 5(ES Modules)。データ層(utils/ models/ repositories/)はTypeScript化済み、他は移行中(Future Work参照) |
| Database | MongoDB / Mongoose |
| 計算サービス | Python / FastAPI |
| 認証 | JWT / bcryptjs |
| テスト・CI | Vitest + Supertest / mongodb-memory-server(backend)、Vitest + React Testing Library(frontend)、pytest、GitHub Actions |
| 開発環境 | Docker Compose |
frontend・backend とも ES Modules を使用します。採用理由と落とし穴は docs/architecture.md にまとめています。
中心エンティティは CoffeeRecord(1回のコーヒー体験)です。
{
userId, title, consumedAt, recordType, // recordType: "home" | "cafe"
rating, notes, cafeName, roasterName,
originId, farmName, varietyIds, processId, roastLevelId, flavorIds,
}
origin / variety / process / roastLevel / flavor は別コレクションへの参照にし、表記揺れを防いで知識グラフで同じ属性を1ノードに統合できるようにしています。farm だけはマスター化せず farmName という文字列で持たせています。農園はデータ品質を担保しにくく、MVPの段階でマスター化すると重複だらけになるためです。
各マスターは表示用の name と、比較用に正規化した normalizedName(unique)を持ちます。RoastLevel だけは値が5段階に固定されているため、normalizedName の代わりに key(light〜dark)と並び順の order を持ちます。
詳細は docs/domain-model.md・docs/database.md を参照してください。
知識グラフは装飾ではなく、記録同士の共通点と自分の嗜好を探索するためのUIです。グラフ専用のコレクションはMongoDBに保存せず、CoffeeRecordとマスターデータからリクエスト時に導出します。
{
"nodes": [
{
"id": "record:abc",
"type": "record",
"label": "Ethiopia Natural",
"metadata": { "recordId": "abc", "consumedAt": "...", "rating": 5 }
},
{
"id": "origin:xyz",
"type": "origin",
"label": "Ethiopia",
"metadata": { "originId": "xyz", "recordCount": 3 }
}
],
"edges": [
{
"id": "record:abc-origin:xyz",
"source": "record:abc",
"target": "origin:xyz",
"type": "ORIGIN"
}
],
"summary": { "recordCount": 10, "nodeCount": 24, "edgeCount": 37 }
}
生成の流れ:
backend/core/graph/graphBuilder.js(DB/HTTPに依存しない純粋関数)が、record:{id} のような種別プレフィックス付きのstable IDでノードを重複排除し、edgeを生成するfeatures/graph/components/GraphCanvas.jsx が、そのJSONをそのまま react-force-graph-2d へ渡す。座標計算・レイアウトは内蔵の d3-force(chargeStrength / linkDistance / collideRadius を調整)が担い、ノードのドラッグ操作にも反応してその場で再計算する(一度きりの静的レイアウトではなく、常時稼働する物理シミュレーション)。ノードの見た目(アイコン・色・当たり判定)はcanvasへ自前で描画している(utils/nodeVisuals.js / utils/canvasIcons.js)ノード種別(record / origin / farm / variety / process / roastLevel / flavor / cafe / keyword)は色だけでなくアイコン・形状でも区別しています。keywordは、notesの自由記述を固定辞書と部分文字列一致で照合して都度導出するノードで、他の属性のようなマスターデータのコレクションは持ちません。詳細は docs/knowledge-graph.md・docs/design.md を参照してください。
必要なもの: Docker Desktop
git clone https://github.com/hikaru181069/coffee-app.git
cd coffee-app
docker compose up -d --build
MongoDB / FastAPI / Backend / Frontend / Prometheus / Grafana の6サービスが起動します。環境変数は docker-compose.yml にローカル開発専用の値が定義済みなので、.env の用意は不要です。
admin / admin。Prometheusのダッシュボードをプロビジョニング済み、monitoring/grafana/provisioning/参照)ポート番号は
docker-compose.ymlのホスト側ポートに合わせています。他のプロジェクトと被らなければ、5173/5001/8000のような一般的な番号に変更しても構いません。
ソースコードを編集するとホットリロード(nodemon / Vite / uvicorn --reload)で反映されます。停止は docker compose down(-v を付けるとDBのデータも削除)。
負荷テスト(k6)は上記5サービスと違い常駐させず、必要な時だけ実行します。
docker compose run --rm k6 run -o experimental-prometheus-rw /scripts/smoke-test.js
# 仮想ユーザー数・実行時間を変えたい場合(ファイルはコピーしない)
docker compose run --rm -e VUS=20 -e DURATION=60s k6 run -o experimental-prometheus-rw /scripts/smoke-test.js
結果はGrafanaの「k6 Load Test」ダッシュボード(monitoring/grafana/provisioning/dashboards/k6-load-test.json)でリアルタイムに見られます。「Coffee App Overview」のBackend Memory・Request Rateと同時に見ると、負荷がbackend側にどう跳ね返るかも確認できます。
「どのくらいの負荷から性能が崩れ始めるか」を探したい場合は、breakpoint-test.jsを使います(VUを10→20→40→80→160と30秒おきに引き上げる。先にGrafanaのダッシュボードを開いておくと崩れる瞬間が見られます)。
docker compose run --rm k6 run -o experimental-prometheus-rw /scripts/breakpoint-test.js
特定のVU数で止めて腰を据えて観測したい場合は、capacity-test.jsを使います(指定したVU数へ一気に到達させたあと、一定時間(既定60秒)維持する階段状のテスト。breakpoint-test.jsのように常にVUが動き続けないため、各レベルでの数値を読み取りやすい)。
docker compose run --rm k6 run -o experimental-prometheus-rw /scripts/capacity-test.js
# 見たいVU・維持時間を変える場合(例: 崩れ始めたVU45〜58付近だけ細かく見る)
docker compose run --rm -e STEPS=40,45,50,55,58,65 -e HOLD_DURATION=45s \
k6 run -o experimental-prometheus-rw /scripts/capacity-test.js
AWSへのリリース準備の一環で、docker-compose.yml(開発用)とは別に docker-compose.prod.yml を用意しています。frontendはVite開発サーバーではなくビルド済みファイルをnginxで配信し、backend/fastapiもホットリロード無しの本番相当の起動方法(npm ci --omit=dev / --reload無し)になります。AWSアカウントは不要で、手元のPCだけで完結します。
cp .env.prod.example .env.prod # JWT_SECRET・GRAFANA_ADMIN_PASSWORDを自分の値に書き換える
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --build
# 初回だけ、マスターデータ・デモデータを投入
docker compose -f docker-compose.prod.yml --env-file .env.prod exec backend npm run seed
docker compose -f docker-compose.prod.yml --env-file .env.prod exec backend npm run seed:demo
/api/宛のリクエストをbackendへリバースプロキシするため、ブラウザからbackendへ直接アクセスする必要が無くなりましたbreakpoint-test.jsでVU100〜140あたりからレイテンシが悪化することが分かったため導入。効果はdocs/architecture.md「k6(負荷テスト)」参照)admin / .env.prodのGRAFANA_ADMIN_PASSWORD。開発用(3000番)と同時に動かせるようポートをずらしています)負荷テスト(k6)はnginxのリバースプロキシ経由(実際のブラウザと同じ経路)で実行されます。
docker compose -f docker-compose.prod.yml --env-file .env.prod run --rm k6 run -o experimental-prometheus-rw /scripts/smoke-test.js
ロードバランシングを外し、backend1台だけに直接負荷をかけて観測したい場合はBASE_URLを上書きします(capacity-test.jsと組み合わせて、崩れ始めるVU帯をnginxを介さず再確認する例)。
docker compose -f docker-compose.prod.yml --env-file .env.prod run --rm \
-e BASE_URL=http://backend1:5001/api \
k6 run -o experimental-prometheus-rw /scripts/capacity-test.js
停止は docker compose -f docker-compose.prod.yml --env-file .env.prod down(-v を付けるとDBのデータも削除)。
注意: これはあくまで「ローカルでの本番再現」です。AWS(ECS/ECR/Secrets Manager等)への実際のデプロイはまだ行っていません(詳細は
DEPLOYMENT.md参照)。
必要なもの: Node.js 22 / Python 3.13 / Docker(MongoDB用)。版は Docker・CI と揃えています。
Nix と direnv があれば、direnv allow するだけで Node.js 22 / Python 3.13 / uv / mongosh がそろい、.venv も自動で作られます(flake.nix・.envrc 参照。direnv がなければ nix develop で同じ環境に入れます)。この場合、下の「依存関係」のうち Python 仮想環境の2行は不要です。
# 依存関係
cd backend && npm install
cd ../frontend && npm install
# Python 仮想環境(テスト用ツール込み。requirements-dev.txtがrequirements.txtを内包する)
python3 -m venv .venv
.venv/bin/pip install -r fastapi-service/requirements-dev.txt
# 環境変数
cp backend/.env.example backend/.env # 値を埋める
起動(3つのターミナル):
docker compose up -d mongodb # MongoDB
cd fastapi-service && ../.venv/bin/uvicorn main:app --reload --port 8000
cd backend && npm run dev
cd frontend && npm run dev
Node.js は
import.meta.dirnameを使うため 20.11 以上が必要です(開発・Docker・CI では 22 を使用)。
cd backend && npm run seed # 産地・品種・精製方法・焙煎度・フレーバーの初期候補
cd backend && npm run seed:demo # デモユーザーとサンプル記録15件(seedを内包)
どちらも既存データを上書き・削除しないため、何度実行しても安全です。
backend/.env(ひな形は backend/.env.example):
| 変数 | 説明 |
|---|---|
PORT | Express が待ち受けるポート(既定 5001) |
MONGO_URI | MongoDB 接続文字列 |
JWT_SECRET | JWT の署名鍵。コミットしないこと |
FRONTEND_URL | CORS で許可するフロントエンドのURL |
FASTAPI_URL | FastAPI サービスのURL |
frontend は VITE_API_URL で Express の URL を指定します(未指定時は http://localhost:5001)。
cd backend && npm run typecheck # tsc --noEmit(utils/models/repositories層のみ、Future Work参照)
cd backend && npm test # Vitest + Supertest + mongodb-memory-server
cd frontend && npm run test # Vitest + React Testing Library
cd frontend && npm run lint # ESLint
cd frontend && npm run build # ビルド確認
cd fastapi-service && ../.venv/bin/pytest # pytest
main への push と pull request で GitHub Actions が同じ内容を実行します(.github/workflows/test.yml)。backendのテストはmongodb-memory-serverを使い、実際にDBへデータを入れて「他ユーザーの記録を更新・削除できない」ことまで検証しています。
mlb-appから再利用したもの — このリポジトリは、同じ構成(React + Vite / Express + JWT認証 / MongoDB / FastAPI / Docker Compose)で先に作った mlb-app を土台にしています。認証(register/login/JWT発行)、app.js/server.js の分離、共通UI(ErrorCard・ProtectedRoute・Navbarのレスポンシブ構造)、Docker/CI構成をそのまま流用しました。
新しく設計し直したもの — CoffeeRecordとマスターデータのモデル・API・知識グラフはすべて新規設計です。特に以下は当初の想定から実装中に判断を変えた点です。
graphNodes/graphEdges コレクションを持たず、CoffeeRecordから都度導出する設計にしました。MVPのデータ量では生成コストが問題にならず、記録更新のたびにグラフを同期する複雑さを避けられるためです(docs/database.md)。react-force-graph-2d へ置き換え、ドラッグ中の座標更新はライブラリに任せる設計へ変更しました。苦労した点
location.key を使い、どんなナビゲーションでもページ全体を再マウントする仕組み)と、選択後にURLの?focus=を消す処理が衝突し、選択した直後に状態が消えるバグに遭遇しました。原因は「URLの書き換えがReact Routerの新しいナビゲーションとして扱われ、ページごと再マウントされていた」ことです。当初は window.history.replaceState を直接使う回避策で解決しましたが、後日「他の全ページはURLを開いた瞬間に読む入力としてだけ使い、ページ側から書き戻すことはしていない」という共通ルールに気づき、Graph画面だけが持っていたこの後片付け処理自体を削除しました。選択状態は既にコンポーネント内のstateへ1回だけ反映済みのため、URLに?focus=が残っても再選択が誤って走ることはなく、これによりGraph画面も他の全ページと同じ設計に揃いました。react-force-graph-2d の未文書化の挙動 — 乗り換え後も、onNodeClick/onBackgroundClick がほぼ発火しない、width/height を明示的に渡すとズーム・ドラッグが効かなくなる、カメラ追従用の onEngineTick/onEngineStop が実際には力学シミュレーションが動いているにもかかわらず一度も呼ばれない、といった複数の不具合に遭遇しました。いずれもライブラリ本体(force-graph)のソースを直接読んで原因を特定し、クリック判定を自前のpointerdown/pointerup比較で置き換える、canvasサイズを初回計測値で固定する、カメラ追従を自前のrequestAnimationFrameループへ置き換える、という形でそれぞれ回避しました(詳細は frontend/src/features/graph/components/GraphCanvas.jsx 冒頭のコメント参照)。docs/mvp.md のOut of Scope)utils/ models/ repositories/まで完了。次はvalidators/ services/ controllers/ routes/ middleware/、その後frontend)・CSS Modulesへの移行| ファイル | 内容 |
|---|---|
docs/product.md | プロダクトの目的・対象ユーザー・設計判断の原則 |
docs/mvp.md | MVPのスコープと完了条件 |
docs/design.md | 画面構成・UIルール |
docs/domain-model.md | CoffeeRecord とマスターデータ |
docs/database.md | MongoDB スキーマ設計 |
docs/knowledge-graph.md | 知識グラフの生成方針 |
docs/features.md | Insights・Search・Entity Detail・Stats・Discoverの仕様 |
docs/architecture.md | サービス責務・モジュール形式・エラー形式 |
docs/api.md | APIエンドポイント設計 |
docs/implementation-plan.md | Phase 0〜6 の進め方 |
docs/mlb-legacy-inventory.md| mlb-app由来コードの棚卸し記録(Phase 6で削除実施) |