デモキット仕様(配布+GMeet 実演)
顧客・店員・BE は本番と同じコード(BE はアダプタのみ mock)、Terminal だけモックにしたデモ環境。先方に zip を配布し、Google Meet で使い方を実演する。
現行のAWSデモは Cloudflare Pages + AWS API 構成。手順は「11. Cloudflare Pages + AWS デモ」と ../OPERATIONS.md を参照。
1. 目的
- 実機と Square アカウントなしで、V1 の操作感を再現する
- 先方が自分の PC で起動して試せる
- 本番と同じ状態遷移・API 形状を使い、捨てコードにしない
- 現金は対象外(V1.1。デモでは扱わない)
2. 構成
[CloudFront]
/s/{shopId}/customer ← 顧客PWA(公開)
/s/{shopId}/staff ← 店員PWA(公開)
/api/* ← Lambda(BE、ADAPTER=mock)
/webhooks/* ← Lambda
[店舗PC(キット / Node)]
/terminal ← Terminal モック(ローカル配信)
/setup ← 初期設定
- PWA は公開ホスト。客・店員はスマホの URL を開くだけ
- キットは Terminal モックとランチャーを担当
- モック端末は 2 秒ポーリングで BE と同期(現行AWSデモ)
3. 配布物
shop-kit/
├── start.bat Windows 用(ダブルクリック)
├── start.command Mac 用(初回 chmod +x を README に明記)
├── package.json
├── package-lock.json
├── server.js Terminal モック配信+ランチャー
├── shop.config.json 設定
├── public/
│ ├── terminal/ Terminal モック
│ └── setup/ 初期設定
├── README.md 5分で分かる手順
└── DEMO-SCRIPT.md GMeet 台本(3分/15分)
4. 起動(Windows / Mac)
前提
- Node.js 18 以上(20 LTS 推奨)
- インターネット接続(BE はクラウド)
手順
- zip を展開
start.bat(Windows)/start.command(Mac)を実行- ブラウザが自動で開く
- 未設定なら
/setupでshopId/registerId/apiBaseUrlを入力 - ランチャーから「顧客」「店員」「端末」を開く
現状のPWA: manifest とアイコンのみで、Service Worker は未登録。ブラウザ運用で、PWAインストールは未対応。
スマホからHTTPSで開く場合(任意・AWS不要)
Cloudflare Quick Tunnel の例(独自ドメイン・アカウント不要、URLは起動ごとに変わる):
# 別ターミナルで3本起動
cloudflared tunnel --url http://localhost:5173
cloudflared tunnel --url http://localhost:5174
cloudflared tunnel --url http://localhost:3100
表示されたURLを .env またはシェルの環境変数に設定して npm run dev:
CUSTOMER_URL=https://xxxx.trycloudflare.com/
STAFF_URL=https://yyyy.trycloudflare.com/
TERMINAL_URL=https://zzzz.trycloudflare.com/
- ランチャーのQRが上書きURLになる。PCの「端末画面を開く」はローカルのまま
cloudflaredは別途インストール(このリポジトリの依存には含めない)- インストール済みPWAはURL(オリジン)に固定されるため、Quick TunnelのURL変更後は再インストールが必要
- 継続利用する場合は Tailscale Funnel などの固定URLを使う
- ローカルデモ自体はAWS不要(Docker上のDynamoDB Localを使用)
実装上の注意
- ネイティブ依存ゼロ(
sqlite3等を使わない) - パスは
path.join、改行は.gitattributesで固定 - ブラウザ起動は
process.platformでstart/openを切替 - 起動パネルは Terminal(3100)のHTTP応答を待ってから別窓で開く(失敗時はパネルのボタン)
OPEN_TERMINAL=0で Terminal の自動オープンを無効化- Terminal パネルのQRは LAN の
3100(TERMINAL_URL指定時はそのURL)。スマホからも開ける - ポート 3000 → 使用中なら 3001 に自動フォールバック
- Windows の文字化け対策(UTF-8 /
chcp 65001) - 起動時に
doctor:Node 版、API 到達性、設定の妥当性をチェック
5. 設定
shop.config.json
{
"shopId": "shop-01",
"shopName": "デモ商店",
"registerId": "reg-01",
"terminalId": "term-01",
"apiBaseUrl": "https://xxxx.execute-api.ap-northeast-1.amazonaws.com/prod",
"publicBaseUrl": "https://xxxx.cloudfront.net",
"mode": "mock",
"staffPin": "1234"
}
- 配布時に
shopId/registerIdを発行して同梱 modeはキットの表示・機能フラグ用。実際の決済アダプタは BE 側のADAPTER(mock/sandbox/production)で決まるstaffPinはデモ専用(本番は Cognito)
6. Terminal モック仕様
画面
┌────────────────────────────┐
│ DEMO │
│ ──────────────────────── │
│ ご注文 │
│ コーヒー豆 200g ×2 2,400 │
│ ドリッパー ×1 800 │
│ ──────────────────────── │
│ 合計 ¥3,200 │
│ │
│ [ カードをタッチ ] │
│ [ キャンセル ] [タイムアウト] │
└────────────────────────────┘
状態
| 状態 | 表示 |
|---|---|
IDLE |
「お待ちください」 |
PRESENT |
明細+合計+タッチ促し |
PROCESSING |
スピナー「処理中」 |
SUCCESS |
チェック+「完了」+レシート風 |
FAILED |
エラー+再試行案内 |
CANCELED / EXPIRED |
取消・期限切れ |
操作(デモ用)
タッチ(成功)→POST /api/mock/checkouts/{id}/completeキャンセル→.../cancelタイムアウト→.../timeout- 成功・失敗は本番と同じ共通ハンドラを通す
表示上の注意
- 「DEMO」バッジを常時表示し、本物と誤認させない
- 金額・明細は BE が返した注文をそのまま表示
- 端末風フレーム(5.5インチ比率)で実機に寄せる
7. モード(BE 側 ADAPTER)
ADAPTER |
カタログ | 端末 | 用途 |
|---|---|---|---|
mock |
シードJSON | Terminal モック | 配布デモ |
sandbox |
Square Sandbox | シミュレート端末ID | 結合テスト |
production |
Square 本番 | 実機 | 本番 |
- キットの
shop.config.jsonのmodeは表示・フラグ用。BE のADAPTERと揃えて運用する
8. GMeet 実演(30分)
| 時間 | 内容 |
|---|---|
| 0–5分 | 全体像(顧客/店員/端末の3画面) |
| 5–15分 | 正常系:カート→6桁→店員確認→端末タッチ→完了 |
| 15–20分 | 例外系:キャンセル/タイムアウト |
| 20–27分 | 先方の PC で /setup→起動→実演(画面共有でフォロー) |
| 27–30分 | 本番(Square 実機)との差分、次フェーズ |
画面共有の配置
- 1画面に3ウィンドウ:顧客PWA(モバイル幅)/店員PWA(モバイル幅)/Terminal モック
- 2レジを見せる場合は、キットを別ポートでもう1つ起動(
reg-02)
9. トラブルシュート
| 症状 | 原因 | 対応 |
|---|---|---|
| 起動しない | Node 未導入/古い | README の手順、node -v 確認 |
| ポート使用中 | 既存プロセス | 自動で 3001 へ。表示された URL を使う |
| 画面が真っ白 | API 到達不可 | apiBaseUrl と /api/health を確認 |
| カメラが動かない | HTTPS でない/アプリ内ブラウザ | Safari/Chrome で開く(MVP はスキャンなし) |
Mac で start.command が開かない |
実行権限 | chmod +x start.command |
| 文字化け | コンソールのエンコーディング | UTF-8 / chcp 65001 |
| 「本物?」と誤解 | モック | DEMO バッジと README を明示 |
10. 受入条件
- Windows と Mac の両方で
startから起動できる - 未設定時に
/setupへ誘導される - 顧客→店員→端末→完了 が一連で動く
- キャンセル/タイムアウトが再現できる
- 2レジ同時で干渉しない
- DEMO 表示が出ている
- README と台本だけで先方が再現できる
11. Cloudflare Pages + AWS デモ(現行)
ローカルにVite/Nodeを常駐させず、画面はCloudflare Pages、API/DBはAWSで動かす構成。
Cloudflare Pages(無料・HTTPS)
customer.pages.dev → 顧客アプリ + /launcher
staff.pages.dev → 店員アプリ
terminal.pages.dev → Terminal
↓ fetch /api/*(CORS)
AWS API Gateway → Lambda → DynamoDB
↑
WebSocket(wss)はAPI Gatewayへ直接
前提
- AWSアカウント・AWS CLI・SAM CLI・Node.js 22
- AWSプロファイル(例:
shoptools)にCloudFormation/Lambda/DynamoDB/SSM/IAM/S3の権限 - Cloudflareアカウント(Pages Free)
CLOUDFLARE_API_TOKEN(Account → Cloudflare Pages → Edit)CLOUDFLARE_ACCOUNT_ID.envにCLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDを設定(Git管理外).envにMFA_SERIAL/MFA_TOTP_SECRET/MFA_DURATION_SECONDSを設定。MFA_SERIALはMFAデバイスのARN(例:arn:aws:iam::<account>:mfa/<device-name>)。ユーザーARNではない。TOTPシークレットはMFAデバイス同等の秘密MFA_TOTP_SECRETはAuthenticator登録時のQRにあるBase32 secret。AWSは既存デバイスのsecretを再表示しない
初回デプロイ
. .\scripts\use-env.ps1
npm run aws:mfa # MFA(.envのTOTPシークレット)
npm run aws:check
powershell -File scripts\deploy.ps1 -Yes # AWSバックエンド
powershell -File scripts\pages.ps1 -Yes # Cloudflare Pages
pages.ps1 は以下を行う:
- AWSスタックの
ApiUrlを取得 - 3アプリをビルドし、
dist/config.jsにAPIベースを注入 - QR付き
launcher.htmlを生成 wrangler pages deployで顧客/店員/Terminalを配置
表示されたURL:
- 起動パネル:
https://<prefix>-customer.pages.dev/launcher - 顧客:
https://<prefix>-customer.pages.dev/ - 店員:
https://<prefix>-staff.pages.dev/?r=reg-01 - Terminal:
https://<prefix>-terminal.pages.dev/
起動・停止(データ保持)
npm run aws:demo:stop
npm run aws:demo:start
npm run aws:demo:status
- stop: Api/Webhook/Syncの同時実行0+同期ルール停止
- start: 同時実行復元+同期ルール再開
- CloudFront/S3は使わない。Pagesの静的配信は停止中も残る
データ操作
npm run aws:data:export
npm run aws:data:import -- -File .\backups\shoptools-dev-....json -Yes
npm run aws:data:reset -- -Yes
DynamoDBへ直接アクセスするため、停止中でも実行可能。resetは全件削除後に店舗/レジを再作成する。
ポーリング
- 顧客カタログ: 10秒
- Terminal: 2秒
- 店員の決済中: 1秒
APIはCORSでPagesドメインからの直接アクセスを許可する(デモは*、本番はPagesドメインに限定)。