Commit graph

2453 commits

Author SHA1 Message Date
Till JS
cf03743bae fix(ui): add left scroll offset to PageCarousel
First panel no longer sticks to the left edge. Left padding set to
calc(50vw - 240px) so the carousel starts with generous breathing room.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:16:20 +02:00
Till JS
ec7c563283 fix: remove stale references to deleted packages (shared-auth-stores, shared-profile-ui, shared-app-onboarding)
- Dockerfile.sveltekit-base: remove COPY lines for 3 deleted packages
- CI workflow: remove shared-profile-ui from SHARED_WEB_PATTERN
- manavoxel package.json: remove shared-auth-stores dependency
- uload CLAUDE.md: update auth store reference to shared-auth-ui
- APP_ONBOARDING.md: update package path to shared-ui/onboarding

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:15:58 +02:00
Till JS
a15b027e96 fix(shared-ui): block click event after drag to prevent detail view opening
After a successful drag-and-drop, the browser fires a click event on
the source element. This was opening the detail view overlay instead of
completing the drop. Now a one-time click blocker is added after drag
ends to swallow the spurious click.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:15:53 +02:00
Till JS
9b8814ea37 fix(ui): make homepage PageCarousel full-width (no side padding)
Break out of the layout's max-w-7xl px-4 container using negative
margins so the workbench carousel fills the entire viewport width.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:14:08 +02:00
Till JS
1bd001ec9a fix(manacore/web): restrict page drag to handle only, allow item DnD
Page reorder drag now only starts from the drag-handle icon, not from
anywhere in the page. This allows dragSource on list items (tasks,
events, contacts) to work without being intercepted by page reorder.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:11:58 +02:00
Till JS
f819b24596 fix: revert guestMode $state() — caused effect_update_depth_exceeded
Making guestMode reactive with $state() triggered an infinite effect
cascade: guestMode.notifications being accessed in the template created
a reactive dependency that, combined with 8+ AppPages each running
$effect for module loading, exceeded Svelte's effect update depth limit.

Root cause: GuestMode object has reactive getters that return new
references on each access. Wrapping it in $state() made every template
access trigger a re-render, which triggered more effects, creating an
unbounded cascade.

Fix: Keep guestMode as plain variable (non-reactive). The warning about
non_reactive_update is acceptable — guestMode is set once during init
and its properties are accessed imperatively, not reactively.

Also:
- Remove debug console.logs from AppPage, +page, +layout
- Keep onMount for workbench state loading (replaces $effect)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:10:21 +02:00
Till JS
6ced238571 chore: delete 25 web-archived directories, remove stale stubs, clean workspace config
- Delete all 25 apps/*/apps/web-archived/ directories (superseded by unified ManaCore app)
- Remove stale +page.server.ts stubs from teams, organizations, settings (always returned empty data)
- Simplify teams and organizations pages to static empty-state (no server load dependency)
- Delete empty apps/context/apps/mobile/components/variants/index.ts
- Remove commented-out apps-archived entries from pnpm-workspace.yaml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:03:49 +02:00
Till JS
e1077e261f fix(manacore/web): fix entity registration hang + registry type errors
- Make entity registration lazy (ensureEntitiesRegistered) to avoid
  circular imports at module load time
- Re-enable cross-module drop target in AppPage
- Fix Component type in app-registry to accept any props (AnyComponent)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:57:59 +02:00
Till JS
d8ce4eaf34 refactor: consolidate codebase — remove archived code, deduplicate packages, standardize middleware
- Delete 17 server-archived/ directories (consolidated into apps/api/)
- Delete apps-archived/ (clock, wisekeep) and services-archived/ (it-landing, ollama-metrics-proxy)
- Fix type safety: replace all `any` casts in cross-app-queries.ts with proper Local* types
- Remove duplicate shared-auth-stores package (identical copy of shared-auth-ui/stores/)
- Remove duplicate theme store from shared-stores (canonical version in shared-theme)
- Migrate memoro-server rate-limiter to shared-hono/rateLimitMiddleware
- Migrate uload-server JWT auth + error handler to shared-hono (authMiddleware, errorHandler)
- Migrate arcade-server error handling to shared-hono
- Merge shared-profile-ui and shared-app-onboarding into shared-ui
- Unify /clock route into /times/clock, remove redirect stubs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:55:58 +02:00
Till JS
7ee57b7afd feat(manacore/web): add entity descriptor system with cross-module drag-and-drop
Introduce EntityDescriptor pattern: each module declares how its items
can be displayed, dragged, dropped, and created from other modules.

- Entity types + registry with executeDrop orchestration
- Entity descriptors for todo, calendar, contacts
- List items are now draggable (dragSource) across pages
- Pages accept cross-module drops (event→todo, contact→calendar, etc.)
- Drops create new items + bidirectional manaLinks via shared-links
- LinkedItems component shows cross-module links in DetailViews
- Visual feedback: page glows purple on valid hover, green on success

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:42:38 +02:00
Till JS
d73591865c fix: move bottomChromeHeight after isTagStripVisible declaration
$derived cannot reference variables declared later in the script.
Moved the calculation below the isTagStripVisible $state declaration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:39:14 +02:00
Till JS
f0d5ba2128 fix: allow localhost in CSP connect-src during development
Dev env vars (_CLIENT suffixed) are empty, so localhost:3001 (auth),
localhost:3050 (sync), localhost:3060 (api) were blocked by CSP.

Added http://localhost:* and ws://localhost:* to connect-src when
NODE_ENV !== 'production'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:37:13 +02:00
Till JS
d368bd34b5 fix: replace bind:clientHeight with calculated bottom chrome height
bind:clientHeight + $effect setting CSS variable caused infinite reflow
loop: height change → CSS var → padding change → height change.

Now using $derived calculation from state (isCollapsed, isTagStripVisible)
instead of DOM measurement. No reflow loop possible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:34:42 +02:00
Till JS
9534d29967 fix: revert client sync from per-app SSE to HTTP polling
Per-app SSE connections exhaust the browser's 6-connection-per-origin
limit, causing the app to hang on load. Reverted to HTTP polling for
both eager and lazy apps.

SSE server endpoint remains available for future use as a single unified
stream (one connection for all apps, similar to the old unified WebSocket).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:31:53 +02:00
Till JS
81d5e83861 fix: revert @const to svelte:component (invalid placement in div)
@const can only be used inside {#if}, {#each}, etc. — not directly in
a <div>. Reverted ActionZone and AuthGateModal back to <svelte:component>
which works correctly (the deprecation warning is less important than
a broken app).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:04:18 +02:00
Till JS
c21793baaf fix: resolve all 40 Svelte dev warnings for clean startup
- Add $state() to 4 reactive variables (guestMode, emailInput, passwordInput, searchInputElement)
- Replace 3 deprecated <svelte:component> with direct component references
- Fix 8 a11y issues: add ARIA roles, tabindex, keyboard handlers to click-handler divs
- Remove 22 unused CSS selectors across 8 shared-ui components

Zero warnings on dev startup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:01:17 +02:00
Till JS
2bd8f0babf fix: change unified API default port from 3050 to 3060
Port 3050 is used by mana-sync. The unified API server gets its own port.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:54:07 +02:00
Till JS
1245fdc077 feat(manacore/web): enhance Times & Zitare pages, add DetailViews, clean up homepage
- Times ListView: inline timer with start/stop, name input, live elapsed display
- Times DetailView: editable entry with duration (h/m/s), project, billable, delete
- Zitare ListView: tap-to-cycle quotes, inline fav button, tag drag-and-drop support
- Zitare DetailView: full quote view with category, author bio, share, favorite
- Homepage: remove tag bar (available via PillNav), carousel uses full width
- Register both DetailViews in app-registry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:52:27 +02:00
Till JS
c5906e4c29 fix: update all dev scripts to use unified API server
Replace 15 individual dev:*:server scripts with single dev:api command.
Update all dev:*:full, dev:*:app, dev:*:local scripts to start the
unified API server (apps/api) instead of archived individual servers.

dev:manacore:servers now starts: auth + sync + api (3 processes instead of 8)
dev:manacore:full now works without errors.

Removed: wisekeep scripts (project archived), broken server references.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:51:46 +02:00
Till JS
9966e9edeb fix(ui): remove Observatory, API Keys, Gifts from PillNav
These are secondary pages accessible via settings/profile, not primary navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:40:32 +02:00
Till JS
f7ee9ead44 fix(branding): rename ManaContacts to Kontakte
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:38:53 +02:00
Till JS
019f3eb9fd feat(manacore/web): show tags in detail views with click-to-remove
Display assigned tags as colored pills in todo, calendar, contacts
DetailViews. Clicking a tag pill removes it from the item. Hover turns
the X icon red for clear affordance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:37:41 +02:00
Till JS
794424d6ad fix(ui): open all AppDrawer apps in new tab
All app clicks in the PillNav app drawer now open in a new tab via
window.open('_blank'). Previously internal URLs used window.location.href
(same tab navigation) which was confusing in the unified app context.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:36:26 +02:00
Till JS
0d142efa3c feat(manacore/web): show tags as labeled pills instead of dots
Replace tiny 6px tag dots with readable pills showing colored dot +
tag name. Uses color-mix for subtle tinted background per tag color.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:30:44 +02:00
Till JS
e9d4cbfdba fix(manacore/web): fix tag drag-and-drop — use reactive .value instead of .subscribe()
useAllTags() returns a Svelte 5 runes object with .value, not an
Observable with .subscribe(). Also fix getTagsByIds() calls to pass
the allTags array as first argument.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:26:22 +02:00
Till JS
976fb5fdf8 fix(ui): move nav toggle to right side of InputBar, make it larger
- Add rightAction snippet prop to QuickInputBar (InputBar.svelte)
- Move toggle from leftAction to rightAction (renders after submit button)
- Increase toggle size from 28px to 36px for better tap target

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:21:47 +02:00
Till JS
06ebc6271d feat(manacore/web): add tag drag-and-drop to workbench pages
- Mount DragPreview + draggable tag bar on workbench homepage
- Add dropTarget on list items in todo, calendar, contacts ListViews
- Show assigned tags as colored dots on list items
- Tags can be dragged from the tag bar onto any item to assign them
- Drop target highlights with module-colored outline on hover

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:20:54 +02:00
Till JS
fb5271acc8 fix(ui): move PillNav toggle inside QuickInputBar via leftAction snippet
Toggle button now renders inside the InputBar pill (left side) instead of
as a separate element next to it. Uses the existing leftAction snippet prop.

- Button is 28px circle, subtle background, no border/shadow (lives inside pill)
- Remove bottom-stack-row wrapper (no longer needed)
- Cleaner visual: toggle is part of the input bar, not floating beside it

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:15:29 +02:00
Till JS
81f781c133 fix(ui): move Tags to leftmost in PillNav, match toggle button to InputBar style
- Tags pill moved to first position in nav items (leftmost)
- Toggle button: 44px round (matches InputBar height), same border-radius
  (9999px), same backdrop-filter blur, same box-shadow, theme-aware colors
- Button sits directly next to QuickInputBar with no gap, vertically centered

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:08:24 +02:00
Till JS
b3dd8cded9 fix(ui): dynamic bottom-chrome-height for tabs, notifications, main content
The bottom-stack container now exports its height as --bottom-chrome-height
CSS custom property (via bind:clientHeight + $effect on :root). All elements
that need to position above the bottom chrome read this variable:

- PageCarousel minimized-tabs: bottom: var(--bottom-chrome-height)
- NotificationBar: bottom: var(--bottom-chrome-height)
- Main content padding: calc(var(--bottom-chrome-height) + 2rem)

This ensures tabs, notifications, and content never overlap with the
bottom stack regardless of PillNav collapse state or TagStrip visibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:59:16 +02:00
Till JS
b415567dfa refactor(ui): unified bottom-stack container for PillNav, QuickInput, TagStrip
Replace 4 independent position:fixed elements with one flex container that
stacks them naturally from bottom to top. Elements push each other
automatically — no more hardcoded offsets or z-index conflicts.

Stack order (bottom → top):
1. PillNavigation (collapsible)
2. TagStrip (togglable)
3. QuickInputBar + toggle button row

Shared-UI changes:
- PillNavigation: add positioning='fixed'|'static' prop
- QuickInputBar: add positioning='fixed'|'static' prop
- TagStrip: add positioning='fixed'|'static' prop
- All default to 'fixed' for backward compatibility

Layout changes:
- Wrap all bottom elements in .bottom-stack (position:fixed, flex-column)
- Remove hardcoded bottomOffset calculations
- Toggle button is now inline next to QuickInputBar (not separately positioned)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:52:40 +02:00
Till JS
bed2060ba5 fix(manacore/web): fix height resize using element's current height as start value
When heightPx is not yet set, use the element's actual offsetHeight
instead of 0 so the first drag correctly adjusts height.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:51:54 +02:00
Till JS
b66a26810f feat(manacore/web): add 2D resize (width + height) to workbench pages
Extend PageShell resize handle to support diagonal drag for both
width and height. Height is persisted per page in workbench settings.
Resize cursor changed from ew-resize to nwse-resize.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:49:39 +02:00
Till JS
ef0c834a2b feat(ui): add PillNav toggle button next to QuickInputBar
Small floating button (▼/▲) at the bottom-right that toggles PillNav
visibility. QuickInputBar's bottomOffset adjusts dynamically when nav
is collapsed (70px → 12px), reclaiming vertical space.

- Button uses existing handleCollapsedChange() with localStorage persistence
- Smooth transitions on position and rotation
- Glass-morphism style (blur + semi-transparent background)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:45:43 +02:00
Till JS
9ea7e482f0 refactor(manacore/web): rename AppView → ListView across all 24 modules
Consistent naming: ListView.svelte + DetailView.svelte as a pair.
Update app-registry.ts and splitscreen/registry.ts imports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:45:11 +02:00
Till JS
fed38efb8b fix(sync): fix SSE live updates — 2 bugs found during E2E testing
Bug 1: NotifyUser() early-returned when no WebSocket clients existed,
skipping SSE subscriber notifications entirely. Fixed by restructuring
to check WS clients and SSE subscribers independently.

Bug 2: SSE stream cursor defaulted to client's `since` parameter when
no initial data existed. If `since` was in the future (or very recent),
live updates had created_at < cursor and were silently filtered out.
Fixed by defaulting cursor to now() when no initial data is returned.

Bug 3: NotifyUser used original sseSubs slice instead of sseSubsCopy
after releasing the read lock (race condition).

Verified E2E: Push from client A → SSE stream on client B receives
live change event with correct data within ~1 second.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:39:46 +02:00
Till JS
4cb1bda852 feat(manacore/web): add overlay detail views for cards, storage, presi
Add inline-editable DetailViews with auto-save for:
- cards: deck details with color, description, public toggle
- storage: file details with rename, favorite, size/type info
- presi: presentation deck details with slide count

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:26:57 +02:00
Till JS
650dea5e1d feat(manacore/web): add overlay detail views for 8 more modules
Add inline-editable DetailViews with auto-save for:
planta, inventar, skilltree, memoro, questions, uload, mukke, citycorners

Wire AppView list items to open overlay via navigate() with sibling
navigation support. Fix citycorners table names (cityLocations→ccLocations).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:57:09 +02:00
Till JS
a08f1501f2 feat(manacore/web): add overlay detail views with inline editing, consolidate routes
- Remove /dashboard (redundant), merge /home into / (app root)
- Update all redirects and navigation references accordingly
- Add panel navigation stack with overlay detail views for workbench
- Implement inline-editable DetailViews for todo, calendar, contacts
- Auto-save on blur, prev/next navigation with sibling arrows
- Fix minimized tabs z-index behind quick input bar
- Fix showNewEvent undefined error in calendar AppView

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:43:05 +02:00
Till JS
c8daa443fc feat(sync): replace WebSocket with SSE client for real-time sync
Client now connects to GET /sync/{appId}/stream via fetch + ReadableStream
instead of WebSocket + HTTP pull. Each app gets its own SSE connection that
delivers initial sync data + live updates in one persistent stream.

Changes:
- Remove WebSocket connection (connectUnifiedWs)
- Add connectSSE() per app using fetch + ReadableStream
- Parse SSE events (changes, heartbeat) from streamed response
- Auto-reconnect on disconnect with WS_RECONNECT_DELAY
- Fallback to polling if SSE endpoint not available
- ensureAppSynced() connects SSE for lazy apps on first visit
- handleOnline() reconnects all active SSE streams
- handleOffline() aborts all SSE connections

Benefits: 1 connection instead of 2 (WS + HTTP), data delivered instantly
without notification → pull round-trip, works through HTTP proxies/CDN.

Push (POST /sync/{appId}) remains unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:27:30 +02:00
Till JS
068a64b275 feat(sync): add SSE streaming endpoint for real-time sync
New endpoint GET /sync/{appId}/stream sends Server-Sent Events with
change data directly, replacing the WebSocket notification + HTTP pull
round-trip pattern.

Server (Go):
- HandleStream() in handler.go: SSE endpoint with initial sync + live streaming
- Hub.Subscribe()/Unsubscribe() in hub.go: channel-based SSE subscriber system
- Notification type for type-safe SSE events
- convertChanges() helper extracted from duplicated code
- WriteTimeout set to 0 for SSE long-lived connections

Protocol: Client connects to /sync/{appId}/stream?collections=a,b&since=...
Server sends initial changes, then streams live changes as other clients sync.
Heartbeat every 30s keeps connection alive. Push still uses POST /sync/{appId}.

WebSocket remains available as fallback (not removed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:24:10 +02:00
Till JS
8ba3c4c10d feat(sync): partial sync — lazy collection loading on module visit
Only sync eager apps at startup (manacore, todo, calendar, contacts,
tags, links — needed for dashboard widgets). All other apps are lazy:
their collections sync on first module route visit.

Reduces startup pull requests from ~108 to ~20-30. Lazy apps get
synced when the user navigates to their module via ensureAppSynced().

- Add EAGER_APPS config set in sync.ts
- startAll() only starts pull for eager apps
- ensureAppSynced() starts pull + periodic sync for lazy apps
- Route-based trigger in +layout.svelte $effect

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:19:20 +02:00
Till JS
f7f5c9eb3a feat(sync): add pull pagination with hasMore flag
Server now returns hasMore: true when there are more than 1000 changes
pending for a collection. Client continues pulling in a loop until
hasMore is false, using the last row's timestamp as cursor.

Prevents data loss after long offline periods where >1000 changes
accumulated for a single collection.

Server changes (Go):
- GetChangesSince() accepts limit parameter
- HandlePull() fetches limit+1, trims, sets hasMore
- SyncedUntil uses last row's timestamp when paginating

Client changes (TypeScript):
- Pull loop: while (hasMore) { fetch → apply → advance cursor }
- Cursor only persisted after all pages fetched

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:17:20 +02:00
Till JS
03434c2802 refactor(auth): absorb shared-auth-stores into shared-auth-ui
Merge the auth store factories (createManaAuthStore, createAuthStore) from
@manacore/shared-auth-stores into @manacore/shared-auth-ui, reducing
from 3 auth packages to 2.

- Copy store files into shared-auth-ui/src/stores/
- Re-export store factories and types from shared-auth-ui
- Update imports in manacore/web and arcade/web
- Remove shared-auth-stores from active package.json dependencies

Result: @manacore/shared-auth (core, platform-agnostic) +
        @manacore/shared-auth-ui (Svelte components + stores)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:43:42 +02:00
Till JS
baca70155a fix(contacts): create self-contact in guest mode too
ensureSelfContact now works without profile data — creates a minimal
"Ich" contact in guest/local mode, syncs with profile when authenticated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:42:46 +02:00
Till JS
31d168c02b feat(contacts): add self-contact with profile sync and "Mein Profil" page
- Auto-create a self-contact (fixed ID) from the user's auth profile
  on first visit to /contacts, synced on each load
- Pin self-contact to top of all contact lists with "Du" badge
- Add "Mein Profil" carousel page showing a profile card view
- Add page option to ContactPagePicker

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:39:54 +02:00
Till JS
3556fc18be chore: archive 17 standalone app servers (replaced by unified API)
All app compute servers have been consolidated into apps/api/ (unified
Hono/Bun server). Old servers moved to apps/*/apps/server-archived/.

Archived: cards, chat, contacts, context, calendar, guides, moodlit,
mukke, news, nutriphi, picture, planta, presi, questions, storage, todo, traces

Still active: uload (separate domain), memoro (Supabase-based)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:37:45 +02:00
Till JS
9363063cd7 feat(api): port remaining 12 modules to unified API server
Complete consolidation of all 15 app servers into one Hono/Bun process.

Modules added: chat, context, picture, storage, todo, planta, nutriphi,
guides, moodlit, news, traces, presi

Total: 15 modules, one server, one port (3050), ~2400 LOC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:34:08 +02:00
Till JS
eb97378438 feat(manacore/web): add page carousel to contacts module
Add ContactPage and ContactPagePicker components using the shared
PageCarousel/PageShell system. Available pages: Alle Kontakte,
Favoriten, Bald Geburtstag, Mit E-Mail, Mit Telefon, Mit Unternehmen,
Mit Adresse, Kürzlich hinzugefügt. Default opens "Alle" + "Favoriten".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:21:07 +02:00
Till JS
aa93c54391 feat(api): create unified API server with first 3 modules
New consolidated Hono/Bun API server at apps/api/ that replaces individual
app servers. One process, one port, one auth middleware, one container.

Modules ported:
- calendar: RRULE expansion, ICS import, Google Calendar (stub)
- contacts: avatar upload (S3), vCard import/parsing
- mukke: audio upload/download presigned URLs, batch cover art

Architecture: each module registers routes under /api/v1/{module}/*
using the shared-hono middleware stack (auth, rate limit, error handler).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:12:15 +02:00