--- trigger: glob globs: **/*.svelte.ts,**/*.svelte --- # Convex + Svelte Best Practices This document outlines the mandatory rules and best practices for integrating Convex with Svelte in this project. ## 1. Imports Always use the following import paths. Do NOT use `$lib/convex` or relative paths for generated files unless specifically required by a local override. ### Correct Imports: ```typescript import { useQuery, useConvexClient } from 'convex-svelte'; import { api } from '@sgse-app/backend/convex/_generated/api'; import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel'; ``` ### Incorrect Imports (Avoid): ```typescript import { convex } from '$lib/convex'; // Avoid direct client usage for queries import { api } from '$lib/convex/_generated/api'; // Incorrect path import { api } from '../convex/_generated/api'; // Relative path ``` ## 2. Data Fetching ### Use `useQuery` for Reactivity Instead of manually fetching data inside `onMount`, use the `useQuery` hook. This ensures your data is reactive and automatically updates when the backend data changes. **Preferred Pattern:** ```svelte ``` **Avoid Pattern:** ```svelte ``` ### Mutations Use `useConvexClient` to access the client for mutations. ```svelte ``` ## 3. Type Safety ### No `any` Strictly avoid using `any`. The Convex generated data model provides precise types for all your tables. ### Use Generated Types Use `Doc<"tableName">` for full document objects and `Id<"tableName">` for IDs. **Correct:** ```typescript import type { Doc, Id } from '@sgse-app/backend/convex/_generated/dataModel'; let selectedTask: Doc<'tasks'> | null = $state(null); let taskId: Id<'tasks'>; ``` **Incorrect:** ```typescript let selectedTask: any = $state(null); let taskId: string; ``` ### Union Types for Enums When dealing with status fields or other enums, define the specific union type instead of casting to `any`. **Correct:** ```typescript async function updateStatus(newStatus: 'pending' | 'completed' | 'archived') { // ... } ``` **Incorrect:** ```typescript async function updateStatus(newStatus: string) { // ... status: newStatus as any; // Avoid this } ```