A modern CRM/ERP system built with SvelteKit 5 and Svelte 5 runes. Features client management, task tracking, calendar scheduling, and a dashboard — all powered by class-based reactive stores with zero external state management libraries.
| Layer | Technology |
|---|---|
| Framework | SvelteKit 5 (@sveltejs/kit ^2.16) |
| UI | Svelte 5 (^5.0) + TypeScript 5 |
| Styling | Tailwind CSS 4, bits-ui, tailwind-variants |
| State Management | Svelte 5 runes — class-based stores (no library) |
| Icons | Lucide Svelte |
| Testing | Vitest (unit), Playwright (e2e) |
| Backend | Django REST API (separate repo) |
| Auth | JWT tokens in httpOnly cookies |
| Package Manager | pnpm |
Detailed documentation is in the docs/ directory:
This is a demo repository - https://demo-easymindstudio.vercel.app/. The app requires a test user account to log in.
To request demo credentials, contact: info@easymindstudio.com
git clone <repository-url>
cd frontend
pnpm install
Create a .env file:
API_URL="https://easymind-erp-api.onrender.com/api"
Point API_URL to your Django backend instance.
pnpm dev
Open http://localhost:5173.
src/
├── hooks.server.ts # Auth guard — redirects unauthenticated users
├── routes/
│ ├── +layout.server.ts # Loads user from token (shared across all pages)
│ ├── +layout.svelte # Hydrates userStore, renders ProtectedLayout
│ ├── dashboard/ # Read-only — uses data props, no store
│ ├── clients/ # Interactive — class store + server load + bridge
│ │ ├── +page.server.ts # Server: fetches clients with filters from URL
│ │ ├── +page.ts # Bridge: hydrates clientStore in browser
│ │ ├── +page.svelte # Renders <ClientList />
│ │ ├── [id]/ # Client detail / edit
│ │ └── new/ # New client form
│ ├── tasks/ # Same pattern as clients
│ ├── calendar/ # Same pattern + form actions for CRUD
│ ├── login/ # Public route
│ └── settings/
├── lib/
│ ├── store/ # Svelte 5 class-based stores
│ │ ├── user.svelte.ts # Auth, permissions, display name
│ │ ├── clients.svelte.ts # Clients, contacts, filters, modals
│ │ ├── tasks.svelte.ts # Tasks, filters, pagination
│ │ └── calendar.svelte.ts # Events, filters, view state, modals
│ ├── server/ # Server-only API modules
│ │ ├── auth.ts # Login, token validation, user fetching
│ │ ├── clients.ts # Client API calls
│ │ ├── tasks.ts # Task API calls
│ │ └── calendar.ts # Calendar API calls
│ ├── types/index.ts # Shared TypeScript interfaces
│ ├── components/ # UI components by domain
│ │ ├── clients/ # client-list, client-table, filters, search-bar...
│ │ ├── tasks/ # task-list, task components
│ │ ├── calendar/ # month/week views, event modal, filters
│ │ ├── dashboard/ # stats-card, charts, recent activity
│ │ ├── layouts/ # protected-layout, sidebar
│ │ └── ui/ # Shared primitives (button, input, dialog...)
│ └── hooks/ # Svelte hooks (is-mobile)
├── app.html # HTML template
└── app.css # Global styles (Tailwind)
All client-side state is managed through Svelte 5 class-based stores using runes ($state, $derived, $effect). No Redux, Zustand, or any third-party state library.
// Example: src/lib/store/clients.svelte.ts
export class ClientStore {
clients = $state<Client[]>([]);
loading = $state(false);
filters = $state<{ search: string; lead: LeadStatus | null }>({ search: "", lead: null });
setClientsData(data: { clients: Client[]; pagination: PaginationState }) {
this.clients = data.clients;
this.pagination = data.pagination;
}
updateFilters(newFilters: { search?: string; lead?: LeadStatus | null }) {
this.filters = { ...this.filters, ...newFilters };
}
}
export const clientStore = new ClientStore();
+page.server.ts → +page.ts (bridge) → class store → components
server-only if (browser) { $state $derived(store.field)
cookies, API store.setData() }
Interactive pages (clients, tasks, calendar) use this pattern. Read-only pages (dashboard) pass data as $props directly — no store needed.
pnpm dev # Start dev server
pnpm build # Production build
pnpm preview # Preview production build
pnpm check # Type check (svelte-check)
pnpm lint # ESLint + Prettier check
pnpm format # Format with Prettier
pnpm test:unit # Vitest
pnpm test:e2e # Playwright
pnpm test # Run all tests
Last Updated: February 2026