B2B ウェブサイト フロントエンド開発
デザインカンプを、購買担当者がオフィスのPCでもスマホでも2.5秒以内に開け、GoogleやAI検索に完全に読み取られ、バックエンドで自分たちでコンテンツを変更できるウェブサイトにします。フロントエンドの実装が良いかどうかは、コードの美しさではなく、3つのことで判断します:速いか、クロールできるか、コンテンツを変更してもレイアウトが崩れないか。
上流はデザイン(デザインカンプ、コンポーネント仕様、ビジュアルシステム、レスポンシブルール)、コピー(コピーの構造がDOM階層を決定)、企画(テクニカルリスト、どのアニメーションを実装し、意図的に実装しないか)。下流はバックエンド(フォーム、CMSフィールド、多言語、デプロイ)、SEO(DOMとパフォーマンスのチェック)、テスト。
参考ファイル
| ファイル | いつ読むか |
|---|---|
references/フロントエンドセルフチェックリスト.md | テストに出す前に1つずつチェック |
P0 / P1の項目は自分で修正してから提出し、テストに残さない。コンテンツとアクセシビリティのセマンティクスに関するチェックは b2b-qa-tester/references/ユーザビリティとアクセシビリティチェック項目.md にあり、両者は重複しません。
この工程であなたが何を言うか、意図は何か、どう対応するか
フロントエンドに対して直接要件を出すことはほとんどなく、多くはPM経由、または受入検査の際に出てきます:
| あなたの言葉 | 背後にある意図 | どう対応するか | 帰属 |
|---|---|---|---|
| 「サイトの表示が遅い」 | 購買担当者の第一印象、あなた自身も感じている | PageSpeedを実行:画像をWebPに変換して200KB以内に圧縮、ヒーロー画像をプリロード、フォントをセルフホスティングして3〜4ウェイトのみ、ファーストビュー外の画像とサードパーティスクリプトを遅延読み込み、未使用のプラグインCSS/JSを削除 | 技術:LCP < 2.5s;ビジネス:1秒遅いと購買担当者の離脱が顕著;目標市場のネットワークが悪い場合はさらに顕著 |
| 「スマホで表示が崩れている」 | あなたや上司が微信で開いた | デザインのブレークポイントごとに各ページをチェック;スペック表に横スクロールと先頭列固定を追加;Bentoをシングルカラムにフォールバック;ボタンを全幅;ナビゲーションを折りたたむが問い合わせボタンは常時表示 | 体験:モバイル比率の高い市場ではスマホが主戦場 |
| 「バックエンドでテキストを変更したら、ページが崩れた」 | 自分たちでメンテナンスしたいが、レイアウトが脆弱 | コンテンツエリアは固定のブロック/フィールド(ACFまたはブロックエディタのカスタムブロック)を使用し、テキストの長さが変化してもグリッドに影響しないようにする;各フィールドに文字数ヒントを追加 | 技術:保守性;ビジネス:バックエンドで変更できなければ毎回コードに手を加える必要があり、すぐに誰も触れなくなる |
| 「もっと派手なアニメーションを追加できる?」 | テンプレートサイトと差別化したい | 企画のテクニカルリストにあるアニメーションのみ実装し、CSS + Intersection Observer または軽量GSAPを使用、prefers-reduced-motion を尊重;WebGL、パーティクル、ページトランジションはリストになければデフォルトで実装しない | 技術:アニメーションスクリプトはパフォーマンスの敵;ビジネス:購買担当者は速さを求めており、派手さは求めてない |
| 「Googleで見つからない」 | 公開後のインデックス登録に対する不安 | フロントエンドでできること:セマンティックタグ、ページごとに1つのH1、タイトルとテキストはDOM内にありcanvas/画像ではない、画像にalt属性、構造化データのプレースホルダー、robots で誤ってブロックしない、サイトマップを生成可能にする | SEO:クローラビリティはフロントエンドの責任;ビジネス:見つからなければ存在しないのと同じ |
| 「日本語/英語/多言語切り替えが必要」 | 複数市場 | WPML / Polylang またはマルチサイトを使用、スイッチャーをナビゲーション右上に配置、hreflangはバックエンド/SEOが設定;未翻訳ページは404ではなく英語にフォールバック | 技術:多言語アーキテクチャは一度間違えると後々の移行コストが非常に高い;SEO:hreflangは多国インデックス登録に影響 |
| 「XXサイトのようなフィルター効果を参考にしたい」 | パラメータで製品を検索したい | タクソノミー + カスタムフィールドでフィルター軸を作成、Ajaxでリストをリフレッシュ(ページ遷移なし)、URLにパラメータを含めて共有・インデックス登録可能に;結果が空の場合はガイダンスを表示 | 体験:購買担当者は素材/仕様で検索;SEO:フィルター結果ページもクロール可能(canonicalに注意) |
| 「フォームの入力項目を減らせない?」 | 購買担当者が面倒がるのを懸念 | フィールドは5〜7項目、必須は Name / Email / Message のみ、残りは任意;製品型番は製品ページから自動入力;スマホでは入力欄16pxでズーム防止;送信ボタンにローディング状態を表示 | 体験:必須項目が1つ増えるごとにコンバージョンが低下;ビジネス:低いハードルでまず連絡先を取得、詳細は後日のコミュニケーションで |
| 「テーマを変えたい/XXテンプレートにしたい」 | 他のサイトがかっこよく見えた | テーマは骨格を決めるもので、ビジュアルはデザインシステムで決まる;テーマを変えるのは作り直しに等しい;どうしても変更する必要がある場合は、テーマのパフォーマンスとブロックサポートを評価してから決定 | 技術:テーマはコンテンツ構造とパフォーマンスの上限を決定づける;ビジネス:やり直しコスト |
実装フロー
1. 技術選定(問い合わせサイトのデフォルトはWordPress)
- WordPress + 軽量テーマ(GeneratePress / Blocksy / Kadence / カスタムブロックテーマ)+ ACF またはネイティブブロックでカスタムフィールド;Elementor / WPBakery などのページビルダーは、そのサイズの大きさとロックインを避けるため使用しない(旧サイトで既に使用中の場合は、評価してから決定)。
- カスタムブロックまたは子テーマ。
- 静的サイトまたはフレームワーク(Astro / Next.js)は、バックエンドでのメンテナンスが不要で、かつ長期的にコードをメンテナンスできる担当者が社内にいる場合のみ使用;それ以外の場合は、後でサイトを管理する同僚にとってWordPressの方が親しみやすい。
2. ビジュアルシステムの構築
デザイントークンをCSS変数として定義:色、フォントサイズスケール、行高、余白、角丸、シャドウ、ブレークポイント。すべてのコンポーネントは変数のみを参照し、後で色やフォントを変更しやすくする。フォントは woff2 でセルフホスティング、font-display: swap、ファーストビューフォントをプリロード、フォールバックフォントスタックで幅を一致させる。
3. コンポーネント実装順序
ナビゲーション(メガメニューとスマホ折りたたみ、問い合わせボタン常時表示を含む)→ ボタンとフォームコントロール → カード(製品カード、事例カード)→ スペック表(ゼブラストライプ、tabular数字、横スクロール、先頭列固定)→ Tabs / Accordion → Counter → Bentoグリッド → CTAエリア → フッター → スティッキー問い合わせバー/WhatsAppフロート → ロゴの無限スクロール → スクロールに合わせたフェードイン。最初に全サイトで再利用可能なものを作り、次に単一ページのものを作る。
4. ページテンプレート
ホームページ、カテゴリページ(フィルター付き)、製品詳細ページ(ギャラリー、スペックタブ、問い合わせフォームプリセット)、About、OEM/プロセス、業界ページ、認証ページ、FAQ(Schemaフレンドリーな構造)、ブログ一覧と記事、Contact、thank-youページ、404。各テンプレートに対応するフィールドグループをバインドし、後でサイトを管理する同僚がバックエンドでフィールドに入力するだけでよく、レイアウトを気にする必要がないようにする。
5. パフォーマンスとクローラビリティのチェック(公開前必須)
- LCP < 2.5s、CLS < 0.1、INP < 200ms、モバイルPageSpeed ≥ 80
- フルスクリーンプリローダーは一切設置しない。 ファーストビューのHTML、コピー、CTAは無条件に即座にレンダリングする。実測に基づき、Awwwards受賞サイト31サイト中、7サイトはローディング画面のせいで実際に開けなかった(うち1サイトは57のリクエストがすべて200でconsoleにエラーがなくても、54%で止まった)。本当にリソースを待つ必要がある場合は、
Promise.race([リソース準備完了, 1.5sタイムアウト])を記述する。詳細はb2b-ui-designer/references/受賞サイト実証.mdを参照。 - 仮想スクロールは使用しない(Lenisなどスクロールを乗っ取る方式)。実測でGAのスクロール深度レポートが偽のデータになる、アンカージャンプと「最後の位置に戻る」が機能しなくなる、プログラム的なスクロールがアニメーションを中断することが確認されている。問い合わせサイトはデータでファネルを判断し、アンカーでナビゲートする。
- 問い合わせフォームにハニーポットフィールドを追加:
<input name="website">にposition:absolute;left:-9999px;width:4px;height:4px;opacity:0+aria-hidden="true"+tabindex="-1"を設定し、送信時に空でなければ破棄。 - 画像:WebP / AVIF、
srcset、ファーストビューはプリロード、それ以外は遅延読み込み、単一画像 ≤ 200KB、ヒーロー ≤ 400KB、製品シーンセクションのメイン画像 ≤ 300KB かつ自動圧縮から除外(短辺 ≥2000px の製品画像を200KBに圧縮するとぼやけるため)。 - フォント:≤ 4ファイル、合計 ≤ 300KB。
- スクリプト:サードパーティスクリプトは遅延読み込み、未使用のCSS/JSを削除、アニメーションライブラリは必要なものだけを読み込む。
- DOM:ページごとに1つのH1、見出しレベルを飛ばさない、テキストはDOM内にある、画像にalt属性、リンクにテキスト、ボタンは
<button>、フォームにはlabel。 - アクセシビリティ:キーボードで到達可能、フォーカスが可視、コントラスト基準を満たす、
prefers-reduced-motionが機能する。 - robots / noindex はテストサイト期間中は有効、公開時には無効にする(公開チェックリストに記載し、バックエンドに引き継ぐ)。
レンダリングレベルでのセルフチェック(上記はコードのチェック、こちらはレンダリングされた画面のチェック;ux-ui-agent-skills / oil-uiを参照):
- 各テンプレートのスクリーンショットを3種類撮って1枚に合成:デスクトップ1440、スマホ390、
prefers-reduced-motion: reduce、保存先_内部/06-站点记录/截图/、ファイル名「テンプレート名-日付」。合成画像は隔離レビューとQAのためのものであり、自分で見て削除するためのものではない。 - 横方向のはみ出し:各スクリーンショットに対応するページで
document.documentElement.scrollWidth > window.innerWidthを実行し、trueなら P1 として記録、自分で修正してから提出。 - タッチターゲット:仕様では 44px だが、実測の最低ラインは 24×24 — クリック可能な要素がレンダリング後に 24×24 より小さい場合は P1 として記録(ux-ui-agent-skills を参照、WCAG 2.2 の最低基準に対応);実測は
getBoundingClientRect()を使用し、デザインカンプは見ない。 - hover / focus 状態のコントラストも実測する。デフォルト状態だけでなく:ボタンホバーで色が薄くなる、リンクフォーカスで色が変わった後でも、テキストと背景色のコントラストが基準を満たしている必要がある。
:root以外にベタ書きの hex があってはならない:すべての色はCSS変数のみを参照し、grep で#[0-9a-fA-F]{3,6}を検索して:rootとダークモードの変数再定義内にのみ出現を許可する。- アイコンに絵文字を使用しない:アイコンはすべて企画で決められたアイコンライブラリ(Lucide / Phosphor / Tabler)を使用、絵文字はOS間でレンダリングが異なり、色変更もできない。
- 自動化部分は
node scripts/check.mjs dist --shotsを実行:3種類のスクリーンショットを撮り、横方向のはみ出しをチェックし、ベタ書きhexと絵文字をスキャン;人手ではチェックできない項目(hover / focus のコントラスト、合成画像のレイアウト確認)のみを補う。 - 画像確認の割り当て:3種類のスクリーンショットのセルフチェックは、自分が撮ったスクリーンショットのみを見る;一度のステップで合計20枚を超えない、割り当てを超えた場合は「1枚ずつ確認せず、メタデータで判断」と記述し、エラーとしない。
隔離レビュー:G3前(ホームページがブラウザでレンダリングできたら、全サイト完成を待たずに実施)、ソースコードを読まず、デザイン決定の説明を読まないサブエージェントを起動し、ホームページの3種類のスクリーンショットと b2b-site-diagnosis/references/会社タイプ別クイックチェックとセルフチェック.md のみを与え、マニュアルに従ってホームページに 1〜10点 を付け、削除可能なテキストをリストアップさせる;点数と削除可能リストを _内部/06-站点记录/フロントエンドセルフチェックリスト.md の末尾に追記する。理由を読んだ人はページを擁護するので、レビュアーは理由を読んでいない人でなければならない。隔離レビューを実施しなかった場合は、セルフチェックリストに「未実施の隔離レビュー」と明記し、空白のままにしてはならない。
6. アニメーション実装ルール
アニメーションは2種類に分けられ、実装原則が異なる。
通常のフェードインタイプ(企画のテクニカルリストにある項目のみ実装):CSS優先、JSは次、ライブラリは最後;ビューポートに入ったら1回だけトリガーし、繰り返さない;持続時間は300〜600ms。
製品シーンセクション(G2の方向性リストで決まった場合のみ、全サイトで最大1セクション):scrub 駆動、可逆、持続時間パラメータなし(状態はスクロール位置で決まる);固定はCSS position: sticky を使用し、ScrollTrigger の pin は使用しない;実装は b2b-ui-designer/references/製品シーンセクション.md に従う。スマホ版ではこのセクションを残すが強度を下げる:filter: blur() を削除、回転角度を半分に、シーン画像を低解像度版に変更;セクション全体を静的なスタックに退化させてはならない — それは全トラフィックの半分がこのサイトの唯一の記憶に残るポイントを見られないことを意味する。
両方に共通:prefers-reduced-motion: reduce の場合はすべてのアニメーションをオフにし、シーンは最初の状態で停止、その他のコンテンツは通常のスタック表示に;スクロール固定ポイントは全サイトで指定された1箇所のみ;Counterはビューポートに入ったら1回トリガー;無限スクロールはCSSアニメーションを使用し、ホバーで一時停止。
なぜこのようにするのか:帰属
- 技術:パフォーマンス、クローラビリティ、保守性。これがフロントエンドの主な帰属であり、ほとんどの決定はここに帰着する。
- 体験:スマホでの使いやすさ、フォームの摩擦の低さ、フィルターのリフレッシュなし。
- ビジネス:速い = 購買担当者が離脱しない;変更可能 = 毎回コードを触る必要がない;クロール可能 = 問い合わせが来る。
- ビジュアル:デザインシステムを忠実に再現し、「ついでに最適化」しない。
例:
| 決定 | 帰属 | 理由 |
|---|---|---|
| ページビルダーを使わずカスタムブロックを使用 | 技術 + ビジネス | サイズが半分になり、バックエンドでテキストを変更してもレイアウトが崩れない |
| スペック表の先頭列を固定、横スクロール | 体験 | スマホでパラメータの見出しが消えない |
| フィルターにURLパラメータを使用 | 体験 + SEO | 共有可能、インデックス登録可能 |
| アニメーションで reduced-motion を尊重 | 体験 + 技術 | アクセシビリティとパフォーマンス |
| フォントをセルフホスティング | 技術 | DNSルックアップを1回削減、国内アクセスでGoogle Fontsの影響を受けない |
| 問い合わせボタンをスマホナビゲーションに常時表示 | ビジネス | どの画面からでもワンクリックで問い合わせ可能 |
出力形式
- テストサイトのURLとバックエンドアカウント(バックエンドに引き渡してデプロイ)
- フィールドとブロックの説明:各テンプレートのフィールド、文字数ヒント、画像サイズ要件(バックエンドマニュアル用)
- パフォーマンスレポート:PageSpeed モバイル/デスクトップのスクリーンショットと数値
- フロントエンドセルフチェックリスト(上記ステップ5の各項目にチェック;末尾に隔離レビューの点数と削除可能テキストリスト、または「未実施の隔離レビュー」と明記)
- 3種類のスクリーンショットの合成画像(1440 / 390 / reduced-motion、テンプレートごとに1枚)
- 未実装/ダウングレード説明:どのデザインをどのブレークポイントでダウングレードしたか、その理由
引き継ぎと合格基準
テストに出す前に:すべてのテンプレートを Chrome / Safari / Edge / Firefox と iOS / Android で確認;セルフチェックリストがすべて合格;バックエンドでテキストを1行変更、画像を1枚変更、製品を1つ追加してもレイアウトが崩れない;フォームのフロントエンドバリデーションとローディング状態が正常(メール到達はバックエンドが担当);アニメーションが reduced-motion でオフになる。
パイプラインインターフェース(独立したエージェントとして実行される場合)
ユーザーへの話し方:技術に疎い人として扱う。3種類のことだけを言う——ここまでやった(1行)、あなたが決めるべきビジネス上の選択(各項目にデフォルト値あり、最大5項目)、次にあなたがすること(1行);実行者、モード、契約、フロー、役割名、ゲート番号、ファイルパスなどの内部用語は出さない。ビジネス上の選択を聞くとき以外は止まらない;ユーザーが「続けて」「開始」と言ったら次のステップに進み、「この工程はこれ以上進められない」とは説明しない。
契約:以下の「入力」にリストされたファイルのみを受け取り、上流の完全な会話は受け取らない;以下の「出力」にリストされたファイルのみを書き、他の人の成果物を変更しない;各工程で質問せず、不足しているものはすべて _内部/待用户决定.md に追記し、PMがまとめて停止ポイントで一度に質問する(1回につき最大5項目);他のエージェントを横断的に呼び出さず、上流にギャップを発見した場合は「フロー戻し」としてレシートを書き、PMが調整する。この工程ではネット検索やサイトクロールは行わない。
入力:デザインの 设计稿/、视觉系统.md、组件规范.md、响应式规则.md;コピーの 文案稿.md(DOM構造と実際のコンテンツ充填用);企画 方案.md のテクニカルリスト;PMの素材ファイル。デザインが確定するまで作業を開始しない。
出力:サイトのソースコード(交付/ ルートディレクトリ、公開後に会社に残るもの)、_内部/06-站点记录/README-技術パート.md(デプロイと実行部分。後でこのサイトを管理する同僚(あなたかもしれない)に向けて書き、「あなた」で記述し、選定プロセス、内部パス、「パイプライン / エージェント / QA / PM」などの内部用語は使用しない;PMがルートの README.md にマージ)、_内部/06-站点记录/ 以下の フィールドとブロックの説明.md(≤ 80行)、パフォーマンスレポート.md(≤ 40行)、フロントエンドセルフチェックリスト.md(チェック済み版、行数制限なし)、ダウングレード説明.md(≤ 30行)、および スクリーンショット/(各テンプレートの1440 / 390 / reduced-motion の3種類合成画像)。
引き継ぎペイロード(欠落は未引き継ぎとみなされ、下流は直接差し戻し可能):
- → バックエンド:
フィールドとブロックの説明.md、各編集可能ブロックに対応するCMSフィールド名、タイプ、必須かどうか、文字数制限。 - → SEO:テストサイトURL、
パフォーマンスレポート.md(LCP / CLS / INP の3つの実測値とテスト条件(デバイス + ネットワーク)を含む)。 - → QA:
フロントエンドセルフチェックリスト.md(チェック済み版、隔離レビュー結果または「未実施の隔離レビュー」を含む)、ダウングレード説明.md(どのアニメーションがどの条件下で何にダウングレードされるか)、スクリーンショット/の3種類合成画像。 - → デザイン:実装不可能またはパフォーマンス上の競合がある具体的な場所 + 2つの代替案(「できません」とは言わない)。
関与範囲:カスタムブロックまたは子テーマ、すべてのテンプレート、フィルター可能なカタログ、スペック表コンポーネント、多言語スイッチャー、Counter / Bento / 無限スクロール、1箇所のスクロール固定ポイント(リストにあれば)。
完了判定:セルフチェックリスト合格、パフォーマンス基準達成、バックエンドでのコンテンツ変更でレイアウトが崩れない。満たされた場合、バックエンド連携とテストをトリガーする。
フロー戻し:デザインが特定のブレークポイントで実装不可能またはパフォーマンス上の競合がある場合 → デザインに代替案を戻す;コピーが長すぎてオーバーフローする場合 → コピーに戻す;素材のサイズが不足している場合 → PMに戻す。
特殊ケースの処理
| ケース | 判断方法 | 対処法 |
|---|---|---|
| 素材やコピーが揃っていないのに作業を開始する必要がある | スケジュールが来ているが、素材リストに空欄がある | 作業を開始してよい、「実際の構造でプレースホルダー」を使用:画像部分は固定比率のプレースホルダーブロック(比率とサイズを明記)、テキスト部分はコピーの文字数分の等幅ダミーテキスト;すべてのプレースホルダー要素に data-placeholder 属性を追加し、テストでそれをスキャン;公開前に必ずクリアする |
| 製品画像がないまま公開する必要がある | 先に公開し、後で画像を追加することを決定 | フィールドが空の場合、ブロック全体を条件付きレンダリングで非表示にし、空のカード、破損画像、露出したaltテキストを表示しない;製品カードに画像がない場合は「型番 + パラメータ」情報カードスタイルに切り替える(デザインに仕様がある場合);ヒーローはタイポグラフィレイアウトにする;画像が準備でき次第アップロードすれば、レイアウトは変わらない |
| 低解像度の画像しかない | 元画像の幅 < 800px | srcset は元画像の幅を超えないサイズのみ生成、コンテナの max-width を元画像の幅に制限、拡大しない;ヒーローに使用しない;ウォーターマーク付きはPMに差し戻す |
| 画像のアスペクト比がバラバラ | 3:4、16:9、1:1 が混在 | すべて aspect-ratio コンテナ + object-fit: cover で切り抜き、主要被写体のずれは object-position で調整;画像のトリミングは要求しない |
| バックエンドでアップロードした画像がレイアウトを壊す | 後でサイトを管理する同僚が自分で画像をアップロードする | フィールドにサイズヒントとアップロードバリデーション(最小幅、アスペクト比)を追加、アップロード時に自動的にWebP ≤ 200KBに圧縮;ブロックは固定コンテナを使用し、画像に合わせて変形しない |
| デザインカンプが特定のブレークポイントで実装不可能、またはパフォーマンスと競合する | Bentoの6グリッドがスマホで長すぎる、ビデオファーストビューが予算超過 | まずデザインの意図に沿った代替案を提示(スマホ版は2列または折りたたみ、ビデオはposterにフォールバック)、ダウングレード説明に記載してデザインに確認を取る;デスクトップ版を勝手に変更しない |
| コピー確定後に英語を変更してオーバーフローする | タイトルが3行になる、ボタンテキストが改行される | フォントサイズを縮小するのではなく、コピーに差し戻す;コンテナに ±20% のテキスト長の余裕を持たせる |
| 旧サイトがページビルダーを使用しており、継続使用を求められた | Elementor / WPBakery に大量のページがある | サイズとロックインを評価;どうしても継続する必要がある場合:未使用のウィジェットを無効化、パフォーマンスオプションを有効化、単一ページのDOMノード数を制限、すべての画像を再圧縮;パフォーマンスレポートに上限を明記;新しいページはブロックを使用 |
| ターゲット市場のネットワークが遅い | 東南アジア、アフリカ、中南米 | ビデオファーストビューをposterにフォールバック、ヒーロー ≤ 250KB、フォントは2ウェイトのみ、アニメーションはフェードインのみ;パフォーマンスは3Gスロットリングで測定し記録 |
| 多言語フォントで文字が欠ける | タイ語、ベトナム語、アラビア語、ロシア語 | フォントスタックにNoto Sansの対応するバリアントを追加;各言語でタイトルの改行とRTLミラーリングを個別にテスト |
| ビジネスメールがない、またはバックエンドが未準備の状態でフォームをテストする必要がある | バックエンドの連携がまだ設定されていない | フォームフロントエンドは一時的にエントリデータベースとローカルメールログに接続し、「一時的」と明記;連携がないフォームをテストに提出しない |
| 旧サイトの特定のページをそのまま残しておくよう求められた | 旧ページにトラフィックがある | コンテンツを新しいテンプレートに移行し、URLはバックエンドが301リダイレクト;新サイト内に旧サイトのHTMLを埋め込まない |
よくある間違い
- 重量級ページビルダーを使用し、ホームページが3MBになる
- タイトルを画像またはcanvasにして、Googleが読み取れない
- Google Fontsから7ウェイトのフォントを引っ張ってくる
- Chromeデスクトップのみでテストする
- バックエンドでテキストを1行変えるとページがずれる
- フィルターを純粋なフロントエンド状態で実装し、URLが変わらず、共有できず、インデックス登録できない
- アニメーションが
prefers-reduced-motionを無視し、すべての画面で動く - テストサイトの noindex を公開時にオフにするのを忘れる(公開チェックリストに記載する必要あり)
- 「ついでに」デザインの余白や色を変更する