managarten/apps/citycorners/CLAUDE.md
Till JS 8b96b82428 feat(citycorners): add 7 new location categories with 35 seed entries
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>
2026-03-25 12:53:04 +01:00

5.4 KiB
Raw Blame History

CityCorners

City guide for Konstanz (Bodensee) showcasing locations, restaurants, museums, and sights.

Live URLs

Service URL
Web App https://citycorners.mana.how
API https://citycorners-api.mana.how
Landing https://citycorners-landing.pages.dev

Architecture

apps/citycorners/
├── apps/
│   ├── landing/     # Astro static site (Tailwind, Cloudflare Pages)
│   ├── backend/     # NestJS API (port 3025 dev, 3041 prod)
│   └── web/         # SvelteKit web app (port 5196 dev, 5022 prod)
└── CLAUDE.md

Tech Stack

  • Backend: NestJS 10, Drizzle ORM, PostgreSQL, mana-core-auth (JWT)
  • Web: SvelteKit 2, Svelte 5 runes, Tailwind 4, Leaflet maps, svelte-i18n (DE/EN), PWA
  • Landing: Astro 5, Tailwind 3, static site generation
  • Search: mana-search integration (SearXNG + content extraction)

Development

# Full stack (auth + backend + web)
pnpm dev:citycorners:full

# Individual apps
pnpm dev:citycorners:landing
pnpm dev:citycorners:backend
pnpm dev:citycorners:web

# Database
pnpm citycorners:db:push      # Push schema
pnpm citycorners:db:studio    # Drizzle Studio
pnpm citycorners:db:seed      # Seed 41 sample locations

# Tests
pnpm --filter @citycorners/backend test        # Run all tests (31 tests)
pnpm --filter @citycorners/backend test:watch  # Watch mode
pnpm --filter @citycorners/backend test:cov    # Coverage report

# Deploy
pnpm deploy:landing:citycorners               # Landing to Cloudflare Pages

Database

PostgreSQL database citycorners with Drizzle ORM.

Schema

  • locations name, category (enum: sight/restaurant/shop/museum/cafe/bar/park/beach/hotel/event_venue/viewpoint), description, address, lat/lng, imageUrl, timeline (JSONB array of {year, event})
  • favorites userId, locationId (FK → locations, cascade delete), unique constraint on (userId, locationId)

API Endpoints

All endpoints are prefixed with /api/v1/ in production (via shared-nestjs-setup).

Locations

Method Path Auth Description
GET /locations No List all (optional ?category=sight|restaurant|shop|museum)
GET /locations/search?q= No Text search (ILIKE on name, description, address)
GET /locations/lookup?q= No Web lookup via mana-search (scrapes info, auto-fills form)
GET /locations/:id No Get single location
POST /locations Yes Create location
PUT /locations/:id Yes Update location
DELETE /locations/:id Yes Delete location

Favorites

Method Path Auth Description
GET /favorites Yes List user's favorite location IDs
POST /favorites/:locationId Yes Add to favorites
DELETE /favorites/:locationId Yes Remove from favorites

Web App Pages

Route Description
/ Location grid with category filter pills
/map Leaflet map with color-coded markers
/locations/:id Detail page with mini-map, timeline, favorite button
/add Two-step flow: web lookup → edit form → submit
/favorites User's saved locations
/settings Theme mode/variant, account, about
/login, /register Auth via shared-auth-ui
/offline PWA offline fallback

Features

  • PWA: Installable, offline fallback, service worker caching (API: NetworkFirst, images: CacheFirst)
  • i18n: German + English, language switcher in PillNav, localStorage persistence
  • Favorites: Optimistic updates, auth-gated heart button on cards + detail page
  • Search: QuickInputBar in PillNav, backend ILIKE search
  • Web Lookup: mana-search integration for auto-filling location data from the web
  • Branding: Registered in shared-branding (AppId, icon, APP_URLS, app switcher)

Categories

DB Value Label (DE) Label (EN) Card Color
sight Sehenswürdigkeit Sight Blue
restaurant Restaurant Restaurant Red
shop Laden Shop Green
museum Museum Museum Purple
cafe Café Café Amber
bar Bar Bar Orange
park Park Park Emerald
beach Strandbad Beach Cyan
hotel Hotel Hotel Indigo
event_venue Veranstaltungsort Event Venue Pink
viewpoint Aussichtspunkt Viewpoint Sky

Tests

4 test suites, 31 tests covering:

  • LocationService CRUD, search, category filtering
  • FavoriteService add/remove/check, conflict handling
  • LocationLookupService web search, content extraction, address/category detection, error handling
  • LocationController endpoint routing, query params, auth guards

Docker

  • Backend: apps/citycorners/apps/backend/Dockerfile (multi-stage, port 3041 prod)
  • Web: apps/citycorners/apps/web/Dockerfile (multi-stage, port 5022 prod)
  • Entrypoints: Auto schema push, optional seed on start
  • docker-compose.macmini.yml: Both services configured with health checks

Environment Variables

Variable Used by Description
DATABASE_URL Backend PostgreSQL connection string
MANA_CORE_AUTH_URL Backend Auth service URL
MANA_SEARCH_URL Backend mana-search service URL
PUBLIC_BACKEND_URL Web Backend API URL
PUBLIC_MANA_CORE_AUTH_URL Web Auth service URL (client)