ぼくのShopify を公開しました。Shopify ストアのドメインを入れると、そのショップの商品を一覧表示し、検索・絞り込み・詳細確認・元の商品ページへの移動・CSV での一括出力ができる、小さな Web アプリです。

「ぼくの。」のアプリ一覧にも載せていますが、今回は招待制です。誰でもすぐ使える公開ツールではなく、パスワード付きの入口を置いています。検索エンジンにも載せない方針にしています。使う人を絞ったうえで、自分の作業に本当に必要な機能だけを残した、というのがこのアプリの立ち位置です。広く見つけてもらうことより、必要なときに確実に使えることを優先しました。

なぜつくったか

Shopify で動いているショップの商品を、まとめて見たい場面がありました。管理画面に入れる立場なら Admin API やエクスポート機能があります。けれど、自分が触りたいのは「公開されているカタログを、自分の画面で読みやすく並べる」ことに近いケースでした。

たとえば、気になるショップの品揃えを横断して眺めたいとき。特定のキーワードが入った商品だけ抜き出したいとき。あとで表計算ソフトに落として、価格帯やタイトルの傾向をざっと眺めたいとき。どれも「買うための UI」より「調べるための UI」に近いです。

ブラウザのタブを何枚も開きながらスクロールするより、一覧と検索が手元にある方が早い。派手な機能はいらない代わりに、その一連が軽いと助かる、という感覚です。公式の管理画面は強力ですが、権限やセットアップが要るし、自分の閲覧用メモとして持ち歩くには重いこともあります。

もうひとつは、個人開発の練習台としてちょうどよかったことです。外部の公開エンドポイントを Worker 経由で取り、ブラウザの IndexedDB に蓄え、スマホでも使える画面に落とす。サーバー側のデータベースは持たない。「ぼくの。」の他アプリと同じく、静かに使える実用性を優先しました。つくって公開して、自分で使いながら直す。そのループが回しやすい題材でした。

できること

使い方はシンプルです。

  1. shopify.bokuapp.com を開く
  2. 招待用のパスワードで入る
  3. Shopify ストアのドメインを入力する(例: example.com
  4. 商品一覧が表示されたら、検索・フィルタ・詳細・CSV を使う

一覧ではタイトルやベンダーなどで探しやすくしています。詳細では画像や説明の要点を見つつ、元の商品ページへ飛べます。CSV 出力は、手元で並べ替えたり照合したりしたいとき用です。別のショップを見たくなったら、結果画面から切り替えられます。

カート、会員ログイン、購入フロー、ショップへの書き込みはありません。見る・探す・持ち出す(CSV)までが範囲です。Storefront API や Admin API も使っていません。公開カタログとして取れる情報を、読み取り専用で扱う前提です。

画面上には、取得元や利用上の注意も載せています。公開データを便利に見る道具であって、ショップの運営権限を代行するものではない、という線引きをはっきりさせておきたかったためです。便利さの裏で何をしているかが曖昧だと、使う側も不安になると思ったからです。

招待制にした理由

最初は公開ツールとして出す案もありました。ただ、外部ストアへ継続的に問い合わせる仕組みなので、無制限に開くと負荷や意図しない使い方のリスクが上がります。自分と、必要な相手だけが入る形の方が安心です。

そのため入口にパスワードを置き、セッションも時間で切れます。静的なページ自体は配信されますが、商品取得の API は認証付きです。あわせて noindex や robots の制限も入れ、検索結果に載せないようにしています。入口を知っている人向けのアプリ、という位置づけです。

「便利だから広く」より、「使う場面がはっきりしているから狭く」を選びました。ぼくの。の他アプリがブラウザ完結の無料ツールとして開いているのとは、少し違う公開の仕方です。個人開発でも、全部を同じ公開度にしなくてよい、という学びでもありました。いまは招待制のまま、何人かで使ってみてからの公開にしたいのと、管理系のページをつくってからにしようと考えています。

データの流れ

構成は次のとおりです。

ブラウザ → shopify.bokuapp.com(Cloudflare Workers)→ 対象 Shopify ストア

ブラウザから Shopify へ直接取りに行かず、Worker が中継します。CORS やリクエストの扱いをこちらで揃えられるほか、ページ単位のキャッシュも Worker 側に置けます。ブラウザの制約に振り回されにくくなり、取得まわりのルールを一箇所にまとめやすいです。

取得はページ分割です。最初のページが返ってきたらすぐ一覧を出し、続きはバックグラウンドで少し間隔を空けながら取ります。大きなカタログでも、最初の数秒で「見始められる」状態にしたかったためです。上限は設けてあり、極端に巨大なストアは途中まで、という割り切りもあります。全部を完璧に取るより、日常の用途で十分な量を、無理のないペースで取る方を優先しました。

ブラウザ側では IndexedDB(boku-shopify)にショップと商品を保存します。一度取ったデータは、ユーザーが「商品を更新」するまでは手元に残ります。自動で何度も洗い替えすると、見た目は新鮮でも上流への問い合わせが増えます。更新は明示的な操作にしました。ローカルデータを消す操作も用意してあります。端末を変えるとデータは持ち越されません。サーバーにユーザーデータを貯めない代わりに、手元のブラウザが作業場になります。

Worker 側のキャッシュはページ URL 単位で一定時間持ちます。同じショップを短い時間に何度も見ても、毎回フルで上流へ行かないようにしています。キャッシュと手元保存の二段にして、「いま画面に出ているもの」と「上流の最新」を分けて考えられるようにしました。最新性が絶対に必要なら更新ボタンを押せばよく、そうでなければ手元の一覧で十分、という使い分けです。

つくってみて考えたこと

速さより、最初の一手

全部取り終わるまでスピナー、という実装も簡単でした。ただ、商品数が多いと待ち時間が長く感じます。1 ページ目を先に出し、残りは裏で足していく形にしたのは、体感の差が大きかったです。進捗やトーストで「いま取っている」ことが分かるようにもしています。「止まっているのか進んでいるのか」が分からない待ち時間は、実際の秒数以上に長く感じます。

更新はユーザーの意思で

「常に最新」は魅力的ですが、閲覧ツールとしては過剰になりやすいです。手元のスナップショットで十分調べられることも多く、必要になったときだけ洗い替える方が、自分の使い方には合っていました。確認ダイアログでおおよその所要感も出すようにしています。更新中はボタンを無効にして、二重に走らないようにもしています。

やらないことを決める

購入・在庫予約・レコメンド・AI 要約などは、最初から外しました。入れるほど「何のアプリか」がぼやけると感じたからです。一覧・検索・詳細・CSV があれば、当初の目的は満たせます。足りなければ後から足せますが、足りなくても説明できる状態を先に作りたかったです。個人開発では、機能を足すより「これはやらない」と書く方が難しいことがあります。今回はそれが比較的はっきりしていました。

公開カタログであることの意味

扱っているのは、ショップが公開している商品情報です。非公開の管理データや顧客情報には触れません。それでも、便利な閲覧は負荷や利用規約の観点で丁寧さが要ります。招待制、キャッシュ、取得間隔、検索非掲載は、そのためのブレーキです。使う側としても、対象ショップの利用条件や常識的な頻度を守る前提で使ってほしいです。便利な道具ほど、使い方の丁寧さが価値を決めると思っています。

UI で残したもの、削ったもの

結果画面では注意書きを目立たせすぎず、でも無視されない位置に置いています。ホームではブランドを前面に、結果では作業に集中できるようヘッダーを少し変えています。エラー文言は読みやすいように区切る、といった小さなところも、自分で使ってみて直しました。見た目の派手さより、迷わず戻れることと、いま何が起きているかが分かることを優先しています。

自分用と共有用のあいだ

完全に自分だけならローカルスクリプトでも足ります。一方で、画面付きでスマホからも見られる形にしておくと、その場で確認しやすいです。招待制は、その中間——自分用の延長として、必要な相手だけに見せる——ための選択でした。

技術のメモ

フロントエンドは Vite + TypeScript で、React は使っていません。HTML / CSS / 素の TypeScript で画面を組み立てています。スマホでも使えるよう、レイアウトはシンプルにしています。コンポーネントライブラリに頼らない分、画面の状態管理は自分で整理する必要がありますが、MVP の範囲なら十分扱えました。

API は Cloudflare Workers です。デプロイは既存の deploy.sh から Worker + 静的アセットをまとめて出しています。サーバー DB(D1 など)は使わず、永続はブラウザの IndexedDB に寄せました。「自分の端末にデータがある」感覚の方が、このアプリの用途には素直でした。運用コストも小さく保てます。

ゲートやキャッシュ、ページングの細かい定数はアプリ側の README に残しています。運用で触りそうなところだけ、後から自分で追えるようにしてあります。ブログではパスワードの仕組みの細部には触れません。招待された相手には、別途必要な案内を渡す形にしています。

これから

当面は、招待制のまま安定して使えることを優先します。ほしい機能が出てきたら、一覧の見やすさや CSV の列、フィルタの粒度といった「見る・出す」寄りの改善を先に考えたいです。ショップ運営そのものを置き換える方向には広げないつもりです。必要なら、自分用のメモ機能や、複数ショップの切り替えをもう少し滑らかにする、くらいが次の候補です。

うまくいった点は、スコープを狭く保てたことです。失敗というほどではないですが、キャッシュや取得の待ち時間、エラー時の文言などは、公開後に自分で触って直す前提で出しています。最初から完璧な閲覧体験を目指すより、日常で使える最小構成を先に出す方が、この題材には合っていました。

アプリの入口は ぼくのShopify です。一覧は アプリ からも辿れます。「ぼくの。」本体は bokuapp.com です。関連する読みものは、これからも個人開発のメモとして残していきます。

個人の作業用に近いアプリを、招待制という形で外に置くのは初めてに近い感覚でした。広く公開するツールとは別の型として、うまく運用できればと思っています。使ってみて気になる点があれば、お問い合わせ からどうぞ。