Migrate frontend from Alpine.js to SvelteKit and update documentation

Migrated the frontend from Alpine.js to SvelteKit with shared UI stores.
Updated the project structure to use SvelteKit primitives for routing,
state management, and form handling. Added a new round counter component
and updated the project root to use a single Dockerfile. Updated
dependencies including Alpine.js, Vite, and SvelteKit. Refined CSS and
configuration files for the new frontend stack.
This commit is contained in:
2026-04-11 20:12:45 +02:00
parent 2c0cd01ab2
commit 4822e03ab4
4 changed files with 24 additions and 55 deletions

View File

@@ -1,6 +1,6 @@
# EDH/Commander Stats Tracker
A lightweight, responsive web application for tracking Magic: The Gathering EDH/Commander games with comprehensive statistics and analytics. Built with Fastify (Node.js), PostgreSQL, and Alpine.js for optimal performance and scalability.
A lightweight, responsive web application for tracking Magic: The Gathering EDH/Commander games with comprehensive statistics and analytics. Built with Fastify (Node.js), PostgreSQL, and SvelteKit for optimal performance and scalability.
## Features
@@ -9,7 +9,7 @@ A lightweight, responsive web application for tracking Magic: The Gathering EDH/
#### Authentication & Users
- **Secure Authentication**: JWT-based login/registration system with password hashing (HS512).
- **User Profile Management**: View and edit user profile information.
- **Session Management**: Persistent authentication with localStorage/sessionStorage support.
- **Session Management**: Secure, HttpOnly cookie-based authentication for seamless sessions.
- **Configurable Registration**: Toggle user registration on/off via `ALLOW_REGISTRATION` environment variable for controlled access.
#### Commander Management
@@ -64,7 +64,7 @@ A lightweight, responsive web application for tracking Magic: The Gathering EDH/
#### User Interface
- **Responsive Design**: Mobile-friendly layout using Tailwind CSS.
- **Dark Theme**: Professional dark color scheme with proper contrast.
- **Alpine.js Components**: Lightweight, reactive UI without heavy frameworks.
- **Svelte Components**: Reactive UI powered by SvelteKit and shared stores.
- **Professional Navigation**: Easy access to all major features.
- **Accessibility**: Semantic HTML and accessible form controls.
@@ -103,7 +103,7 @@ A lightweight, responsive web application for tracking Magic: The Gathering EDH/
- **Backend**: Fastify (Node.js v20+)
- **Database**: PostgreSQL 16 with connection pooling (pg library)
- **Frontend**: Alpine.js, Tailwind CSS (CDN)
- **Frontend**: SvelteKit, Tailwind CSS
- **Visualization**: Chart.js
- **Containerization**: Docker & Docker Compose
- **Authentication**: JWT with HS512 hashing
@@ -242,15 +242,15 @@ edh-stats/
│ ├── package.json # Node.js dependencies
│ └── Dockerfile
├── frontend/
│ ├── public/
│ │ ├── css/ # Tailwind styles
│ │ ├── js/ # Alpine.js components
│ │ ── components/ # Reusable HTML components
│ ├── *.html # View files
│ │ └── round-counter.html # Live round counter (NEW)
│ ├── src/
│ │ ├── routes/ # SvelteKit pages and layouts
│ │ ├── lib/components/ # Shared UI components (NavBar, Footer, etc.)
│ │ ── lib/stores/ # Svelte stores (auth, derived state)
│ ├── static/ # Static assets (fonts, images, css)
│ ├── tailwind.config.js # Tailwind configuration
│ ├── package.json # Node.js dependencies
── Dockerfile
│ ├── vite.config.js # Vite dev/proxy configuration
── package.json # Frontend dependencies
│ └── Dockerfile* # Dev/prod Dockerfiles
├── postgres_data/ # Persisted PostgreSQL data (Docker volume)
├── docs/ # Documentation
├── FIXES.md # Detailed list of fixes applied
@@ -384,24 +384,19 @@ docker compose exec postgres psql -U postgres -d edh_stats
The application logs connection pool info at startup. To debug connection issues, set `LOG_LEVEL=debug` to see detailed connection logging.
### Frontend State Management
- Alpine.js components handle all state management
- No external state management library needed
- Components:
- `app()`: Main dashboard and page initialization
- `commanderManager()`: Commander CRUD operations
- `gameManager()`: Game logging and editing
- `roundCounterApp()`: Real-time round counter with game timing
- Authentication tokens stored in `localStorage` (persistent) or `sessionStorage` (session-only)
- Data persistence: `localStorage` for round counter state
- Dynamic content loading: Partial HTML pages loaded and inserted via loaders
- SvelteKit components manage UI state through Svelte's built-in reactivity.
- Shared state (authentication, derived data) lives in `src/lib/stores`, primarily `auth.js`.
- Authentication relies on secure HttpOnly cookies; the store only tracks user metadata and loading state.
- Persistent client data (e.g., round counter progress) is stored in `localStorage` with defensive guards for SSR.
- Routing, forms, and API interactions are handled with first-class SvelteKit primitives instead of manual DOM loaders.
### Authentication Flow
1. User registers with username and password
2. Password hashed with bcryptjs (12 rounds)
3. JWT token generated (HS512 algorithm)
4. Token stored in browser (localStorage/sessionStorage)
5. Token validated on protected routes
6. Automatic token validation on component initialization
4. Secure session cookie issued to the browser
5. Protected routes validate the JWT extracted from the cookie
6. `auth.init()` validates the cookie on app start and hydrates the user store
### Error Handling
- All API errors return appropriate HTTP status codes
@@ -448,13 +443,13 @@ The application logs connection pool info at startup. To debug connection issues
- **Registration Control**: Added `ALLOW_REGISTRATION` environment variable to toggle signup availability
- **Game API Response**: Ensured all game endpoints return complete commander information (name, colors)
- **Form Validation**: Improved notes field handling to prevent null value validation errors
- **Frontend Error Handling**: Fixed Alpine.js key binding issues in top commanders template
- **Frontend Error Handling**: Fixed legacy Alpine.js key binding issues in top commanders template prior to the Svelte migration
### Previous Session Fixes
This version includes **19+ bug fixes and improvements** addressing:
- SQL parameter mismatches and injection vulnerabilities
- Boolean type conversion issues in form submissions
- Invalid Alpine.js expressions and duplicate elements
- Invalid legacy Alpine.js expressions and duplicate elements
- Corrupted SVG paths in UI components
- Field name mismatches between frontend and backend
- Color parsing and null/undefined value handling

View File

@@ -9,7 +9,6 @@
"version": "2.2.0",
"license": "MIT",
"dependencies": {
"alpinejs": "^3.13.3",
"chart.js": "^4.4.1"
},
"devDependencies": {
@@ -617,21 +616,6 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@vue/reactivity": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
"integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.1.5"
}
},
"node_modules/@vue/shared": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz",
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==",
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
@@ -645,15 +629,6 @@
"node": ">=0.4.0"
}
},
"node_modules/alpinejs": {
"version": "3.15.4",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.4.tgz",
"integrity": "sha512-lDpOdoVo0bhFjgl310k1qw3kbpUYwM/v0WByvAchsO93bl3o1rrgr0P/ssx3CimwEtNfXbmwKbtHbqTRCTTH9g==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "~3.1.1"
}
},
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",

View File

@@ -11,7 +11,6 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
},
"dependencies": {
"alpinejs": "^3.13.3",
"chart.js": "^4.4.1"
},
"devDependencies": {
@@ -24,7 +23,7 @@
"vite": "^8.0.8"
},
"keywords": [
"alpinejs",
"sveltekit",
"tailwindcss",
"magic-the-gathering",
"edh",

View File

@@ -1,6 +1,6 @@
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&family=Inter:wght@300;400;500;600;700&display=swap');
/* Alpine.js x-cloak - hide elements until Alpine initializes */
/* Utility to hide elements until JS initializes */
[x-cloak] {
display: none !important;
}