- Expand FAQ entries from ~5 to 8-14 per app with app-specific feature documentation
- Add comprehensive features, shortcuts, and keyboard shortcut sections
- Integrate shared getManaFAQs() in 10 apps with /mana page
- Integrate shared getPrivacyFAQs() in all 18 apps with app-specific data types
- Add unit tests for help content in all 18 apps (72 tests total)
- Tests verify: DE/EN content, matching FAQ/feature counts, unique IDs, contact info
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents potential XSS by safely serializing env values instead of using
raw string interpolation. Also creates missing hooks.server.ts for context
app and standardizes citycorners to use the same injection pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements passwordless authentication via passkeys using @simplewebauthn:
Backend (mana-core-auth):
- New passkeys table in auth schema (credentialId, publicKey, counter, etc.)
- PasskeyService with registration/authentication flows and challenge storage
- 7 new API endpoints (register, authenticate, list, delete, rename)
- createSessionAndTokens helper for non-password auth flows
- Security event types for passkey operations
Client (shared-auth):
- signInWithPasskey() and registerPasskey() with dynamic @simplewebauthn/browser imports
- isPasskeyAvailable() browser capability check
- Passkey management methods (list, delete, rename)
UI (shared-auth-ui):
- Passkey button on LoginPage with key icon, shown when browser supports WebAuthn
- Divider between passkey and email/password form
App integration:
- All 19 web app auth stores have isPasskeyAvailable() and signInWithPasskey()
- All 19 web app login pages pass passkeyAvailable and onSignInWithPasskey props
- rpID=mana.how in production enables cross-app passkey usage (SSO-compatible)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
No external auth providers to keep authentication fully self-sovereign
and avoid dependency on third-party services. Removes Google Sign-In,
Apple Sign-In components, utilities, endpoints, translations, and
mobile dependencies across all apps and shared packages.
Google/Apple integrations for data sync (Contacts import, Calendar sync)
are intentionally preserved as they serve a different purpose.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New reviews table (userId, locationId, rating 1-5, comment, unique per user)
- ReviewService with CRUD, stats aggregation, batch stats for lists
- ReviewController with GET/POST/DELETE endpoints at /reviews/:locationId
- Location list and detail endpoints now include reviewStats (avg + count)
- Star rating display on location cards (home page)
- Full review section on detail page: star picker, comment, submit, delete
- i18n: 13 new review-related translations (DE/EN)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Svelte 5 restricts {@const} to block contexts only. Use direct
isOpenNow() calls in {#if} conditions instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
shared-auth depends on shared-types for contactsClient, causing build
failure when the package isn't available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add isOpenNow() utility that checks current time against opening hours
- Show "Open now" / "Closed" badge on location cards and detail page
- Add category filter pills to the map page (click to filter markers)
- Add opening hours to seed data for cafés, bars, restaurant, shops, museums
- Add missing category colors to detail page
- i18n: openNow, closedNow, filterAll (DE/EN)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SvelteKit prerendering of /offline failed because favicon.png was
referenced in app.html but not present in the static directory.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The package was dynamically imported in the map page but not declared
in package.json, causing production builds to fail.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The shared-pwa package was missing from the Dockerfile build steps,
causing the web container build to fail on esbuild resolution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add cafe, bar, park, beach, hotel, event_venue, and viewpoint categories
to the CityCorners city guide. Each category includes 5 real Konstanz
locations with descriptions, addresses, and coordinates.
Changes across all layers: DB schema enum, DTOs, lookup keyword detection,
i18n (DE/EN), map colors, filter pills, landing page, and seed data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New script generates COPY blocks between marker comments, eliminating
manual maintenance. All 17 web Dockerfiles updated with markers.
Supports --check flag for CI validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. SEO Slugs: Auto-generated from name (ä→ae, ö→oe, etc.), unique with
-2/-3 suffix. Routes accept both UUID and slug. Seed data includes slugs.
2. Opening Hours + Contact: website, phone, openingHours fields in schema.
Displayed on detail page, editable in add/edit forms.
3. Landing Page with API: Fetches locations from backend at build time,
falls back to hardcoded JSON if API unreachable.
4. Frontend Tests: Vitest setup with api.test.ts (50 backend + web tests).
5. Marker Clustering: leaflet.markercluster for 10+ locations on map,
direct markers for fewer.
6. Favorite Collections: New collections table with CRUD endpoints.
Favorites page has tabs for favorites vs collections. Create, view,
delete collections with location management.
7. Rate Limiting: In-memory guard (10 req/min) on write endpoints.
Returns 429 with retryAfter.
8. Soft Deletes: deletedAt field, all reads filter deleted records.
POST /locations/:id/restore endpoint for owners.
50 backend tests passing, 0 type errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unnecessary wrapper div in WidgetContainer
- Increase grid gap from gap-4 to gap-5 for breathing room
- Add auto-rows-fr for equal row heights
- Add min-h on widget content so empty widgets aren't tiny
- Change default layout to 3 equal columns (small)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Photo Gallery:
- New `images` JSONB array field in locations schema
- POST /locations/:id/images endpoint to add photos (auth required)
- Gallery with thumbnail strip and image counter on detail page
- Any authenticated user can add photos to any location
- "Add photo" button inline with thumbnails
2. Nearby Locations:
- GET /locations/:id/nearby endpoint with Haversine distance query
- Configurable radius (default 2km, max 10km)
- Returns up to 5 nearby locations sorted by distance
- Horizontal scroll card strip on detail page showing distance
3. Search Suggestions + History:
- GET /locations/suggestions endpoint (prefix matching, fast)
- Search history stored in localStorage (max 8 entries)
- Empty search shows recent history with clock icon
- Selected locations automatically saved to history
- Falls back to full-text search if no prefix matches
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Owner tracking (createdBy):
- Add createdBy field to locations schema
- Set createdBy to userId on location creation
- Only owners can edit/delete their own locations
- Seed/unowned locations remain editable by anyone
2. Edit/Delete UI:
- Edit button + full edit form at /locations/:id/edit
- Delete button with confirmation dialog on detail page
- Both only visible to the location owner
- ForbiddenException (403) if non-owner tries to modify
3. Pagination:
- Backend returns paginated results (page, limit, total, totalPages)
- Frontend "Load more" button for infinite scroll
- Category filter reloads from API with server-side filtering
- Default 20 items per page, max 100
Tests updated: 36 tests passing (5 new for ownership + pagination).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lazy loading for location card images
- Category filter pills now show count (e.g. "Restaurants (3)")
- Better empty states with category-specific messages and emoji
- Share button on detail page (Web Share API with clipboard fallback)
- "On map" and "Directions" (Google Maps) buttons on detail page
- Geolocation "locate me" button on map page with user marker
- Image URL retry button on add form when image fails to load
- i18n keys for all new features (DE/EN)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mac Mini had 25k+ TIME_WAIT sockets exhausting the 16k ephemeral port range,
blocking all outgoing TCP connections. Root cause: ~50 health checks at 30s
intervals + n8n automation creating excessive short-lived connections.
- Remove n8n service and volume (no longer needed)
- Increase health check intervals: 30s → 120s (app services), 10s → 30s (infra)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a "Kosten" tab showing all 40+ credit operations across all apps,
grouped by app with category filters (AI, Productivity, Premium) and
color-coded cost badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add `locale` prop to all 6 apps using QuickInputBar
(todo, contacts, zitare, citycorners, questions, calendar)
- Enable `deferSearch` on apps with create flow
(contacts, zitare, questions) to match todo behavior
- Pass locale through Calendar's UnifiedBar wrapper
- Questions: default to 'en' locale (English-first app)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests: Jest + ts-jest with mock factories. 4 test suites covering LocationService (CRUD, search), FavoriteService (add/remove, conflicts), LocationLookupService (web search, extraction, error handling), LocationController (endpoints, query params).
Docs: Complete CLAUDE.md rewrite with live URLs, all endpoints, web pages, features, environment variables, Docker config, and test overview.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: GET /locations/lookup?q= endpoint that searches via mana-search, extracts content from top results, auto-detects address and category, returns pre-filled data with source links.
Frontend: /add page now has a two-step flow:
1. Search step: user enters a place name, backend scrapes the web
2. Edit step: form pre-filled with found data (name, description, address, category), user can review/edit before submitting. Shows source links.
Also fixed all API paths to use /api/v1/ prefix via centralized api() helper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
API paths: Created centralized api() helper in $lib/api.ts. All fetch calls now use /api/v1/ prefix matching the production NestJS route structure.
New feature: /add page where authenticated users can submit new locations with name, category, description, and optional address. Added "Hinzufügen" nav item with plus icon.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align all 20 web app auth stores to a consistent pattern:
- Use DEV_* constants with import.meta.env.DEV guard (no localhost leak in prod)
- Pass backendUrl to initializeWebAuth for automatic 401 token refresh
- Add redirectTo to forgotPassword for correct post-reset redirect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PWA: @vite-pwa/sveltekit with shared-pwa config, offline fallback page, service worker with standard caching preset.
i18n: svelte-i18n with DE/EN locale files, all UI strings translated, language switcher in PillNav, auth pages use shared-i18n translations.
Landing: Migrated from scoped CSS to Tailwind CSS with @astrojs/tailwind. Hero section, card grid, category filter buttons, detail page with timeline. Removed unused components (Welcome, ThemeToggle, update-locations.js).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: GET /locations/search?q= endpoint with ILIKE on name, description, address.
Frontend: QuickInputBar wired up in app layout, searches locations via API, navigates to detail page on select.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New project with three apps:
- Landing (Astro): static site with SVG illustrations, location data
- Backend (NestJS, port 3025): CRUD API for locations + favorites, Drizzle ORM, auth via mana-core-auth
- Web (SvelteKit, port 5196): Tailwind 4, PillNav, auth (login/register/SSO), Leaflet map, favorites with optimistic updates, theme/settings
Infrastructure: DB init SQL, setup-databases.sh, generate-env.mjs, root package.json scripts, Dockerfiles, docker-compose.macmini.yml (backend:3025, web:5022), Cloudflare wrangler.toml.
Branding: registered in shared-branding (AppId, APP_BRANDING, APP_ICONS, MANA_APPS, CitycornersLogo).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>