Pre-launch theme system audit found multiple parallel layers in themes.css
(--theme-X full hsl strings, --X partial shadcn aliases, --color-X populated
by runtime store with raw channels) plus dead-code companion files. The
inconsistency caused light-mode regressions when scoped-CSS consumers
wrote `var(--color-X)` standalone — the variable holds raw HSL channels
which is invalid as a color value, browser fell back to inherited (white).
Rewrite to one consistent layer:
- Source of truth: --color-X defined as raw HSL channels (e.g.
`0 0% 17%`) in :root, .dark, and all variant [data-theme="..."]
blocks. Matches the format the runtime store
(@mana/shared-theme/src/utils.ts) writes, eliminating the
static-fallback-vs-runtime mismatch and the corresponding flash
of unstyled content on hydration.
- @theme inline uses self-reference + Tailwind v4 <alpha-value>
placeholder so utility classes generate correctly AND opacity
modifiers work: `text-foreground/50` → `hsl(var(--color-foreground) / 0.5)`.
- @layer components (.btn-primary, .card, .badge, etc.) wraps
var(--color-X) refs with hsl() — they were broken in light mode
too for the same reason.
Convention going forward (also documented in the file header):
1. Markup: use Tailwind utility classes (text-foreground, bg-card, …)
2. Scoped CSS: hsl(var(--color-X)) — always wrap with hsl()
3. NEVER raw var(--color-X) in CSS — that's the bug pattern
Net file: 692 → 580 LOC. Single source layer, no indirection.
Also delete dead companion files (zero imports anywhere):
- tailwind-v4.css (had broken self-reference, never imported)
- theme-variables.css (legacy hex-based palette)
- components.css (legacy component utilities)
- index.js / preset.js / colors.js (Tailwind v3 preset format,
irrelevant under Tailwind v4)
package.json exports map shrinks accordingly to just `./themes.css`.
Consumers using `hsl(var(--color-X))` (~379 files across mana-web,
manavoxel-web, arcade-web) keep working unchanged — the public API
name `--color-X` is preserved. Only the broken pattern `var(--color-X)`
(~61 files) needs a follow-up sweep, handled in a separate commit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
All standalone SvelteKit web apps have been superseded by the unified
ManaCore app (apps/manacore/apps/web). Moved to web-archived/ within
each project to preserve history while removing from active workspace.
Archived: calc, cards, chat, citycorners, contacts, context, guides,
inventar, moodlit, mukke, news, nutriphi, photos, picture, planta,
presi, questions, skilltree, storage, times, zitare, todo, calendar,
uload, memoro
Moved to apps-archived/: wisekeep (not integrated, inactive)
Kept active: manacore (unified), matrix, manavoxel, arcade (separate containers)
Server, landing, and package directories remain active for each project.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add URL validation (must be valid http/https), short code uniqueness check,
custom code format validation, maxClicks >= 1, expiresAt must be future
- Migrate uload-server click tracking from sync_changes to uload.clicks table
for performant analytics with SQL indexes on link_id, clicked_at, country
- Migrate analytics queries from JSON aggregation on sync_changes to direct
SQL on uload.clicks (typed columns instead of data->>'field' extraction)
- Make short URL domain configurable via PUBLIC_ULOAD_DOMAIN env var
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The uload-server reads links from sync_changes (local-first via mana-sync)
and never used the Drizzle schema tables (users, accounts, workspaces, links).
Strip uload-database package to only the clicks table which is needed for
performant analytics aggregation with proper SQL indexes.
- Remove 5 unused tables (users, accounts, workspaces, links, relations)
- Keep only uload.clicks with indexes on link_id, clicked_at, country, device_type
- Simplify uload-database package from ~190 LOC to ~40 LOC
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mirrors the frontend unification (single IndexedDB) on the backend.
All services now use pgSchema() for isolation within one shared database,
enabling cross-schema JOINs, simplified ops, and zero DB setup for new apps.
- Migrate 7 services from pgTable() to pgSchema(): mana-user (usr),
mana-media (media), todo, traces, presi, uload, cards
- Update all DATABASE_URLs in .env.development, docker-compose, configs
- Rewrite init-db scripts for 2 databases + 12 schemas
- Rewrite setup-databases.sh for consolidated architecture
- Update shared-drizzle-config default to mana_platform
- Update CLAUDE.md with new database architecture docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Links created from other apps (calendar, contacts, etc.) now carry a source
field. Added source filter dropdown and source badges in the link list.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each app's PillNavigation now has spotlightActions with app-specific
quick actions (create, navigate, settings). Users can press Cmd+K / Ctrl+K
from any app to search apps, navigate, and trigger actions.
Apps: todo, calendar, contacts, chat, picture, clock, zitare, cards,
storage, manacore, mukke, presi, context, questions, photos, planta,
citycorners, guides, calc, moodlit, matrix, uload, arcade
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a tiered access control system so apps can be released
gradually (founder → alpha → beta → public) without extra infrastructure.
Users are gated at the AuthGate level based on their tier vs the app's
requiredTier. All apps remain deployed and reachable, but only users
with sufficient tier can enter.
- Add accessTier enum + column to users schema (default: 'public')
- Add tier claim to JWT payload in better-auth config
- Add requiredTier field to ManaApp interface + all 25 apps
- Add hasAppAccess(), getAccessibleManaApps(), ACCESS_TIER_LABELS
- Update AuthGate with tier check + access denied screen
- Update getPillAppItems + Home page to filter by user tier
- Update all 22 app layouts to pass user tier to PillNav
- Add admin API: GET/PUT /api/v1/admin/users/:id/tier
- Document access tier system in CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sync integration:
- Redirect service reads links from mana-sync's sync_changes table
- Analytics service queries clicks from sync_changes
- Click tracking writes to sync_changes (visible to all clients)
- Public profile reads from sync_changes
- Server DB points to mana_sync database (not separate uload DB)
- Removed uload-database dependency from server
Stripe:
- Real Stripe checkout session creation (monthly/yearly)
- Webhook handler with signature verification
- Webhook route bypasses JWT auth
Documentation:
- Root CLAUDE.md: added uload to project table, dev commands, local-first list
- mana-sync CLAUDE.md: added uLoad, Taktik, Calc to connected apps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Docker:
- Dockerfile for web (sveltekit-base, port 5029) and server (Bun, port 3041)
- docker-compose.macmini.yml entries for uload-server + uload-web
- Landing page deploy script (Cloudflare Pages)
Documentation:
- Complete CLAUDE.md rewrite reflecting local-first + Hono architecture
Features:
- Bulk select/deselect all/toggle active/delete
- Link expiry date (datetime picker)
- Password-protected links
- Max clicks limit
- Badges for password/expiry/maxClicks on link items
- Advanced options collapsible section in create & edit forms
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Features added to links page:
- QR code generation with modal and download
- Edit modal for title, URL, UTM parameters
- Collapsible UTM parameter fields (source, medium, campaign)
- Click count links to analytics page
- Confirm dialog before delete
Analytics dashboard improvements:
- Country breakdown with progress bars
- Device breakdown with percentages
- Time period switcher (7/30/90 days)
- Tooltip on timeline bars
- Back navigation
Other:
- Public profile page /u/[username] via Hono endpoint
- i18n setup with svelte-i18n (DE/EN locale files)
- PWA support via @vite-pwa/sveltekit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add auth store using createManaAuthStore
- Wrap app layout with AuthGate (allowGuest=true)
- Add GuestWelcomeModal and SessionExpiredBanner
- Start sync on login, stop on logout
- Rewrite login/register/forgot-password to use shared auth UI
- Remove all PocketBase auth references
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move from apps-archived/ to apps/
- Delete NestJS backend, PocketBase, old scripts and docs
- Create Hono/Bun redirect server (click tracking, analytics API)
- Create @manacore/uload-database shared Drizzle schema package
- Add local-first store (Dexie.js) for links, tags, folders
- Rewrite Links and Tags pages to use IndexedDB
- Simplify hooks, layouts, remove all server-side data loading
- Add dev scripts: dev:uload:web, dev:uload:server, dev:uload:local
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>