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>