Imported from ytyng/mouse-pointer-accuracy (
AGENTS.md). Install upstream withnpx skills add ytyng/mouse-pointer-accuracy. Copyright stays with the author.
AGENTS.md
このファイルは AI コーディングエージェント (Claude Code 等) が参照するためのガイド。
人間向けプロジェクト概要は README.md を参照。
プロジェクト概要
マウスポインタの精度・速度を計測する SvelteKit 製の Web アプリ。
完全クライアントサイド (ssr = false)、データは localStorage に保存。Vercel にデプロイする。
ディレクトリ構造
mouse-pointer-accuracy/
├── AGENTS.md このファイル (CLAUDE.md からシンボリックリンク)
├── CLAUDE.md → AGENTS.md
├── README.md ユーザー向け概要
├── vercel.json Vercel build 設定 (repo root)
├── .gitmodules svelteutils サブモジュール定義
└── frontend/
├── package.json
├── svelte.config.js adapter-vercel
├── vite.config.ts
├── tsconfig.json svelteutils を型チェック対象から除外
├── eslint.config.js prettier 統合
├── .prettierrc pop-three / domainhike 準拠
├── README.md frontend 個別ドキュメント
├── sh/
│ └── build-for-vercel.sh Vercel ビルドスクリプト (PAT で submodule 取得)
└── src/
├── app.html HTML シェル + Bootstrap Icons CDN
├── app.d.ts
├── lib/
│ ├── types.ts TestPattern / TestResult / Target / ClickEvent
│ ├── patterns.ts PATTERNS 定数 + getPattern / listPatterns
│ ├── storage.ts localStorage 読み書きと validation
│ ├── export.ts JSON / TSV / Markdown エクスポート
│ ├── i18n.ts i18nKit (svelteutils ラッパー)
│ └── svelteutils/ git submodule (cyberneura/svelteutils, private)
└── routes/
├── +layout.svelte
├── +layout.ts ssr = false
├── layout.css Tailwind import
├── +page.svelte ホーム (パターン一覧 + 記録一覧)
└── test/[pattern]/+page.svelte 計測ページ
技術スタック
- SvelteKit 2 + Svelte 5 (runes mode 強制)
- TypeScript (strict)
- Tailwind CSS 4
- Bootstrap Icons 1.11 (CDN)
- adapter-vercel (
@sveltejs/adapter-vercel) - pnpm (lockfile 必須、Node
>=22.13.0) - prettier + eslint (フォーマット + lint)
SvelteKit 2 / Svelte 5 (runes) は破壊的変更が多い世代。 API を確認したいときは context7 MCP で最新ドキュメントを取得する。 例:
mcp__context7__resolve-library-id→mcp__context7__get-library-docsライブラリ ID:/sveltejs/svelte,/sveltejs/kit
開発フロー
初回セットアップ
# submodule 取得 (private repo: cyberneura/svelteutils)
git submodule update --init --recursive
cd frontend
pnpm install
日常コマンド
cd frontend
pnpm dev # 開発サーバー (http://localhost:5173)
pnpm build # 本番ビルド (Vercel adapter)
pnpm preview # 本番ビルドをローカル確認
pnpm check # svelte-check (型チェック)
pnpm lint # prettier --check + eslint
pnpm format # prettier --write (整形)
ユニットテスト
現時点でテストフレームワーク (vitest 等) は導入していない。
追加時は context7 MCP で /vitest-dev/vitest の最新ドキュメントを参照する。
開発パターン
i18n (日本語 / 英語)
i18nKit() でロケールを取得し _(ja, en) で文字列を切り替える。
import { i18nKit } from '$lib/i18n';
const { _, lang } = i18nKit();
// _(ja, en) でブラウザ言語に応じた文字列
ブラウザ言語は navigator.language から自動判定、+layout.ts で ssr = false を設定して
ハイドレーション不整合を回避している。
TestPattern
src/lib/patterns.ts の PATTERNS 定数に追加する。name / description /
scoreFormula は { ja, en } 構造、version (number) は仕様変更時に増やす。
'pattern-id': {
id: 'pattern-id',
version: 1,
name: { ja: '名前', en: 'Name' },
description: { ja: '...', en: '...' },
workWidth, workHeight, targetDiameter,
targets: [...],
sequence: [...],
score: (totalMs, missClicks) => ...,
scoreFormula: { ja: '...', en: '...' }
}
TestResult (localStorage 保存形式)
サマリーのみ保存。クリック詳細 (ClickEvent[]) や patternName は保存しない。
表示・エクスポート時に patternId から getPattern(id).name で都度解決する。
patternVersion を保持しているので、後でマスター仕様が上がっても旧記録の取得条件が分かる。
バリデーション
storage.ts の isValidResult で localStorage 読み込み時に型検証する。
新フィールドを追加した場合は isValidResult も更新すること (旧データ互換に注意)。
デプロイ (Vercel)
Vercel 側設定
- Root Directory: デフォルト (repo root)
- Framework Preset: Other
- Node.js Version: 22.13 以上
- Environment Variables:
GITHUB_PAT(cyberneura/svelteutils を Read できる Fine-grained PAT)
仕組み
repo root の vercel.json の buildCommand が frontend/sh/build-for-vercel.sh を呼び、
スクリプトが下記を行う:
GIT_ASKPASS経由でGITHUB_PATを git に渡す (URL に PAT を埋め込まない)git submodule update --init --recursiveで svelteutils を clonefrontend/でpnpm install --frozen-lockfile+pnpm buildfrontend/.vercel/outputを repo root の.vercel/outputに移動 (冪等)
詳細は frontend/sh/build-for-vercel.sh を参照。
ワークフロー (推奨)
コード変更 → PR 作成 → マージまで
- ブランチを切る前に
git statusを確認 - 開発・修正を行う
pnpm check/pnpm lintをパスさせる (push 前必須)/review-stageで staging 内容をセルフレビュー/feature-prで feature ブランチ作成 → コミット → push → PR 作成/wait-copilot-reviewで Copilot レビューを待つ/review-pr-commentでレビューコメントへ対応- レビューコメント対応 → 再 push → 再レビュー依頼 のサイクルを Copilot が
no new commentsを返すまで繰り返す
コミットメッセージ
- 関西弁不可、絵文字不可
- Claude Code 署名 (Co-Authored-By 等) は入れない
- メールは
t@ytyng.com
Prettier / ESLint
- インデントは スペース 2 つ (
useTabs: false) - Single quote /
trailingComma: 'none'/printWidth: 100 prettier-plugin-tailwindcssは 入れない (svelte plugin 3.5.x との互換性問題、 詳細はfrontend/README.mdの「メモ」を参照)
注意事項
svelteutils
src/lib/svelteutils/ は private な git submodule (cyberneura/svelteutils)。
tsconfig.jsonのexcludeで型チェック対象から除外eslint.config.jsのignoresで lint 対象から除外.prettierignoreで format 対象から除外- Vercel ビルド時は
GITHUB_PATで clone
ssr = false
+layout.ts で ssr = false にしている。理由:
- localStorage と navigator.language に依存するため
- i18n がクライアント言語で完結するため
SSR を有効化する変更は慎重に。localStorage 直接参照、window 参照などが各所にある。
Modal a11y
intro / pause modal は +page.svelte (test) のルートレベルに配置 (work area 外)。
role="dialog" / aria-modal / aria-labelledby を付与し、$effect で主要ボタンに
focus を移動している (focus trap までは実装していない)。
