Claude CodeでWebアプリのユーザーアカウント管理を始める
メールアドレスもパスワードも使わないアカウント管理を作る。ユーザー登録の画面もいらない。ランダムな鍵(UUID)をひとつ発行して、それを持っている人を本人とみなす、といういちばん軽い方式。
題材は寄せ書き。名前と一言を書くと全員のページに並び、あとから自分の投稿だけ編集できる。編集できるのは本人だけにしたいので、誰が本人かを見分ける仕組みが要る。それをログインキーで作る。
本記事は Claude Code を例に進めるが、プロンプトを渡す相手はまとめてエージェントと呼ぶ(Codex など他のコーディングエージェントでも、同じプロンプトで進められる)。
前提:Wranglerハンズオンを終えていること(Cloudflare のアカウントと wrangler のログインが済んでいる状態)。D1でデータ共有型Webアプリを作るをやっていると2章から5章が復習になって速いが、やっていなくてもこの記事だけで完結する。前のハンズオンで作ったアプリは使わず、新しく作る。
1. このハンズオンで作るもの
Section titled “1. このハンズオンで作るもの”1-1. 作るもの:ログインキーで入る寄せ書き
Section titled “1-1. 作るもの:ログインキーで入る寄せ書き”完成イメージ。書いた一言が付箋のように並ぶ。前に書いた人はログインキーを入れると自分の分を編集できる
- 名前と一言を入力すると、全員の寄せ書きに並ぶ(1人1投稿、あとから編集可)
- 閲覧は誰でもできる。投稿・編集はログインキーを持っている本人だけ
- 初めて投稿した人に、ログインキーを1つ渡す
- 別の端末でもキーを入れれば、同じ自分として続けられる
- 自分のキーは表示・コピー・保存でき、漏れたら作り直せる
同じ寄せ書きを別の認証方式で作るハンズオンが2つある。アプリは同じで、本人確認のやり方だけが違う。
| 記事 | 本人確認のやり方 |
|---|---|
| この記事(ACC) | ログインキー(UUID)。本人が保管する |
| パスキーで複数ユーザーのアカウントを作る | 指紋・顔・PIN。端末が保管する |
| ソーシャルログインで寄せ書きを作る | Google や GitHub のアカウント。外部サービスに任せる |
認証は、アプリの中身とは別の層にある。だから同じ寄せ書きに3通りの入口を付け替えられる。
1-2. 3つの「名前」を分けて考える
Section titled “1-2. 3つの「名前」を分けて考える”各利用者は、役割の異なる3つの識別子を持つ。
| 識別子 | 役割 | 秘密か |
|---|---|---|
| 内部の主キー | DBが内部で使う不変のID(投稿と本人を結びつける) | 秘密ではない(が、むやみに見せない) |
| 表示名 | 寄せ書きに出る名前。本人が決める | 公開 |
| ログインキー(UUID) | 本人であることの証明。これを持つ人が本人 | 秘密。他人に渡さない |
とくに大事なのは、ログインキーは「表示名」でも「主キー」でもないこと。ログインキーは合言葉(パスワードのランダム版)であって、DBの行を指すIDとは別系統。だから、
- ログインキーはサーバーに生のまま保存しない(ハッシュにして保存する。パスワードと同じ扱い)
- ログインキーはURLやログに出さない(漏れると乗っ取られる)
- ログインキーは漏れたら作り直せる(新しい鍵に差し替えても、表示名や投稿はそのまま残る。主キーと別系統だから)
表示名を変えても投稿は同じ人のものとして残るのも、この分離のおかげ。表示名で紐づけていたら、名前を変えた瞬間に過去の投稿と切り離されてしまう。
1-3. アカウントは「軽い」代わりに弱点もある
Section titled “1-3. アカウントは「軽い」代わりに弱点もある”このログインキー方式は、メールもパスワードも要らず手軽な反面、はっきりした弱点がある。鍵が漏れたら、その人になりすませる(誰が使ったかも分からない)。鍵は本人も暗記できないので、保管も本人任せになる。
だから、この方式が向くのは漏れても致命的でない情報を扱うアカウントに限る(寄せ書きの投稿、アンケートの回答、趣味の記録など)。決済・健康・他人の個人情報のような重い情報を扱うなら、もっと本格的な認証(→ 最後の章で案内)にする。強いのは「推測されない」ことであって「漏れない」ことではない、と覚えておく。
もうひとつの向き不向きがある。どれくらいの頻度で使うサービスか、である。
この方式は「日常的に使うサービス」向き。理由はキーの置き場所にある。ログインキーは端末の localStorage に置くが、これは永続的な保存領域ではなく「そのサイトを使い続けている限り生きるキャッシュ」。iPhone・iPad のブラウザ(Safari も Chrome も中身は同じ WebKit)と Mac の Safari は、そのサイトを7日ほど開かないでいると中身を消す(開けばカウンタはリセットされる)。Windows・Android のブラウザや Mac の Chrome では消えない。
つまり週に何度も開くサービスならキーは実質消えないが、年に数回しか使わないサービスでは、次に開いたときにはまず消えている。そのとき頼れるのは本人が控えたキーだけ。ところが「キーをメールに送っておいてください」と案内して実際に送る人は少なく、送った人も数か月後にはどこに送ったか忘れている。この方式には復旧手段が無いので、そこで行き止まりになる。設計としてできるのは保存を促すことまでで、それ以上は担保できない。
年に数回のアクセスが前提のサービスなら、この方式は選ばない。メールにログインリンクを送る方式やソーシャルログインのように、本人確認の媒体をアプリの外に持つやり方にする。逆に言えば、毎日・毎週開いてもらえるサービスであれば、この軽さが利点になる。
1-4. 全体の流れ
Section titled “1-4. 全体の流れ”- 事前準備:ベース名と作るものの仕様をエージェントに覚えさせる
- データベース:D1 を作り、アカウントと寄せ書きのスキーマを設計する
- バックエンド:キーの発行と照合、寄せ書きの読み書き
- フロントエンド:キーの表示・保存・入力・作り直し
- デプロイと動作確認:別端末で同じ自分になれるか、鍵を作り直せるか
- セキュリティの要点と、次のステップ
ブラウザでの手作業はデプロイの確認くらいで、実装はすべてエージェントに依頼できる。
2章から5章は D1 のハンズオンとほぼ同じ手順。D1でデータ共有型Webアプリを作るを終えている人は流し読みでよい。違うのは4章のスキーマ(アカウントを持つ)だけ。
2. 事前準備
Section titled “2. 事前準備”2-1. ベース名を決める
Section titled “2-1. ベース名を決める”このアプリでは、作業フォルダ・D1データベース・Pages プロジェクトに名前を付ける。これらの名前は 自分のアカウント内で重複できない(Pages プロジェクト名だけは Cloudflare 全体で一意)。前に作ったものと同じ名前を使うと、そこで衝突してうまくいかない。
そこで最初に、自分だけの ベース名 を1つ決めておく。
- 例:
yosegaki-key、yosegaki-yto(イニシャル)、yosegaki-0819(日付)など - 短く・英小文字と数字とハイフンだけにしておくと、そのまま全部の名前に使える
ベース名はそのまま 公開URL(https://<ベース名>.pages.dev)になる。すでに使われているとベース名の後ろにランダムな英数3文字が付くので、URL をきれいにしたい場合はブラウザで https://候補名.pages.dev を開いて空きを確認しておくとよい。「このサイトにアクセスできません」と表示されれば空き。
この記事では、決めたベース名を <ベース名>、D1データベース名を <ベース名>-db と表記する。
2-2. 作業フォルダを準備
Section titled “2-2. 作業フォルダを準備”Finder で ~/claude フォルダ(なければ作る)の中に、ベース名の作業フォルダを作る(例: yosegaki-key)。
2-3. Claude Codeを起動
Section titled “2-3. Claude Codeを起動”Claudeデスクトップアプリを起動。
Code(Claude Code)を選択 → 新規 をクリック → 作業フォルダを指定(例: ~/claude/yosegaki-key)
セッションを始める前に、画面左下のモード選択を 編集を受け入れる にしておく(自動 にしない)。
セッションを開始したら、最初にベース名をエージェントに覚えさせる。次のプロンプトは、先頭の yosegaki-key(1箇所だけ)を自分のベース名に置き換えて渡す。
このプロジェクトのベース名は yosegaki-key です。これを CLAUDE.md に記録してください。- アプリ名・プロジェクト名 = ベース名- D1データベース名 = ベース名のうしろに -db を付けた名前これ以降、私のプロンプトの <ベース名> はベース名に、<D1データベース> は「ベース名-db」に読み替えて作業してください。以降のステップでは <ベース名> や <D1データベース> と書いたプロンプトをそのまま渡せば、エージェントが自分の名前に展開してくれる。なお、エージェントが読み込む設定ファイルは Claude Code では CLAUDE.md、Codex では AGENTS.md。
2-4. 作るものをエージェントに覚えさせる
Section titled “2-4. 作るものをエージェントに覚えさせる”アプリの仕様を、先に CLAUDE.md に書いてしまう。 以降のプロンプトでは「仕様のとおりに」と参照するだけでよくなる。
これから作るアプリの仕様を CLAUDE.md に書いてください。
## 作るもの:みんなの寄せ書き- 名前と一言を書くと、みんなの寄せ書きに並ぶ- 1人1件。あとから自分の分だけ編集できる- 表示名は本人が決める。あとから変えられる- 閲覧は誰でもできる。書き込みと編集は本人だけ- 本人確認はログインキーで行う。メールアドレスもパスワードも使わない- 画面は上から「みんなの寄せ書き」の一覧、「あなたの寄せ書き」の入力欄、の順に並べる- 寄せ書きは付箋のようなカードを並べ、本文の下に右寄せで「— 名前」を出すこの仕様は3つの記事で共通。違うのは「本人確認を何でやるか」の1行だけで、アプリそのものは同じ。同じ寄せ書きを、パスキーとソーシャルログインで作るハンズオンもある。
なぜ先に書くのか。仕様を毎回のプロンプトに書くと、作りたいものの話と、どう作るかの話が混ざる。スキーマを作るときも、APIを作るときも、画面を作るときも「1人1件で、あとから編集できて…」と繰り返すことになり、どこまでが自分のアプリの都合で、どこからが認証の作法なのか分からなくなる。
先に1回書いておけば、以降のプロンプトは「どう作るか」だけになる。 そして自分のアプリを作るときは、ここを差し替えるだけでよい。この記事のプロンプトのうち、書き換えるのは仕様の部分だけで、ログインキーまわりの指示はそのまま使える。
仕様が長くなってきたら、別のファイル(
SPEC.mdなど)に移してCLAUDE.mdから指す形にする。CLAUDE.mdは「毎回読ませたいこと」を置く場所なので、増えすぎると毎回の読み込みが重くなる(→ 作業メモをリポジトリに残す)。今回の仕様は数行なのでCLAUDE.mdに直接書く。
2-5. Wranglerログイン状態の確認
Section titled “2-5. Wranglerログイン状態の確認”npx wrangler whoamiアカウント名やメールアドレスが表示されればOK。表示されない場合はWranglerハンズオンの1章を参照してインストール・ログインする。
3. 【データベース】D1データベースを作成
Section titled “3. 【データベース】D1データベースを作成”D1データベース <D1データベース> を作って作成すると database_id が表示される。これは5章の wrangler.jsonc で使う。
Database ID(
database_id):データベースの識別子。仮に外部に漏れても、API Tokenがなければ操作できないため問題なし。
4. 【データベース】スキーマ設計とマイグレーションファイル
Section titled “4. 【データベース】スキーマ設計とマイグレーションファイル”1-2 で整理した3つの識別子を、そのままテーブルの形にする。
まず設計だけ相談する。
CLAUDE.md に書いた仕様のとおりに、データ設計を考えたい。本人確認のところだけ、次のようにしてください。- 利用者ごとにUUIDのログインキーを発行する。- サーバーには生のキーを保存せず、SHA-256のハッシュだけを保存する(列は key_hash、UNIQUEにする)。- 投稿は、表示名ではなく内部の主キーで本人に紐づける。まず設計だけ見せて。いきなり作らないで。設計に納得したら、マイグレーションファイルを作ってもらう。
その設計で、マイグレーションファイルを作成して。ファイルは migrations/0001_init.sql に保存して。
key_hashにはUNIQUE制約を付ける(同じ鍵が2アカウントに割り当たらないように)。生のキーではなくハッシュを保存するのは、DBが漏れても生の鍵は出ないようにするため。パスワードをハッシュで保存するのと同じ考え方(ただしログインキーは長いランダム値なので、パスワードのような「遅いハッシュ+ソルト」までは要らず、SHA-256で足りる。この理屈をユーザーが決めるパスワードに一般化しないこと)。
投稿を表示名で紐づけないのが大事なところ。表示名は本人が変えられるので、それを手がかりにすると名前を変えた瞬間に過去の投稿と切り離される。内部の主キーで結んでおけば、名前が変わっても投稿は本人のものであり続ける。
5. wrangler.jsonc の作成
Section titled “5. wrangler.jsonc の作成”Pages プロジェクトの設定と、用意した D1 データベースとの結びつけ(バインディング)をまとめて行う設定ファイル。
wrangler.jsonc を作って。Pages プロジェクト名は <ベース名>、公開対象フォルダは public。D1データベース <D1データベース> を binding 名 DB で使う。バインディング(binding):プログラムからD1データベースを呼び出すときの名前。
"binding": "DB"としたので、APIのコードからはenv.DBでデータベースにアクセスできる。
6. 【バックエンド】キーの発行と照合、寄せ書きAPI
Section titled “6. 【バックエンド】キーの発行と照合、寄せ書きAPI”やることは4つ。
- 一覧:寄せ書きの一覧を返す。これは誰でも見られる(キーは要らない)。
- 発行:ログインキーを持たない人が初めて投稿したら、新しいアカウントを作り、UUIDのキーを払い出す。生のキーはこのときの応答で一度だけ返す(サーバーには以後ハッシュしか残らない)。
- 照合:キーを持っている人の操作では、ヘッダで送られてきたキーをハッシュ照合し、どの利用者かを特定する。
- 本人だけの編集:自分の投稿と表示名だけ編集できる。
エージェントに依頼する。
CLAUDE.md の仕様のとおりに、Pages Functions で寄せ書きのAPIを作って。functions/api/ に置く。本人確認のところは、次のようにしてください。- リクエストのログインキーは、URLのクエリではなく HTTP ヘッダ x-app-key で受け取る。- ヘッダにキーが無ければ、新しいアカウントを作ってUUIDのログインキーを払い出す。生成した生のキーは、その応答で一度だけ返す(サーバーにはハッシュだけ保存する)。- ヘッダにキーがあれば、SHA-256でハッシュ化して本人を照合する。- 他人の投稿を編集しようとしたときは、権限エラーではなく「見つからない」(404) を返す。- ログインキーをレスポンスやログやURLに残さない(発行時に一度返すのを除く)。なぜヘッダで受けるのか。キーを
?key=xxxのようにURLのクエリに載せると、サーバーやCDNのアクセスログにキーがそのまま残る(キーは合言葉なので、ログ経由で漏れると乗っ取られる)。HTTPヘッダに載せればURLには出ないので、この漏れを防げる。
キーの照合:送られてきたキーをハッシュ化して、
key_hashが一致する行を探すだけ。生のキーはDBに無いので、DBが漏れても照合の材料(ハッシュ)しか出ない。
他人の投稿に 404 を返す理由:「権限がありません」と答えると、そこに何かがあること自体が分かってしまう。「見つからない」と答えれば、存在を探る手がかりにならない。
7. 【フロントエンド】キーの表示・保存・入力
Section titled “7. 【フロントエンド】キーの表示・保存・入力”利用者から見た動きを作る。ポイントは、発行されたキーを確実に本人へ渡し、次からも使えるようにすること。
7-1. キーの保存とログイン
Section titled “7-1. キーの保存とログイン”CLAUDE.md の仕様のとおりに、寄せ書きの画面を作って。public/ に置く。ログインキーの扱いは、次のようにしてください。- ログインキーは localStorage に保存し、API呼び出しでは毎回 x-app-key ヘッダに載せて送る。- 初めて投稿してキーが発行されたら、「キーを保存」する画面を1回だけ挟む。要件は下記。- すでにキーを持っている人が別の端末で続けられるよう、「ログインキーを入力」する欄も用意する。- 専用リンク(別端末で開くと自動でログインするURL)は #key=(URLのフラグメント)で作る。読み込み時に location.hash からキーを読んで localStorage に保存し、すぐ hash を消す。?key=(クエリ)は使わない。
「キーを保存」画面の要件:- コピー・専用リンクのコピー・メール(mailto)で保存できるボタンを並べる。- 「このキーを無くすと二度と同じ自分に戻れない」旨を明記する。- パスワードマネージャにも拾わせるため、保存はフォーム(form)のsubmitで行い、ユーザー名欄(表示名、readonlyでよい)とパスワード欄(キー、autocomplete="current-password")を持つ。ただし保存の主役はコピー・メールなど手動の手段にする(ブラウザによってはパスワードマネージャの保存提案が出ないため)。なぜフォームにするのか:キーの保存を「コピーして自分でどこかに貼る」だけに頼ると、実際に保存する人は少ない。そこでパスワード欄の見た目にしておくと、利用者が意識していなくても iCloud キーチェーンや Chrome の保存機能が拾ってくれることがある。狙いはパスワードマネージャを使ってもらうことではなく、内蔵の保存機能に黙って拾わせること。意識して 1Password などを使っている人より、こちらのほうが多い。ただしログインキーは「ユーザー名+パスワード」の形を装っているだけなので、拾ってくれないブラウザもある。確実ではないので、コピー・メールの導線は残しておく。
キーはどこで見られる? ログイン中の端末は、キーを localStorage に持っている。だから「自分のキーを表示・コピー」する画面は、その localStorage から読んで表示するだけでよく、サーバーに問い合わせる必要はない(サーバーはハッシュしか持っていない)。表示のためにサーバーへキーを取りに行かないこと。
保存を強く促す理由:このキーが唯一の本人確認手段。無くして、かつどの端末にも残っていないと、その人には二度と戻れない(メールのような復旧手段が無い)。だから発行直後の「キーを保存」ステップを飛ばさせない。とくに localStorage は永続的な保存ではないという前提が大事。iPhone・iPad のブラウザ(Safari も Chrome も中身は同じ WebKit)と Mac の Safari は、そのサイトをしばらく(7日ほど)開かないでいると localStorage を自動で消すことがある。だから「ログインしたまま/ブラウザに入れっぱなしだから大丈夫」は通用しない。キーは必ず別の場所(自分宛てメール・パスワードマネージャなど)にも保存してもらう。ただし、これは促せるだけで守らせることはできない(→ 1-3)。
7-2. キーの作り直し(再発行)
Section titled “7-2. キーの作り直し(再発行)”鍵が漏れたかもしれないときに、本人が新しい鍵に差し替えられるようにする。
ログイン中の利用者が、自分のログインキーを作り直せるようにして。- 新しいUUIDを生成してハッシュを保存し直し、古いキーは無効にする(表示名や投稿はそのまま残す)。- 新しいキーは発行時に一度だけ表示し、各端末で入れ直してもらう。- 「作り直すと、古いキーを保存した端末は入れなくなる」旨を確認してから実行する。「作り直し」と「紛失時の復旧」は別物。作り直し(ローテーション)は、いまログインしている本人が「漏れたかも」と思ったときに、新しい鍵へ差し替える操作。一方、鍵を無くして締め出された状態からの復旧はできない(本人だと確かめる手段が無いため)。ここがこの軽量方式の限界。作り直せるのは表示名や投稿が主キーと別系統だから(鍵の列を書き換えるだけで、データは無傷)。
8. ローカルで動作確認する
Section titled “8. ローカルで動作確認する”公開する前に、手元で動かして確認しておく。
本番DBではなくローカルのD1で動作確認したい。ローカルのD1にマイグレーションを適用(migrations apply)してから、ローカルサーバーを起動して「ローカルで確認したい」とだけ伝えると、マイグレーションのローカル適用が抜けてテーブルが無いまま起動することがある。「ローカルのD1に適用してから」まで含めると確実。
起動したら指定されたURL(http://localhost:8788 など)をブラウザで開いて動作確認する。
9. デプロイ
Section titled “9. デプロイ”本番DBにマイグレーションを適用(migrations apply)してから、wrangler で Cloudflare に直接デプロイして「デプロイして」とだけ伝えると本番D1へのマイグレーション適用が抜けて、画面は出るのに投稿でDBエラーになることがある。「本番DBにマイグレーションを適用」まで含めると確実。
ターミナルでやる場合:
Terminal window npx wrangler d1 migrations apply yosegaki-key-db --remotenpx wrangler pages deploy(
yosegaki-keyは自分のベース名に読み替え。初回は Pages プロジェクト名やブランチを聞かれる)
GitHub に置いて push で自動デプロイする形にしたい場合は、Git連携のハンズオンと同じ手順で足せる。
10. 動作確認
Section titled “10. 動作確認”デプロイできたら、本番URLで次を確認する。
- 初めて投稿すると寄せ書きに並び、「キーを保存」画面が出る。キーをコピーしておく。
- 別の端末(またはシークレットウィンドウ)で開くと、最初は別人(キーが無い)。「ログインキーを入力」に、さっきのキーを貼ると、同じ自分として自分の投稿を編集できる。
- 専用リンク(
#key=…)を別端末で開くと、自動で同じ自分になる。URLからキーが消えることも確認する。 - 表示名を変えても、投稿が自分のものとして残る。
- キーを作り直すと、古いキーでは入れなくなり、新しいキーでは同じ自分のまま続けられる。
- ブラウザの開発者ツールの Network で、投稿リクエストのURLにキーが載っていない(ヘッダに載っている)ことを確認する。
11. セキュリティの要点
Section titled “11. セキュリティの要点”- 生のキーはサーバーに保存しない(ハッシュのみ)。DBが漏れても、生の鍵は出ない。
- キーはヘッダで送る。URL(クエリ)に載せない。載せるとサーバー/CDNのログに残る。専用リンクは
#key=(フラグメント=サーバーに送られない)で。 - キーをログ・エラー画面・レスポンスに出さない(発行時に一度返すのを除く)。
- 他人のデータは「無い」ように扱う。「このキーではアクセスできない」ではなく「見つからない(404)」を返すと、存在を探られにくい。
- 強いのは推測耐性であって漏洩耐性ではない。UUID(v4)のランダムな部分は122ビット(約 5.3×10³⁶ 通り)あり、仮に毎秒1兆回のペースで総当たりしても全部試すのに宇宙年齢の約1200万倍かかる。つまり当てる(推測する)のは事実上不可能。漏れても致命的でない情報に限って使う。
12. ここから広げる
Section titled “12. ここから広げる”今回はアカウントの土台(本人を見分けて、持ち運べるようにする)まで。ここまでできると、次のような発展が同じ仕組みで作れる。
- マイページ:自分の投稿だけを一覧できる画面。投稿を本人に紐づけてあるので、「自分のキーで、自分の投稿を返すAPI」を足すだけ。
- アイコン・プロフィール:表示名のほかに、本人が決めるアイコンや自己紹介を持たせる。
- 1人1投稿をやめる:何度でも投稿できるようにして、それぞれを本人だけが編集・削除できるようにする。掲示板やチャットに近づく。
そして、この軽量アカウントの弱点(漏れたら終わり/復旧できない/たまにしか使わないサービスには向かない)が気になるなら、次のステップがある。
- ソーシャルログイン(Google・GitHub など):ログインを外部サービスに任せる。パスワードもキーの保管も要らず、「◯◯でログイン」はユーザーにも身近。→ ソーシャルログインで寄せ書きを作る
- パスキー(+リカバリコード):端末の指紋・顔・PINでログインするパスワードレス認証。漏れる合言葉が無く、フィッシングにも強い。復旧手段(リカバリコード)も持てる。→ パスキーで複数ユーザーのアカウントを作る
- 管理者だけを締め出したい(利用者の識別は要らない)なら、Basic認証で管理画面を守るやCloudflare Accessのほうが手軽。
「誰でも書ける寄せ書き」から「自分のアカウントで続けられるアプリ」へ。
- ログインキーは「アカウントそのもの」。表示名(見せる名前)や内部の主キー(DBのID)とは別物、と最後まで混同しない。
- キーが漏れたら作り直し(ローテーション)で差し替える。ただし攻撃者も同じキーで作り直せてしまう(先にやられると締め出される)ので、非センシティブ前提での割り切り。
- どの端末にもキーが残っておらず、本人も控えていない場合、その人には戻れない。しかも localStorage は放置で消えることがある(iPhone・iPad の全ブラウザと Mac の Safari)ので、「ログインしたままにしておけば安心」は当てにできない。だから発行時に必ずキーを別の場所(自分宛てメール等)に控えることを利用者に促す。
- localStorage はオリジン単位。プレビュー用のデプロイURLは本番と別オリジンなので、キーも別扱いになる。案内は本番URLで。
- 専用リンク(
#key=)はページを新しく開いたときだけ有効。すでにそのサイトを開いているタブで同じリンクを開いても、URL の#から後ろが変わるだけでページが読み込み直されないので、キーが取り込まれない。別の端末で開く本来の使い方では起きないが、動作確認のときに引っかかる(一度リロードすれば取り込まれる)。
