frontend-architecture について
Exceptionless.Web の画面を扱うコーディングエージェント向けのフロントエンド開発スキルです。新規 UI では Svelte 5 を標準とし、旧 Angular アプリの変更条件や、設計・アクセシビリティ・テストの規約を示します。
主な機能
- 01新規 UI は Svelte 5 を標準化
- 02旧 Angular の変更範囲を明示
- 03機能単位でコードを構成
- 04TypeScript とコンポーネントの規約
- 05アクセシビリティとテストを網羅
活用シーン
- 01Exceptionless.Web にページやコンポーネントを追加
- 02変更対象を Svelte と Angular から選択
- 03フロントエンドコードの一貫性を確認
- 04UI 変更のテストや検証方法を選定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ exceptionless/ exceptionless --skill frontend-architectureインストール後、Claude Code で/frontend-architectureを入力して読み込まれたか確認します。
詳細
フロントエンドアーキテクチャ
Exceptionless.Web には現在、2 つのフロントエンドコードベースがあります。
src/Exceptionless.Web/ClientApp.angularは従来の Angular UI で、現在のサイトの大部分を引き続き担っています。メンテナンス専用として扱ってください。ユーザーから Angular または従来の UI の変更を明示的に依頼された場合を除き、編集したり、ルートを追加したり、そこからパターンを移植したりしないでください。主なフォルダーはapp/、components/、less/、img/、lang/、grunt/です。src/Exceptionless.Web/ClientAppは Svelte 5 アプリで、今後の新しいフロントエンド UI 開発の対象です。
標準では Svelte を使用してください。リクエストに「frontend」、「UI」、「page」、「component」、「form」、「route」とあり、Angular に明示的に言及していない場合は、src/Exceptionless.Web/ClientApp で作業してください。
ユーザーから Angular、従来の UI、またはその画面にしか存在しないバグの修正を明示的に依頼された場合に限り、ClientApp.angular で作業してください。
ディレクトリ構成
src/
├── lib/
│ ├── features/ # Feature slices (vertical organization)
│ │ ├── auth/
│ │ │ ├── api.svelte.ts
│ │ │ ├── models.ts
│ │ │ ├── schemas.ts
│ │ │ └── validators.ts
│ │ ├── organizations/
│ │ ├── projects/
│ │ ├── events/
│ │ └── shared/ # Cross-feature shared code
│ ├── generated/ # API-generated types
│ └── utils/ # Utility functions
├── routes/
│ ├── (app)/ # Authenticated app routes
│ ├── (auth)/ # Authentication routes
│ ├── status/ # Public status route
│ ├── +layout.svelte
│ └── routes.svelte.ts
└── app.html
機能スライス
機能ごとに整理し、新しいファイルを追加する前に、最も近い既存の機能構成に合わせてください。
features/organizations/
├── api.svelte.ts # TanStack Query hooks (see tanstack-query skill)
├── models.ts # Feature-local types and generated type aliases
├── schemas.ts # Zod validation schemas
├── options.ts # Dropdown options, enums
└── components/
└── *.svelte
フォーマッターコンポーネント(必ず使用)
コンポーネントが存在する場合は、独自のフォーマット関数ではなくフォーマッターコンポーネントを使用してください。
| コンポーネント | パス | 用途 |
|---|---|---|
<DateTime> | $comp/formatters/date-time.svelte | 日付と時刻の表示 |
<TimeAgo> | $comp/formatters/time-ago.svelte | 相対時間(「3 時間前」) |
<Duration> | $comp/formatters/duration.svelte | 時間の長さ |
<Bytes> | $comp/formatters/bytes.svelte | ファイルサイズ、メモリ |
<Number> | $comp/formatters/number.svelte | ロケールに応じた数値の表示 |
<NumberCompact> | $comp/formatters/number-compact.svelte | コンパクトな数値表示 |
<Boolean> | $comp/formatters/boolean.svelte | 真偽値の表示 |
<Currency> | $comp/formatters/currency.svelte | 金額 |
<Percentage> | $comp/formatters/percentage.svelte | パーセント値 |
<DateMath> | $comp/formatters/date-math.svelte | Elasticsearch の日付演算式 |
<DateTime value={event.date} />
<Bytes value={event.size} />
{formatDateTime(event.date)}
{new Date(event.date).toLocaleString()}
インポートエイリアス
import { Button } from "$comp/ui/button"; // shared components
import { User } from "$features/users/models"; // $lib/features
import { cn } from "$lib/utils"; // $lib
プロジェクトの Svelte ルール
- 計算状態には
$derivedを、副作用には$effectを優先して使用してください。 - リアクティブなループを避ける必要がある場合は、
$effect内でuntrack()を使用してください。 - ルートのクエリパラメーターのバインディングには、場当たり的な URL 解析ではなく、
$shared/query-paramsのcreateQueryParametersを優先して使用してください。 - 新しいコードでは
onclickやoninputなどの Svelte 5 のイベント属性を使用し、従来のon:click構文は使用しないでください。 - 新しいコンポーネントでは、スロットの代わりにスニペット(
{#snippet children(...)}/{@render children?.()})を使用してください。 - 条件付きクラスには配列形式の class またはローカルの
cn()ヘルパーを使用してください。
一貫性ルール
新しいものを作成する前に、Svelte アプリ内で既存のパターンを検索してください。
- 作成するものに最も近い Svelte の実装を見つけます。
- ファイル構成、命名、インポート、コンポーネントの構成をそれに合わせます。
$shared/および$comp/の共有ユーティリティとコンポーネントを再利用します。- 既存のユーティリティで必要なことをほぼ実現できる場合は、並行するものを作成せず、そのユーティリティを拡張してください。
従来の Angular アプリのアーキテクチャを Svelte にコピーしないでください。
TypeScript ルール
- ファイルとディレクトリには kebab-case を使用してください。
- 制御フロー文では必ず波括弧を使用してください。
- 関数本体に文がある場合は、ブロック形式のアロー関数を使用してください。
- 識別子を略さないでください。
orgではなくorganization、filtではなくfilterを使用してください。 - 名前付きインポートを優先してください。
Dialog、DropdownMenu、Field、Cardなどの shadcn 複合コンポーネントには、名前空間インポートを使用してもかまいません。 anyは避けてください。生成された型、明示的なインターフェース、unknown、または型ガードを使用してください。- Promise は必ず
awaitするか、意図的に fire-and-forget として処理してください。
UI コンポーネント
- ボタン、入力欄、メニュー、ダイアログ、カード、バッジ、区切り線、空の状態、スケルトン、フォームフィールドには、
$comp/ui/*の既存の shadcn-svelte コンポーネントを優先して使用してください。 - ドキュメントの構造には、ネイティブのセマンティック要素(
main、section、nav、form、table、アプリコンポーネントが不要な場合のbutton)も適切です。セマンティクスを汎用のスタイル付きdivに置き換えないでください。 - shadcn の詳細なコンポジションルールについては、
shadcn-svelteスキルを使用してください。 - Exceptionless の運用プロダクト UI に合わせてください。情報密度が高く、控えめで、ざっと見て把握しやすく、近くの画面と一貫性のあるデザインにします。アプリ内で、マーケティング風のヒーローレイアウトや装飾的なビジュアル表現を試すのは避けてください。
アクセシビリティ
- セマンティックなランドマークと、明確な見出し階層を1つ使用してください。
- すべてのフォームコントロールに、対応するラベルまたはアクセシブルな名前を設定してください。
- アイコンのみのボタンには
aria-labelを設定し、装飾目的のアイコンにはaria-hidden="true"を設定してください。 - ダイアログには、視覚的に非表示の場合もタイトルが必要です。
- エラー状態では
aria-invalidを設定し、aria-describedbyでヘルプテキストやエラーテキストに関連付けてください。 - キーボードナビゲーションと、視認できるフォーカス状態を維持してください。
フロントエンドテスト
- ユニットテスト/コンポーネントテストには Vitest と Testing Library を使用し、
.test.tsまたは.spec.tsとして対象のコードと同じ場所に配置してください。 - アクセシブルなクエリを優先してください。まず
getByRole、次にgetByLabelText、その後に表示テキストを使います。セマンティクスだけでは不十分な場合に限り、テスト ID を使用してください。 - E2E テストには Playwright を使用し、ローカルのアプリ URL のみを対象にしてください。CSS セレクターより、ロール/ラベルセレクターを優先してください。
- 変更した動作に絞ったテストを追加し、タスクに関係のない範囲までテスト対象を広げないでください。
- イテレーション中は、関連する最小限のテストまたは対象を絞った検証を実行してください。小さな編集のたびに、広範な Svelte 検証を実行しないでください。未プッシュのフロントエンド変更がある場合のプッシュ前/PR 前の検証、またはユーザーから明示的に求められた場合にのみ
npm run validateを実行してください。このコマンドはファイルをフォーマットするため、実行後にgit statusを確認し、フォーマットによる変更があれば同じコミットに含めてください。
ナビゲーションの優先事項
onclick/goto よりも href によるナビゲーションを優先してください。onclick は、非同期処理(例:保存してから移動する処理)が必要な場合にのみ使用してください。
複合コンポーネントのパターン
新しいコンポーネントを作成する前に、近くにある機能コンポーネントを確認してください。共有する選択肢のセットには options.ts を使用し、ダイアログ/メニュー/カード/フィールドには shadcn の複合コンポーネントインポートを使用し、フォームには tanstack-form スキルを使用してください。