小売の棚前作業を想定した、JANコードのスキャン・整理・出力をスマートフォンで行うオフライン対応PWAです。
カメラでEAN-8 / EAN-13を読み取り、商品名・個数・定価・売価をブラウザのIndexedDBへ保存します。保存したデータは横断検索し、CSV / TSVとして表計算へ渡したり、JANバーコードを画面上にまとめて生成したりできます。
スクリーンショットは、GS1 Japanがインストアマーキング用と説明する
02開始の店内デモ用コードと合成データで構成し、実在の商品・店舗情報は使用していません。
- 棚前で確認したJANを別のメモへ転記する手間を減らしたい
- 同じ商品の連続読取りを個数として数えたい
- JANの先頭0を表計算へ渡すときに失いにくくしたい
- 専用端末やバックエンドを用意せず、スマートフォンだけで作業を始めたい
- 古い作業リストを見分け、用途ごとに整理したい
| 作業 | JAN Syncでできること |
|---|---|
| 棚前での収集 | 背面カメラによるEAN-8 / EAN-13の単発・連続スキャン |
| 棚卸し補助 | 同一JANを個数へ加算し、短時間の重複読取りを抑制 |
| 商品情報の整理 | 名前・個数・定価・売価をリスト単位で保存・編集 |
| 検索 | すべてのリストをJAN・名前で横断検索 |
| データ受け渡し | 検索結果をCSV / TSVでダウンロード |
| バーコード確認 | 履歴または手入力したJANをCanvas上に一括生成 |
| PWA | アプリシェルのキャッシュ、ホーム画面への追加、更新通知 |
- 棚卸しモード — 同じ商品を繰り返し読んだとき、行を増やさず個数へ反映
- 重複読取り防止 — 50〜2,000msの範囲で待ち時間を調整可能
- 読取フィードバック — 音とバイブレーションをそれぞれ4段階で設定
- 端末機能への配慮 — 非対応端末ではバイブ設定やライト操作を表示しない
- 表計算向け出力 — JANの数値化を抑えやすい形式、TSV、個数の行展開を用意
- 古いリストの可視化 — 作成から7日を超えたリストに警告を表示
出力はUTF-8(BOM付き)で、検索欄が空なら全件、検索中なら表示中の結果だけを対象にします。
| プリセット | 出力列 |
|---|---|
| すべて | JAN、名前、個数、リスト、定価(税抜)、定価(税込)、売価(税抜)、売価(税込)、スキャン日時 |
| JANと名前 | JAN、名前 |
| JANのみ | JAN |
数字だけのJANには先頭タブを付け、表計算ソフトによる数値化と先頭0の消失を起こりにくくしています。ソフトや取込方法によるため、完全な保証ではありません。
CSV / TSVは出力専用です。JAN Syncへ再取込する機能はなく、アプリのリストや設定を復元するバックアップにはなりません。
- スキャンデータは外部サーバーへ自動アップロードせず、現在のブラウザ・オリジンのIndexedDBに保存します。
- 初回アクセスとアプリ更新には通信が必要です。読み込み後はService Workerがキャッシュしたアプリシェルを利用できます。
- 端末の紛失・変更、ブラウザのサイトデータ削除、ストレージ消去などで保存データは失われます。サーバー同期や復元機能はありません。
- Google / Yahoo検索ボタンを押すと、対象のJANと商品名が検索サービスへ送られます。
- Cloudflare Pagesはアプリの静的ファイルをHTTPS配信します。
- 対応コードはEAN-8 / EAN-13です。QRコード、UPCなどは対象外です。
- 手入力時は8桁または13桁の数字かだけを確認し、JANのチェックデジットは検証しません。
- バーコード生成は画面上のCanvas表示です。専用の印刷レイアウト、PDF / 画像保存、ラベルプリンター連携はありません。
- 税込表示は税率10%固定・四捨五入です。軽減税率や個別税率には対応しません。
- データはブラウザごと・端末ごとに分かれます。アカウント、共有、複数端末同期はありません。
- カメラ、ライト、バイブレーション、クリップボードの対応状況はブラウザと端末に依存します。カメラ利用にはHTTPSなどのsecure contextが必要です。
JAN Syncは棚前作業を想定して設計し、読取音などを実機テスト後に調整した公開デモです。v1.0.0からv1.2.1まで機能追加と修正を重ねています。
現時点の公開情報は、実店舗への導入社数・利用者数・継続運用期間・業務改善効果を示すものではありません。
graph TD
Hosting["Cloudflare Pages\nHTTPSによる静的配信"] --> Browser["ブラウザ / PWA"]
SW["Service Worker\nアプリシェルのキャッシュ"] --> Browser
Browser --> Scanner["zxing-wasm\nEAN-8 / EAN-13読取り"]
Browser --> Generator["bwip-js\nCanvasへのバーコード生成"]
Browser --> DB["IndexedDB\nlists / scans"]
Browser --> Export["CSV / TSV\nブラウザ内で生成"]
バックエンドAPIやユーザー認証はありません。Cloudflare Pagesがアプリを配信し、スキャンデータの保存・検索・出力はブラウザ内で処理します。
| 領域 | 技術 |
|---|---|
| UI | SolidJS、TypeScript、Tailwind CSS v4 |
| Build | Vite |
| JAN読取り | zxing-wasm |
| バーコード生成 | bwip-js |
| 保存 | IndexedDB(idb) |
| PWA | vite-plugin-pwa、Workbox |
| Hosting | Cloudflare Pages |
| Test | Vitest |
Node.js 24とpnpm 11を使用します。packageManagerとlockfileに合わせて依存をインストールしてください。
corepack enable
pnpm install --frozen-lockfile
pnpm devpnpm devはデスクトップでのUI確認用です。スマートフォンのカメラを試す場合は、HTTPSで配信された環境を使用してください。
pnpm test
pnpm test:coverage
pnpm buildIndexedDB: jan-sync (version 2)
├── lists { id, name, createdAt }
└── scans { id, listId, jan, name, quantity?, retailPrice?, salePrice?, scannedAt }
操作方法は日本語の導入ガイドでも確認できます。
