frontend architecture
26
总安装量
0
周安装量
#7663
全站排名
安装命令
npx skills add https://github.com/exceptionless/exceptionless --skill Frontend Architecture
Skill 文档
Frontend Architecture
Located in src/Exceptionless.Web/ClientApp. The Svelte SPA is the primary client.
Directory Structure
src/
âââ lib/
â âââ features/ # Feature slices (vertical organization)
â â âââ auth/
â â â âââ api.svelte.ts
â â â âââ models/
â â â âââ schemas.ts
â â â âââ components/
â â âââ organizations/
â â âââ projects/
â â âââ events/
â â âââ shared/ # Cross-feature shared code
â âââ components/ # App-wide shared components
â â âââ ui/ # shadcn-svelte components
â âââ generated/ # API-generated types
â âââ utils/ # Utility functions
âââ routes/
â âââ (app)/ # Authenticated app routes
â âââ (auth)/ # Authentication routes
â âââ (public)/ # Public routes
âââ app.html
Route Groups
Organize routes by authentication/layout requirements:
routes/
âââ (app)/ # Requires authentication
â âââ +layout.svelte # App layout with nav
â âââ organizations/
â âââ projects/
âââ (auth)/ # Login/signup flows
â âââ +layout.svelte # Minimal auth layout
â âââ login/
â âââ signup/
âââ (public)/ # Public pages
âââ +layout.svelte # Marketing layout
âââ pricing/
Feature Slices
Organize by feature, aligned with API controllers:
features/organizations/
âââ api.svelte.ts # TanStack Query hooks
âââ models/
â âââ index.ts # Re-exports from generated
âââ schemas.ts # Zod validation schemas
âââ options.ts # Dropdown options, enums
âââ components/
âââ organization-card.svelte
âââ organization-form.svelte
âââ dialogs/
âââ create-organization-dialog.svelte
API Client Pattern
Centralize API calls per feature:
// features/organizations/api.svelte.ts
import { createQuery, createMutation, useQueryClient } from '@tanstack/svelte-query';
import { useFetchClient } from '@exceptionless/fetchclient';
import type { Organization, CreateOrganizationRequest } from './models';
export function getOrganizationsQuery() {
const client = useFetchClient();
return createQuery(() => ({
queryKey: ['organizations'],
queryFn: async () => {
const response = await client.getJSON<Organization[]>('/organizations');
if (!response.ok) throw response.problem;
return response.data!;
}
}));
}
export function postOrganizationMutation() {
const client = useFetchClient();
const queryClient = useQueryClient();
return createMutation(() => ({
mutationFn: async (data: CreateOrganizationRequest) => {
const response = await client.postJSON<Organization>('/organizations', data);
if (!response.ok) throw response.problem;
return response.data!;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['organizations'] });
}
}));
}
Model Re-exports
Re-export generated models through feature model folders:
// features/organizations/models/index.ts
export type {
Organization,
CreateOrganizationRequest,
UpdateOrganizationRequest
} from '$lib/generated';
// Add feature-specific types
export interface OrganizationWithStats extends Organization {
eventCount: number;
projectCount: number;
}
Barrel Exports
Use index.ts for clean imports:
// features/organizations/index.ts
export { getOrganizationsQuery, postOrganizationMutation } from './api.svelte';
export type { Organization, CreateOrganizationRequest } from './models';
export { organizationSchema } from './schemas';
Shared Components
Place truly shared components in appropriate locations:
lib/
âââ features/shared/ # Shared between features
â âââ components/
â â âââ formatters/ # Boolean, date, number formatters
â â âââ loading/
â â âââ error/
â âââ utils/
âââ components/ # App-wide components
âââ ui/ # shadcn-svelte
âââ layout/
âââ dialogs/ # Global dialogs
Generated Types
When API contracts change:
npm run generate-models
Prefer regeneration over hand-writing DTOs. Generated types live in $lib/generated.
Import Aliases
// Configured in svelte.config.js
import { Button } from '$comp/ui/button'; // $lib/components
import { User } from '$features/users/models'; // $lib/features
import { formatDate } from '$shared/formatters'; // $lib/features/shared
Composite Component Pattern
Study existing components before creating new ones:
- Dialogs: See
/components/dialogs/ - Dropdowns: Use
options.tswithDropdownItem<EnumType>[] - Forms: Follow TanStack Form patterns in
svelte-formsskill