All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- List alias — Optional human-friendly alias (e.g.
groceries) for shopping lists, usable in place of the UUID; aliases are unique among active lists, normalized to lowercase, and deleted automatically when the list expires. New endpoints:GET /api/lists/by-alias/{alias}to resolve an alias,PUT /api/lists/{id}/aliasto set, update, or remove it. Small settings UI in the burger menu for managing the alias per list. - AGENTS.md — AI coding agent instructions covering project overview, tech stack, exact commands, coding conventions, development lifecycle (branch-per-change, Conventional Commits, CHANGELOG discipline), PR workflow, and three-tier boundaries (always/ask/never)
- UI design refresh — Refreshed the entire interface with a cohesive design system: a refined indigo brand color, softer layered shadows, rounded card surfaces, an ambient brand-tinted background, gradient primary buttons with subtle hover lift, polished list rows and empty states, custom scrollbars, and consistent keyboard focus rings — all in both light and dark mode, with no change to functionality
- Database schema initialization — Switched from
SchemaUtils.create()toSchemaUtils.createMissingTablesAndColumns()so new columns (like alias) are automatically added to existing tables on deployment without manual migration - Frontend dependencies — Updated all frontend packages to their latest compatible (non-breaking) versions, including Cypress, Vitest, i18next, react-i18next, jsdom, PostCSS, autoprefixer, TailwindCSS, and vite-plugin-pwa, keeping the toolchain current and reducing the surface for known issues
- Frontend Docker base image — Bumped the frontend dev and production Dockerfiles from
node:20-alpinetonode:24-alpineso the container's npm major version matches local development (npm 11), and switchednpm citonpm installso the lock file is reconciled on every build, preventing npm-version lockfile drift from breaking the build - Backend dependencies — Updated backend libraries: Ktor 2.3.6 → 2.3.13, Kotlin 1.9.20 → 1.9.25, Logback 1.4.11 → 1.5.38, PostgreSQL driver 42.7.1 → 42.7.13, Micrometer 1.11.0 → 1.17.0 (now on the modern
io.micrometer.prometheusmetricsPrometheus client), Testcontainers 1.21.3 → 1.21.4, JUnit Jupiter 5.10.1 → 5.14.4, and mockito-kotlin 5.2.1 → 5.4.0 - Build toolchain (Gradle) — Upgraded the Gradle wrapper from 7.6.4 to 8.7, clearing the "incompatible with Gradle 8.0" deprecation warnings, and added an explicit
junit-platform-launcherso the newer JUnit 5.14 platform runs under Gradle - Metric names (breaking for dashboards/alerts) — The two custom gauges were renamed to drop the misleading
_totalsuffix (which the modern Prometheus client reserves for counters):shoppimo_websocket_connections_total→shoppimo_websocket_connectionsandshoppimo_shopping_lists_total→shoppimo_shopping_lists. The bundled Grafana dashboard has been updated to match; any external dashboards, alert rules, or recording rules referencing the old names must be updated
- Flaky backend tests — Resolved intermittent
PSQLException: Connection refusederrors in CI by fixing Testcontainers lifecycle mismatch (@Containermoved tocompanion objectfor all@TestInstance(PER_CLASS)test classes) and disabling parallel test-class execution (maxParallelForks = 1) to prevent Exposed's global database registry from being overwritten mid-test by a concurrently running test class - Add-item timeout type — Replaced the Node-specific
NodeJS.Timeouttype in the Add Item form with the browser-safeReturnType<typeof setTimeout>, so the TypeScript build no longer depends on Node type definitions that don't belong in browser code - Docker frontend build — Regenerated
package-lock.jsonwith npm 10 so thenode:20-alpineimage'snpm cino longer fails with an out-of-sync error; npm 11 had omitted esbuild's per-platform optional binary entries that npm 10 requires
- Swipe-to-delete — List items can be swiped left on mobile to reveal a delete action; full swipe auto-deletes with a collapse animation; desktop retains hover-reveal delete with confirmation
- Sticky bottom input — Add Item form is fixed to the bottom of the screen on mobile for thumb-reachable access; desktop keeps it in the header
- Bottom sheet settings — Burger menu opens as a full-width bottom sheet on mobile, portaled to
document.bodyto avoid z-index stacking issues; redesigned with section labels, title, and inline controls - Inline language switcher — Replaced dropdown with a pill-style button group matching the theme toggle pattern
- Tap delay elimination — Added
touch-action: manipulationglobally to all interactive elements, removing the 300ms delay on mobile browsers - Smart autocomplete positioning — Autocomplete dropdown flips above the input when there's insufficient space below (e.g., when the mobile keyboard is open)
- Edit input overflow — Fixed text input overflowing the screen on small devices in edit mode by adding
min-w-0constraints
6.2.0 - 2026-03-26
- Prometheus application metrics — Replace JSON
/api/metricsendpoint with Prometheus exposition format using Ktor MicrometerMetrics plugin; exposesshoppimo_websocket_connections_total(active WebSocket connections) andshoppimo_shopping_lists_total(total lists in database) alongside JVM and HTTP request metrics
6.1.0 - 2026-03-26
- Detailed push notifications — Replace generic "List updated" message with action-specific notifications: item added (✚), checked (✓), unchecked (↩), edited (✎), deleted (✕), and completed items cleared
- Auto-subscribe with opt-out — Users are automatically subscribed to push notifications when opening a list; per-list opt-out toggle persisted in localStorage
- Push notification delivery — Fix Base64 encoding mismatch between frontend (
btoa()standard Base64) and backend (Base64.getUrlDecoder()URL-safe Base64) that silently broke push delivery - CORS preflight failure — Pass
deviceIdas query parameter instead ofX-Device-Idcustom header to avoid CORS preflight rejections in production
6.0.1 - 2026-03-26
- CORS configuration — Removed
allowCredentials = truewhich is incompatible withanyHost(); the CORS spec forbids wildcard origin with credentials, causing Ktor to silently drop all CORS headers
6.0.0 - 2026-03-26
- Dark Mode — Light, dark, and system-preference theme toggle via
ThemeContextandThemeTogglecomponent; applied across all pages and components - Smart Autocomplete —
AutocompleteServicetracks item history cross-list;AutocompleteDropdownintegrated intoAddItemFormwith keyboard navigation - Push Notifications — Web Push opt-in via
PushNotificationContextandNotificationBell; backend push subscription endpoints (/api/push/subscribe,/api/push/unsubscribe,/api/push/vapid-key) with VAPID signing; notifications triggered on list item changes - Push Subscription Storage — New
PushSubscriptionsdatabase table and repository in Kotlin backend - VAPID Key Support —
PushNotificationServicewith VAPID key configuration; VAPID env vars documented in.env.exampleand wired into Docker Compose files - Backend
.envAuto-Loading —EnvLoader.ktreads.envat startup for local development; gracefully falls back to OS env vars in production - PWA Service Worker — Migrated VitePWA from
generateSWtoinjectManifestfor custom service worker with push event handling - E2E Tests — Cypress tests for dark mode, autocomplete, and push notification UI flows
- README updated with dark mode, autocomplete, and push notification features; env vars table and API endpoints table expanded
- Push notification infinite spinner — Added timeout guard on
navigator.serviceWorker.ready; added VAPID fast-fail if keys are not configured - WebPush API usage — Fixed VAPID key encoding and Web Push library reflection issues
- Removed redundant
eslint-disablecomments; replacedanytypes; extracted i18n strings; deduplicated CSS classes
5.0.0 - 2026-03-25
- Public Open-Source Release: Official GitHub public release of Shoppimo
- Real-time WebSocket synchronization for collaborative editing
- Progressive Web App (PWA) support with offline functionality
- Multi-language support (English and German) with i18n infrastructure
- Responsive design for mobile, tablet, and desktop
- Automatic list cleanup with configurable retention policies
- Docker-based deployment with monitoring stack
- Comprehensive API with CORS support
- Health check endpoints and monitoring integration with Prometheus
- Kotlin/Ktor backend with PostgreSQL database
- React 18 frontend with Vite bundler
- TypeScript throughout frontend and supporting tooling
- Cypress end-to-end testing
- Vitest unit testing framework
- GitHub Container Registry (GHCR) image distribution
- Automated CI/CD with GitHub Actions
Frontend:
- React 18 with Vite
- TypeScript
- TailwindCSS for styling
- PWA capabilities
- i18next for internationalization
- React Router for navigation
- Testing Library and Cypress for testing
Backend:
- Kotlin with Ktor web framework
- Exposed ORM for database access
- PostgreSQL for data persistence
- HikariCP connection pooling
- Logback for logging
Infrastructure:
- Docker & Docker Compose for containerization
- Prometheus for metrics collection
- Grafana for metrics visualization
- Alertmanager for alerting
- GitHub Container Registry for image distribution
- GitHub Actions CI/CD pipelines for automated testing and releases
- Comprehensive documentation (deployment, security, production)
- MIT license (2026 Shoppimo Contributors)
- Professional open-source project structure