Commit graph

189 commits

Author SHA1 Message Date
Till JS
35ec9aeb2e deploy(manavoxel): add Dockerfile, docker-compose, and deploy config
- Dockerfile: two-stage build on sveltekit-base, port 5028
- docker-compose.macmini.yml: manavoxel-web service on port 5028
- Root package.json: dev:manavoxel:web and dev:manavoxel:full scripts
- Fix Tailwind CSS import (shared-tailwind/themes.css)
- Port changed from 5195 to 5028 (consistent dev/prod)

Deploy with: ./scripts/mac-mini/build-app.sh manavoxel-web

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:56:32 +02:00
Till JS
bc428729b0 deploy(taktik): add Dockerfile, docker-compose, SSO config
- Dockerfile based on sveltekit-base pattern (port 5027)
- docker-compose.macmini.yml: taktik-web service with auth + sync
- mana-auth: added taktik.mana.how to trustedOrigins
- CORS_ORIGINS: added taktik.mana.how

Remaining manual steps on Mac Mini:
- cloudflared tunnel route: taktik.mana.how -> localhost:5027
- ./scripts/mac-mini/build-app.sh taktik-web

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 08:55:30 +02:00
Till JS
cb549776ac deploy(calc): add docker-compose, cloudflared tunnel, SSO config
- docker-compose.macmini.yml: calc-web service on port 5026
- cloudflared-config.yml: calc.mana.how → localhost:5026
- mana-auth trusted origins: add https://calc.mana.how
- mana-credits & mana-user CORS: add https://calc.mana.how
- Dockerfile port updated from 5018 to 5026 (5018 used by zitare)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 08:53:41 +02:00
Till JS
e94a41348d fix(docker): remove picture-backend from compose (replaced by Hono server) 2026-03-28 21:31:48 +01:00
Till JS
b45ddbbb83 refactor: remove local AI services from Mac Mini, GPU-only architecture
- Deactivate Ollama, FLUX.2, and Telegram Bot LaunchAgents on Mac Mini
- Remove extra_hosts from mana-llm (no longer needs host.docker.internal)
- Update health-check.sh to monitor GPU server services instead of local
- Update status.sh to show GPU server status instead of native services
- Rewrite MAC_MINI_SERVER.md: remove ~400 lines of Ollama/FLUX/Bot docs,
  add GPU server architecture diagram and deactivation notes
- Update CAPACITY_PLANNING.md with post-offload numbers (~80-150 peak users)

Mac Mini is now a pure hosting server (Web, API, DB, Sync).
All AI workloads run on GPU server (RTX 3090) via LAN.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:23:37 +01:00
Till JS
9276d9a212 feat: GPU offload, signup limit, load tests & capacity planning
- Route all AI workloads (Ollama, STT, TTS, Image Gen) to GPU server
  (192.168.178.11) via LAN instead of host.docker.internal
- Upgrade default model to gemma3:12b and max concurrent to 5
- Add daily signup limit service (MAX_DAILY_SIGNUPS env var)
- Add GET /api/v1/auth/signup-status public endpoint
- Add k6 load test suite (web-apps, auth, sync-websocket, ollama)
- Add capacity planning documentation
- Fix: add eslint-config to sveltekit-base and calendar Dockerfiles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:14:24 +01:00
Till JS
73181ab91d refactor(mana-media): migrate from NestJS to Hono/Bun
Replace NestJS framework with Hono + Bun, eliminating the last
NestJS service from the stack. All business logic preserved:
- CAS upload with SHA-256 dedup
- BullMQ image processing (Sharp thumbnails/variants)
- Matrix MXC URL import
- EXIF extraction
- File streaming/transforms
- Prometheus metrics

23 NestJS files → 12 Hono files. Zero NestJS in the monorepo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:12:42 +01:00
Till JS
e35bbcd09b fix(infra): remove depends_on references to deleted backend services
Chat, Todo, Calendar, Contacts, Storage, ManaDeck, NutriPhi, Mukke
backends were removed in previous sessions but their web services
still had depends_on references, breaking docker compose.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:03:20 +01:00
Till JS
18fae3b66d feat(infra): add docker-compose for new Hono services + DB init
- Add mana-user (3062), mana-subscriptions (3063), mana-analytics (3064)
  to docker-compose with health checks and traefik labels
- Replace old NestJS Tier 3 app backends (~300 lines) with comment
  placeholder for Hono compute servers (need shared Dockerfile)
- Create docker/Dockerfile.hono-server — shared Bun Dockerfile for
  all 14 app compute servers (ARG APP for build context)
- Add 5 new databases to setup-databases.sh: mana_auth, mana_credits,
  mana_user, mana_subscriptions, mana_analytics, mana_sync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:54:24 +01:00
Till JS
7e5167c9a8 fix(infra): fix Forgejo runner image, command, and permissions
- Fix runner image: code.forgejo.org/forgejo/runner:6.3.1
- Add command: forgejo-runner daemon
- Run as root for Docker socket access on macOS
- Runner registered and running on Mac Mini

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:46:51 +01:00
Till JS
7e931b1c6d refactor(services): rename Go services, remove -go suffix
mana-search-go → mana-search
mana-notify-go → mana-notify
mana-crawler-go → mana-crawler
mana-api-gateway-go → mana-api-gateway

Legacy NestJS versions are deleted, suffix no longer needed.
Updated all references in docker-compose, CLAUDE.md, package.json,
Forgejo workflows, and service package.json files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:18:40 +01:00
Till JS
5b673282f9 feat(infra): delete mana-core-auth (NestJS), replace with mana-auth (Hono+Bun)
Remove the entire NestJS-based mana-core-auth service (~36,000 lines
including tests, config, and package files). The new mana-auth service
(Hono + Bun, ~1,900 LOC) is the complete replacement on the same port.

Deleted:
- services/mana-core-auth/ — 169 files, 36,123 lines
  (NestJS 10, Express, class-validator, all NestJS infrastructure)

Updated:
- docker-compose.macmini.yml: mana-auth now builds from services/mana-auth
  with Bun healthcheck, simplified env vars (no Redis, no DuckDB needed)
- CLAUDE.md: mana-core-auth → mana-auth in services list
- Overview plan: marked Phase 4+5 as DONE, updated next steps

The ManaCore auth ecosystem is now:
- mana-auth (3001) — Auth, JWT, SSO, OIDC, Guilds, API Keys, GDPR
- mana-credits (3061) — Credits, Gifts, Guild Pools, Stripe
- mana-user (3062) — Settings, Tags, Storage
- mana-subscriptions (3063) — Plans, Billing, Invoices
- mana-analytics (3064) — Feedback, Voting

Total: ~6,600 LOC across 5 Hono+Bun services
Replaces: ~20,000 LOC in 1 NestJS service (67% reduction)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 03:04:01 +01:00
Till JS
8d36aba134 feat(infra): add Forgejo for self-hosted Git + CI/CD
- Forgejo v11 on port 3041 (git.mana.how via Cloudflare Tunnel)
- Forgejo Runner for CI/CD (GitHub Actions compatible)
- Built-in Docker registry and LFS support
- Registration disabled (admin-only)
- SSH access on port 2222
- Go Services CI workflow (.forgejo/workflows/go-services.yml)
- Setup script: scripts/mac-mini/setup-forgejo.sh

Replaces GitHub dependency for CI/CD. GitHub can remain as
mirror/backup while Forgejo becomes the primary Git host.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 03:00:50 +01:00
Till JS
753c685ef7 feat(services): create mana-analytics, remove feedback/analytics/ai from auth
Extract feedback, analytics, and AI modules from mana-core-auth into
standalone mana-analytics service (Hono + Bun, Port 3064).

New service (services/mana-analytics/):
- User feedback CRUD with voting
- AI-powered feedback title generation via mana-llm
- Simplified from DuckDB analytics to pure PostgreSQL
- ~550 LOC

Removed from mana-core-auth:
- feedback/ module (6 files)
- analytics/ module (4 files)
- ai/ module (3 files)
- db/schema/feedback.schema.ts

mana-core-auth now contains ONLY pure auth:
- Better Auth (JWT, Sessions, 2FA, Passkeys, OIDC, Magic Links)
- Organizations/Guilds (membership management)
- API Keys, Security, Me (GDPR), Health, Metrics
- Ready for Phase 5: Hono rewrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:29:24 +01:00
Till JS
d7799ec95d refactor(photos): remove NestJS backend, use local-first + direct mana-media
The Photos NestJS backend was a proxy to mana-media that enriched
responses with local album/favorite/tag data. Now:

- Albums store → local-first via albumCollection + albumItemCollection
- Favorites → local-first via favoriteCollection (toggle in IndexedDB)
- Photo tags → local-first via photoTagCollection
- Photo listing/stats → direct mana-media API calls from frontend
- Upload → direct mana-media upload from frontend
- Delete → direct mana-media delete from frontend

Removed 27 TypeScript files, 1 Docker container, 1 port (3039).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:18:03 +01:00
Till JS
e7a8567e61 feat(services): create mana-subscriptions, remove from mana-core-auth
Extract subscription billing into standalone mana-subscriptions service
(Hono + Bun, Port 3063). Also removes Stripe module from mana-core-auth
since subscription webhooks are the last consumer.

New service (services/mana-subscriptions/):
- Plans CRUD, subscription management, Stripe Checkout + Portal
- Invoice tracking, webhook handlers for sub/invoice events
- Internal API for plan limits (consumed by guilds service)
- ~990 LOC (vs ~1,700 in NestJS incl. Stripe module)

Removed from mana-core-auth:
- subscriptions/ module (6 files)
- stripe/ module (4 files) — no longer needed in auth
- db/schema/subscriptions.schema.ts
- guilds.service.ts: replaced direct DB plan limit query with
  HTTP call to mana-subscriptions internal API

mana-core-auth now contains only:
- Auth (Better Auth, JWT, Sessions, 2FA, Passkeys, OIDC)
- Organizations/Guilds (membership only, no credits/plans)
- API Keys, Security, Me (GDPR), Health, Metrics
- Feedback + Analytics (next extraction target)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:11:42 +01:00
Till JS
dd2f814cf3 refactor(presi): replace NestJS backend with lightweight Hono server
The Presi NestJS backend (40 source files, 50 deps) was a CRUD wrapper
around decks, slides, and themes — all now handled by local-first sync.

Only the share-link feature requires server-side state (public URLs
without auth), so a minimal Hono + Bun server replaces the entire
NestJS backend:

- apps/presi/apps/server/ — Hono server with share routes + GDPR admin
  Uses @manacore/shared-hono for auth (JWKS), health, admin, errors
- Web app API client stripped to share-only (was 270 lines → 90 lines)
- Removed from docker-compose, CI/CD, Prometheus, env generation
- NestJS backend deleted (40 TS files, 8 test specs, 3038 lines)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:08:40 +01:00
Till JS
82de69476f fix(infra): change mana-notify port to 3042 (3041 used by citycorners)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:40:06 +01:00
Till JS
0bf5a90f12 fix(infra): change mana-notify port to 3041 (3040 used by picture-backend)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:39:36 +01:00
Till JS
d56737fea7 fix(infra): remove clock-backend references from docker-compose
Clock app was migrated to local-first (mana-sync), remove stale
depends_on and environment references to clock-backend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:38:21 +01:00
Till JS
ef19018e71 feat(infra): add mana-sync and mana-notify-go to docker-compose
- mana-sync on port 3051 (Go sync server for local-first apps)
- mana-notify-go on port 3040 (Go notification service)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:35:05 +01:00
Till JS
68004aafa5 feat(infra): add mana-crawler Go service to docker-compose
Port 3023, PostgreSQL + Redis, concurrency 5.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:23:37 +01:00
Till JS
feeebfb7c4 feat(infra): add mana-credits to docker-compose, fix port to 3061
Port 3060 was already taken by api-gateway. Updated mana-credits to 3061.

Changes:
- docker-compose.macmini.yml: Add mana-credits service with health check,
  traefik labels for credits.mana.how, depends on postgres
- docker-compose.macmini.yml: Add MANA_CREDITS_URL to mana-auth env
- Update all port references from 3060 to 3061 (config, Dockerfile, CLAUDE.md)
- Update better-auth.service.ts fallback URLs to 3061
- Update .env.development MANA_CREDITS_URL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:21:54 +01:00
Till JS
4b0f5a29fd feat(mana-search): rewrite search service from NestJS to Go
Replaces the NestJS mana-search service with a Go implementation for
lower resource usage and faster startup. All 7 API endpoints are 1:1
compatible (search, extract, bulk extract, engines, health, metrics,
cache clear). Uses go-readability for content extraction and
html-to-markdown for Markdown conversion. Redis cache with graceful
degradation, Prometheus metrics, and structured JSON logging.

Binary: 22 MB vs ~200+ MB node_modules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:58:40 +01:00
Till JS
c81527c57c fix(matrix-bot): remove port 4000 host mapping (conflicts with synapse)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:25:19 +01:00
Till JS
a70359dcce fix(gateway): use correct database name 'mana' + sslmode=disable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:09:27 +01:00
Till JS
7d1842e31f fix(gateway): use port 3060 (3010 = mukke, 3030 = chat)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:07:55 +01:00
Till JS
3589558b6c fix(gateway): change api-gateway port to 3030 (3010 used by mukke-backend)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:05:00 +01:00
Till JS
819568c3df feat(infra): consolidate 21 Matrix bots into Go binary + add Go API gateway
Replace 21 separate NestJS Matrix bot processes (~2.1 GB RAM, ~4.2 GB Docker images)
with a single Go binary using plugin architecture (8.6 MB binary, ~30 MB RAM).

New services:
- services/mana-matrix-bot/ — Go Matrix bot with 21 plugins (mautrix-go, Redis sessions)
- services/mana-api-gateway-go/ — Go API gateway (rate limiting, API keys, credit billing)

Deleted:
- 21 services/matrix-*-bot/ directories
- packages/bot-services/ and packages/matrix-bot-common/
- Legacy deploy scripts and CI build jobs

Updated:
- docker-compose.macmini.yml: new Go services, legacy bots removed
- CI/CD: change detection + build jobs for Go services
- Root package.json: new dev:matrix, build:matrix, test:matrix scripts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:03:00 +01:00
Till JS
c4d55209a4 feat(auth): add PasskeyManager component and production config
- PasskeyManager.svelte: reusable component for listing, registering,
  renaming, and deleting passkeys (German defaults, fully translatable)
- Production env: WEBAUTHN_RP_ID=mana.how and WEBAUTHN_ORIGINS for all
  *.mana.how subdomains in docker-compose.macmini.yml
- Local DB: passkeys table created via direct SQL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:49:57 +01:00
Till JS
6c1b472e59 feat(manadeck): add Docker deployment for backend and web
Create web Dockerfile and add both manadeck-backend (port 3009) and
manadeck-web (port 5023) to docker-compose.macmini.yml. Add Cloudflare
tunnel routes for manadeck.mana.how and manadeck-api.mana.how.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 15:13:45 +01:00
Till JS
37b061f7e6 perf(infra): stagger Docker health check start periods
Distribute start_period values across service groups to prevent
thundering herd of simultaneous health checks. Backends: 40-60s,
web: 20-45s, bots: 15-35s, monitoring: 10-30s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:31:00 +01:00
Till JS
9139b01d9f fix(infra): use 127.0.0.1 in nginx healthcheck (alpine resolves localhost to IPv6)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:38:10 +01:00
Till JS
e3115b302d feat(infra): add Cloudflare fallback plan + self-hosted landing pages
Two infrastructure improvements for tech independence:

1. Cloudflare Fallback Documentation (docs/CLOUDFLARE_FALLBACK.md):
   - Plan B: WireGuard + Caddy on Hetzner VPS (€3.79/mo)
   - Complete Caddyfile with all 30+ subdomains
   - Step-by-step failover checklist (~15 min to switch)
   - Plan C: Direct IP with ISP

2. Self-Hosted Landing Pages (eliminates Cloudflare Pages dependency):
   - Nginx container (mana-infra-landings) on port 4400
   - Multi-site config: each subdomain → separate dist/ folder
   - Build script: scripts/mac-mini/build-landings.sh
   - Cloudflare Tunnel ingress rules for 10 landing page domains
   - Storage: /Volumes/ManaData/landings/ on external SSD
   - Domains: it, chats, pics, zitares, presis, clocks,
     manadeck, nutriphi, citycorners, docs

Migration path: Build landings locally, set Cloudflare DNS to
tunnel instead of Pages, then decommission CF Pages projects.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:07:40 +01:00
Till JS
e060884881 fix(infra): add healthcheck start_period, restore shared-llm dep in project-doc-bot
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:48:13 +01:00
Till JS
e06e8cca59 fix(infra): use postgres -c flags instead of config_file override
The config_file override replaced the entire default PostgreSQL config
including listen_addresses, breaking inter-container communication.
Use inline -c flags instead which only override specific parameters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:42:42 +01:00
Till JS
fcd7c82ce4 fix(infra): simplify PostgreSQL backup to pg_dumpall + pg_basebackup
pgBackRest as Docker sidecar was overly complex (needs shared WAL
directory, stanza management, special entrypoint). Replace with a
simpler, proven approach using native PostgreSQL tools:

Backup container (postgres:16-alpine):
- Hourly: pg_dumpall | gzip (all databases as SQL, ~2 day retention)
- Daily 03:00: pg_basebackup -Ft -z (physical backup, 30 day retention)
- Auto-cleanup of old backups
- Storage: /Volumes/ManaData/backups/postgres/

Also: Remove pgbackrest.conf, simplify postgresql.conf (remove WAL
archiving config, keep performance tuning + replication for basebackup)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:39:20 +01:00
Till JS
7813e3b4bb fix(infra): use correct pgbackrest Docker image (woblerr/pgbackrest)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:34:44 +01:00
Till JS
39526918a3 feat(infra): add pgBackRest for PostgreSQL Point-in-Time Recovery
Replace simple pg_dumpall with pgBackRest PITR backup system.
This enables recovery to any second, not just the last daily dump.

Configuration:
- docker/postgres/postgresql.conf: WAL archiving + performance tuning
  (shared_buffers=512MB, effective_cache_size=2GB for 16GB Mac Mini)
- docker/postgres/pgbackrest.conf: stanza config + retention policy

Docker (docker-compose.macmini.yml):
- postgres: mount custom config, enable WAL archiving
- postgres-backup: new pgBackRest container
  - Storage: /Volumes/ManaData/backups/pgbackrest
  - Retention: 4 full + 14 differential (~4 weeks)
  - Compression: Zstandard (zst)

Backup Schedule:
- 03:00 daily: Full backup
- Every 6h: Differential (changes since last full)
- Every hour: Incremental (changes since last backup)
- Continuous: WAL archiving (every 60s)

Documentation (docs/POSTGRES_BACKUP.md):
- Complete restore procedures (full, PITR, single DB)
- First-time setup instructions
- Monitoring and alerting integration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:18:33 +01:00
Till JS
fc7d2942d0 feat(picture): add local image generation via mana-image-gen
Add LocalImageGenService that routes to the self-hosted FLUX.2 klein
model on the Mac Mini, eliminating Replicate API dependency for basic
image generation.

Changes:
- LocalImageGenService: wraps mana-image-gen HTTP API (/generate)
  with health checking, timeout handling, and GenerationResult compat
- GenerateService: routes to local or Replicate based on model config
  (replicateId starting with "local/" → LocalImageGenService)
- Local models always use sync mode (no webhooks needed, ~0.8s)
- Seed: add "FLUX.2 Klein (Lokal)" model with sortOrder -1 (shown first)
  - costPerGeneration: 0 (free, runs locally)
  - estimatedTimeSeconds: 1
- docker-compose: add IMAGE_GEN_SERVICE_URL env var for picture backend

Replicate remains available for premium models (Seedream, Nano Banana).
Local FLUX.2 klein becomes the default free option.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:38:30 +01:00
Till JS
124b4f7cba fix(infra): route GlitchTip DSNs internally to avoid Cloudflare roundtrip
All backend containers were sending error reports to glitchtip.mana.how
(via Cloudflare tunnel), creating ~6000 unnecessary external TCP connections
contributing to port exhaustion. Now routes directly to glitchtip:8020
within the Docker network.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:36:59 +01:00
Till JS
6cab9a3c24 fix(infra): remove n8n and increase health check intervals to fix port exhaustion
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>
2026-03-24 10:35:45 +01:00
Till JS
45063b88be feat(mana-llm): add Google Gemini fallback provider with auto-routing
Add Google Gemini as a fallback provider that activates automatically
when Ollama is overloaded or unavailable, ensuring LLM requests always
succeed even under load.

New provider (src/providers/google.py):
- Full LLMProvider implementation using google-genai SDK
- Chat completions (streaming + non-streaming)
- Vision/multimodal support (base64 images)
- Embeddings via text-embedding-004
- Model mapping: Ollama models → Gemini equivalents
  (gemma3:4b → gemini-2.0-flash, llava:7b → gemini-2.0-flash, etc.)

Auto-fallback routing (src/providers/router.py):
- Concurrent request tracking for Ollama (OLLAMA_MAX_CONCURRENT=3)
- When Ollama concurrent > max: route to Google automatically
- When Ollama fails: retry on Google with model mapping
- Health check caching (5s TTL) to avoid hammering Ollama
- Non-Ollama providers (openrouter, groq, together) are never fallback-routed
- Fallback info included in /health endpoint response

New config (src/config.py):
- GOOGLE_API_KEY: enables Google provider
- GOOGLE_DEFAULT_MODEL: default gemini-2.0-flash
- AUTO_FALLBACK_ENABLED: toggle fallback (default: true)
- OLLAMA_MAX_CONCURRENT: concurrent request threshold (default: 3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 22:44:09 +01:00
Till JS
43131986a9 fix(landing-builder): change prod port to 3050 (3030 used by chat)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 13:51:51 +01:00
Till JS
df0b849408 feat: add org landing page builder service
New service that generates static Astro landing pages for organizations
and deploys them to Cloudflare Pages at {slug}.mana.how.

Components:
- Landing Builder Service (NestJS, port 3030) with Astro template
- Admin UI in Manacore web dashboard at /organizations/[id]/landing
- TeamSection + ContactSection for shared-landing-ui
- Two org themes (classic dark, warm light)
- LandingPageConfig types in shared-types
- Docker + CI/CD integration for Mac Mini deployment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 13:20:10 +01:00
Till JS
0f93496364 feat(citycorners): add web lookup for new locations via mana-search
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>
2026-03-23 12:23:24 +01:00
Till JS
0e8d2026d3 fix(citycorners): change backend port to 3041 (3025 used by mana-llm)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:46:01 +01:00
Till JS
71b9339310 refactor: move llm-playground from services/ to apps/playground/
The LLM playground is a SvelteKit web app (frontend), not a backend
microservice. Moving it to apps/ follows the monorepo convention where
all user-facing apps live under apps/.

- Moved services/llm-playground/ → apps/playground/apps/web/
- Renamed package from @mana-llm/playground to @playground/web
- Updated Dockerfile paths for new location
- Updated docker-compose.macmini.yml build context
- Removed unused concurrently dependency
- Added parent package.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:25:54 +01:00
Till JS
7910737dd9 fix(mana-media): use prom-client directly instead of shared metrics package
mana-media uses NestJS 11 while shared-nestjs-metrics targets NestJS 10,
causing DynamicModule type incompatibility. Use prom-client directly with
a simple MetricsController to expose /metrics endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:06:09 +01:00
Till JS
1c5c2446f6 feat(citycorners): add city guide app for Konstanz with full monorepo integration
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>
2026-03-23 10:56:26 +01:00