mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-18 06:49:40 +02:00
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>
5.4 KiB
5.4 KiB
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 filteringFavoriteService– add/remove/check, conflict handlingLocationLookupService– web search, content extraction, address/category detection, error handlingLocationController– 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) |