4.8 KiB
4.8 KiB
CLQMS Frontend - Agent Guidelines
Build Commands
# Development
pnpm dev # Start dev server (http://localhost:5173)
# Production
pnpm build # Build for production (outputs to build/)
pnpm preview # Preview production build locally
# Type Checking
pnpm check # Run svelte-check TypeScript validation
pnpm check:watch # Run type checker in watch mode
# Package Management
pnpm install # Install dependencies
pnpm prepare # Sync SvelteKit (runs automatically)
Code Style Guidelines
TypeScript & Svelte
- Use TypeScript strict mode (configured in tsconfig.json)
- Prefer explicit types over
any - Use Svelte 5 runes:
$state,$derived,$effect,$props - Components use
.svelteextension with<script lang="ts">
Imports & Aliases
Use path aliases (defined in svelte.config.js):
$components/*→src/lib/components/*$stores/*→src/lib/stores/*$types/*→src/lib/types/*$server/*→src/lib/server/*$lib/*→src/lib/*(built-in) Order: External libs → SvelteKit → Internal aliases → Relative imports
Naming Conventions
- Components: PascalCase (e.g.,
Sidebar.svelte,LoginForm.svelte) - Files: kebab-case for non-components (e.g.,
api-client.ts) - Variables/functions: camelCase
- Constants: UPPER_SNAKE_CASE
- Types/Interfaces: PascalCase with descriptive names
- Svelte stores: camelCase (e.g.,
auth,userStore)
Component Structure
<script lang="ts">
// 1. Imports
import { goto } from '$app/navigation';
import { auth } from '$stores/auth';
// 2. Props
let { title, data } = $props<{ title: string; data: SomeType }>();
// 3. State
let loading = $state(false);
// 4. Derived
let isValid = $derived(data && data.length > 0);
// 5. Effects
$effect(() => { if (isValid) console.log('Data loaded'); });
</script>
<svelte:head><title>{title}</title></svelte:head>
<!-- Template -->
<div class="card"><slot /></div>
Styling (Tailwind + DaisyUI)
- Use Tailwind utility classes
- DaisyUI components:
btn,card,input,modal, etc. - Theme: Forest (medical green primary: #2d6a4f)
- Color utilities:
text-emerald-600,bg-emerald-100 - Responsive:
sm:,md:,lg:prefixes - Spacing: 4px base unit (e.g.,
p-4= 16px)
Error Handling
import { api } from '$server/api';
async function fetchData() {
const { data, error, success } = await api.get<Patient[]>('/api/patients');
if (!success || error) {
console.error('Failed to fetch:', error?.message);
return;
}
// Use data
}
Form Handling (Superforms + Zod)
import { superForm } from 'sveltekit-superforms';
import { zodClient } from 'sveltekit-superforms/adapters';
import { z } from 'zod';
const schema = z.object({
username: z.string().min(1, 'Required'),
email: z.string().email('Invalid email')
});
const { form, errors, enhance } = superForm(data?.form, {
validators: zodClient(schema)
});
State Management
import { writable } from 'svelte/store';
interface AuthState {
user: User | null;
isAuthenticated: boolean;
}
function createAuthStore() {
const { subscribe, set, update } = writable<AuthState>({
user: null,
isAuthenticated: false
});
return {
subscribe,
login: (user: User) => update(s => ({ ...s, user, isAuthenticated: true })),
logout: () => set({ user: null, isAuthenticated: false })
};
}
export const auth = createAuthStore();
Route Structure
src/routes/
├── +layout.svelte # Root layout
├── +page.svelte # Landing page (redirects)
├── (app)/ # Group: Protected routes
│ ├── +layout.svelte # App layout with sidebar
│ └── dashboard/
│ └── +page.svelte
└── (auth)/ # Group: Public routes
├── +layout.svelte # Auth layout (centered)
└── login/
└── +page.svelte
API Client Usage
import { api } from '$server/api';
// GET
const { data } = await api.get<User[]>('/api/users');
// POST
const { data } = await api.post<User>('/api/users', { name: 'John' });
// PATCH
const { data } = await api.patch<User>('/api/users/1', { name: 'Jane' });
// DELETE
const { data } = await api.delete('/api/users/1');
Environment Variables
// Use only PUBLIC_ prefix for client-side
import { PUBLIC_API_BASE_URL } from '$env/static/public';
Git Workflow
- Commit messages: imperative mood (e.g., "Add patient form validation")
- Branch naming:
feature/,fix/,refactor/prefixes - Never commit secrets or
.env.local
Testing (To Be Configured)
Test framework not yet configured. When added:
- Unit tests: Vitest (planned per checklist)
- E2E tests: Playwright (planned per checklist)