Frontend Architecture
Work in src/Exceptionless.Web/ClientApp, the sole application frontend at /, and follow its AGENTS.md. Generate root routes with $app/paths; preserve primary historical hash links through the incoming-link compatibility layer.
Feature structure
Keep feature behavior in src/lib/features/<feature>/: API operations in api.svelte.ts, local types in models.ts, validation in schemas.ts or validators.ts, and UI in components/. Reuse generated API types through feature aliases. Match the nearest current feature instead of copying a static scaffold.
- tanstack-query: server state, mutation behavior, and WebSocket invalidation.
- tanstack-form: schema validation and API error mapping.
- shadcn-svelte: installed component composition.
Local UI conventions
- Reuse
$comp,$shared, and$libhelpers. In particular, usecreateQueryParametersfor route query binding. - Use shared formatter components in
src/lib/features/shared/components/formatters/for dates, relative time, duration, bytes, numbers, currency, percentages, booleans, and date math. - Match the existing dense, restrained operational UI and its theme tokens.
- Use
hreffor ordinary navigation; use action handlers when work must finish before navigating. - Prefer derived state for computed values; reserve effects for side effects. Use current Svelte event attributes and snippets.
- Preserve accessible labels, focus behavior, dialog titles, and field-error associations.
Svelte and TypeScript details
- Use
options.tsfor shared option sets within a feature. Use$featuresfor feature imports and$generatedfor generated contracts; extend generated types in feature-owned files. - Prefer named imports; use namespace imports for composite components such as
Dialog,DropdownMenu,Field, andCard. - Keep files and directories kebab-case. Follow the app's ESLint rules for braces and statement formatting.
- Avoid
any; use generated types, explicit interfaces,unknown, and type guards. Spell out identifiers such asorganizationandfilter. - Await asynchronous work and handle failures at the appropriate local boundary. Do not let rejected promises bypass error UI or mark an operation complete before its required work finishes.
- Use
$derivedfor computed values and$effectfor side effects. Useuntrack()selectively when an incidental read should not become an effect dependency; do not hide dependencies needed for correctness. - Use Svelte event attributes (
onclick,oninput) and snippets. Use array class syntax orcn()for conditional classes.
Accessibility and interaction
- Preserve native semantic elements, landmarks, and a clear heading hierarchy. Shared UI components complement document semantics rather than replacing them with styled
divs. - Associate each control with a label. Give icon-only buttons an accessible name and hide decorative icons from assistive technology.
- Give dialogs a title, even when visually hidden. Preserve keyboard navigation and visible focus states.
- Set
aria-invalidon invalid controls and connect help/error messages witharia-describedby. - For motion work, consult the frontend's installed
emil-design-engskill. Apply its interaction principles through existing Svelte components, preserving reduced-motion behavior and the operational UI's restraint.
Verification
Use colocated Vitest/Testing Library tests and local Playwright flows as appropriate. Prefer role and label queries. Follow the app's validation command policy; inspect the rendered flow when UI behavior changes.


