# Copilot Instructions for ttscm-ui ## Project Overview **ttscm-ui** is an Electron desktop application built with **SvelteKit**, TypeScript, and Vite. It connects to the Optima API for credential and company management. The app uses standard SvelteKit routing for single-page navigation and pnpm for package management with patches applied to SvelteKit. ## Architecture Layers ### Electron Architecture - **`electron/main.ts`**: Main process—creates/manages windows, handles file system access. Loads preload script and serves the renderer. - **`electron/preload.ts`**: Currently empty bridge between main and renderer processes. Extend here to expose secure IPC handlers if needed. - **`forge.config.ts`**: Electron Forge configuration with Vite plugin for building main, preload, and renderer targets. ### Frontend (SvelteKit) - **`src/routes/`**: SvelteKit file-based routing with standard pathname router. - `(auth)` group: Authentication pages (login) - `(secure)` group: Protected pages requiring auth - **`src/lib/`**: Reusable modules - `optima-api/`: API client abstraction with modular endpoints (auth, companies, credentials, etc.) - `axios.ts`: Base axios instance with `PUBLIC_API_URL` env variable - **`src/components/`**: Reusable Svelte components (modals, spinners, error boundaries) ### API Communication The `$lib/index.ts` exports `optima` object aggregating all API modules. Example: ```typescript export const optima = { auth: (await import("./optima-api/modules/auth")).auth, company: (await import("./optima-api/modules/companies")).company, // etc. }; ``` Each module (e.g., `auth.ts`) exports functions that call the API using a custom axios instance. ## Key Conventions ### Routing - **Use standard SvelteKit routing with `/` prefix** (e.g., `href="/credentials"`) - Routes in `src/routes/` map to `/path` at runtime - Do NOT use hash-based routing (`#/` routes) ### API Module Pattern Create API modules in `src/lib/optima-api/modules/` following this pattern: ```typescript // Example: credentials.ts export const credential = { async fetchCredentials(api: AxiosInstance) { // Implementation }, }; ``` Export as a named object, then import/aggregate in `src/lib/index.ts`. ### Environment Variables - `PUBLIC_API_URL`: API base URL, used in `src/lib/optima-api/axios.ts` - Prefixed with `PUBLIC_` to be accessible in client code ### File Organization - Components go in `src/components/` (e.g., modals, spinners) - Page-specific logic in `src/routes/[route]/+page.svelte` and `+page.server.ts` - Styles in `src/styles/` with Tailwind CSS + TailwindCSS vite plugin - Tests colocated: `*.spec.ts` or `*.test.ts` next to source files ## Development Workflow ### Installation & Setup ```bash pnpm install ``` Uses pnpm with SvelteKit patches (see `patches/` directory). ### Running in Development ```bash pnpm run start ``` Electron Forge + Vite handles dev server and hot module replacement (HMR). Dev tools open automatically. Main window loads `/login` first. ### Building & Packaging - **Build for production**: `pnpm run package` → outputs to `out/` directory - **Create distributable**: `pnpm run make` → creates installers (configure in `forge.config.ts`) - **Check types & lint**: `pnpm run check` (runs svelte-kit sync + svelte-check) ### Testing #### Unit Tests (Vitest) ```bash pnpm run test:unit ``` - Client tests: `src/**/*.svelte.{test,spec}.{js,ts}` (jsdom environment) - Server tests: `src/**/*.{test,spec}.{js,ts}` excluding svelte tests (node environment) - Setup: `vitest-setup-client.ts` mocks `window.matchMedia` for Svelte 5 + jsdom compatibility #### E2E Tests (Playwright) ```bash pnpm run test:e2e ``` - Tests in `e2e/` directory - Config: `playwright.config.ts` (builds and previews before testing) #### Run All Tests ```bash pnpm run test ``` Runs unit tests first, then e2e. ## Critical Integration Points ### IPC (Electron Main ↔ Renderer) **Status**: Preload script is currently empty. If file system access is needed, define IPC handlers in `electron/main.ts` and expose them via `electron/preload.ts` to renderer process. ### API Authentication - Auth flow starts in `src/lib/optima-api/modules/auth.ts` with `fetchAuthRedirectUri()` - TODO: Enforce auth checks on every page change (see `src/lib/index.ts` comment) ### Build Artifacts - **Dev server URL**: `MAIN_WINDOW_VITE_DEV_SERVER_URL` (injected by Electron Forge) - **Output**: Rendered app built to `.vite/renderer/main_window/` (configured in `svelte.config.js`) ## Common Patterns & Gotchas 1. **Standard Routing**: Use standard SvelteKit routing with `/` prefix (e.g., `href="/credentials"`) — do NOT use hash-based routing 2. **SvelteKit Patches**: Project patches SvelteKit in `patches/` to work around issues. When updating SvelteKit, verify patches still apply. 3. **Async Components**: Svelte 5 has `experimental.async: true` enabled; be aware of async component patterns. 4. **Tailwind**: Uses `@tailwindcss/vite` plugin; configure utilities in tailwind config if needed. 5. **API Error Handling**: API modules throw errors with descriptive messages. Use `$lib/errorHandler.ts` for consistent error formatting. ## Useful Entry Points for Navigation - **Frontend Layout**: [src/routes/+layout.svelte](src/routes/+layout.svelte) (main shell, sidebar, header) - **API Abstraction**: [src/lib/optima-api/axios.ts](src/lib/optima-api/axios.ts) (base client) - **API Modules**: [src/lib/optima-api/modules/](src/lib/optima-api/modules/) (auth, companies, credentials, etc.) - **App Entry**: [src/app.html](src/app.html) - **Electron Main**: [electron/main.ts](electron/main.ts)