Commit graph

2133 commits

Author SHA1 Message Date
Till JS
c02e2649af docs: add Phosphor icon guidelines to code-style.md
Document the icon standard: always use Phosphor components from
@manacore/shared-icons, never inline SVG paths. Lists exceptions
(spinners, brand logos, charts, decorative SVGs).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:46:39 +02:00
Till JS
14df2cd9e2 fix(auth): declare accessTier as additionalField so Better Auth includes it in user object
Without this, Better Auth's definePayload receives a user object
without the custom accessTier column, causing the JWT tier claim
to always default to 'public'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:46:29 +02:00
Till JS
47f981fbc4 refactor(shared-ui): replace remaining inline SVGs with Phosphor icons
Migrate 41 inline SVG icons to Phosphor components across 21 shared-ui
files including CommandBar, InputBar, Sidebar, AudioPlayer, PageHeader,
Select, TagBadge, SettingsRow, and more.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:44:50 +02:00
Till JS
25e39620ec refactor(apps): final SVG-to-Phosphor pass for photos, clock, mukke, inventar
Replace remaining inline SVG icons in photos (25 SVGs), mukke player
controls, clock world-clock, and inventar settings. All remaining
inline SVGs are now exclusively spinners, brand logos, or dynamic
icon rendering via {@html}.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:41:43 +02:00
Till JS
59e535af94 refactor(todo): move ViewSelector behind Layout pill, simplify homepage
- Move board view management (ViewSelector, activeViewId, ViewEditorModal)
  from +page.svelte to +layout.svelte
- Layout pill in PillNav now toggles ViewSelector strip visibility
- +page.svelte reduced to minimal BoardViewRenderer with context-provided view
- Provide activeView via Svelte context from layout
- Fix broken import in TaskItem.svelte (linter artifact)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:41:28 +02:00
Till JS
504e7756a7 refactor(apps): automated SVG-to-Phosphor migration across all apps
Script-based migration of inline SVG icons to Phosphor components.
Covers todo, manacore, mukke, chat, zitare, times, citycorners,
inventar, uload, playground, presi, picture, moodlit, storage, news,
wisekeep, clock, matrix, manadeck, skilltree, and photos.

~190 SVGs replaced across 115 files. Remaining SVGs are spinners,
brand logos, or decorative/chart SVGs that don't map to Phosphor.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:35:17 +02:00
Till JS
f58d58ff99 refactor(apps): replace inline SVGs with Phosphor icons across 19 apps
Migrate inline SVG icon paths to Phosphor components in chat, zitare,
times, citycorners, inventar, manacore, todo, playground, presi, and
more. Part of repo-wide icon unification effort.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:18:20 +02:00
Till JS
3f2e6a3ee5 feat(todo): unify view modes into single route with Fokus/Übersicht/Matrix layouts
Consolidate the two separate view systems (homepage paper pages + /kanban board)
into one unified system on `/`. All three layout modes (Fokus, Übersicht, Matrix)
share the same LocalBoardView data model and BoardViewRenderer, with layout
switching via PillNav tabs instead of route navigation.

- Add FokusLayout component (scroll-snap paper sheets with DnD)
- Add activeLayoutMode setting (fokus/uebersicht/matrix)
- Add layoutOverride prop to BoardViewRenderer
- Rewrite homepage to use BoardViewRenderer + ViewSelector
- Unify DnD type to 'task-dnd' across all layouts
- Convert PillNav from route-based to state-based view switching
- Delete /kanban route (redirect to / with uebersicht mode)
- Update PWA shortcuts, settings, onboarding, help content

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:03:58 +02:00
Till JS
9f6e463eae refactor(calendar,contacts): replace inline SVGs with Phosphor icons
Migrate all inline SVG icon paths to Phosphor components from
@manacore/shared-icons across 38 files. Only spinners (loading
animations) and brand logos (Google) remain as inline SVGs.

Calendar: 0 inline icon SVGs remaining
Contacts: 6 remaining (3 spinners, 1 spinner, 2 Google logos)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 12:01:18 +02:00
Till JS
e68e5c6e5f refactor(shared-ui): unify icon system to Phosphor, remove SVG path fallbacks
Replace duplicate SVG d-path icon maps with Phosphor component lookups
in PillNavigation, PillTabGroup, PillViewSwitcher, and NavVisibilitySettings.
Removes ~250 lines of redundant SVG path data.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 11:11:51 +02:00
Till JS
a545bb6d2f refactor(todo): move edit button from FAB to PillNav, share state via context
- Remove floating edit FAB from +page.svelte
- Add "Layout" pill (grid icon) to PillNav, only visible on homepage
- Share editMode state between layout and page via Svelte context
- Label toggles between "Layout" and "Fertig" when active
- Escape key exits edit mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 11:02:19 +02:00
Till JS
69915a7ca0 feat(todo): horizontal paper pages with inline edit mode
- Each section (priority/date) is its own paper sheet, scrollable horizontally
- Edit FAB (pencil icon, bottom right) toggles inline page editor
- Edit mode: rename pages, configure icon/filters/priorities per page,
  reorder with arrow buttons, add/remove pages
- Three page modes: priority (Eisenhower), date, custom
- Page width selector (S/M/L/XL) visible only in edit mode
- 10 configurable page icons
- Settings stores pageMode, pageWidth, customPages in localStorage
- Fix structuredClone error with Svelte proxies (use JSON round-trip)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 22:39:46 +02:00
Till JS
2783cc3cd8 fix(inventar): import ThemePage from @manacore/shared-theme-ui
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:09:11 +02:00
Till JS
9df8b5945b fix(inventar): import HelpPage from @manacore/help, not shared-ui
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:05:52 +02:00
Till JS
8ffd2ce774 fix(mana-auth): add session-to-token endpoint and return JWT from login
The client (shared-auth) calls /api/v1/auth/session-to-token for SSO and
2FA flows, but this endpoint was never implemented. Also, the login endpoint
returned raw Better Auth session data instead of the expected
{ accessToken, refreshToken } format.

- Add POST /api/v1/auth/session-to-token endpoint
- Fix login to generate JWT via Better Auth's /api/auth/token
- Fix refresh to return JWT instead of raw session data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:56:35 +02:00
Till JS
0d6005dbcc fix(inventar): import FeedbackPage from @manacore/feedback, not shared-ui
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:56:19 +02:00
Till JS
b737240ec1 feat(auth): add access tier system for phased app releases
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>
2026-03-30 21:50:06 +02:00
Till JS
4f68215e68 fix(docker): symlink all @manacore packages in sveltekit-base image
pnpm skips workspace linking when glob patterns like apps/*/apps/* from
pnpm-workspace.yaml match no directories. This caused @manacore/feedback
and other packages to be copied but not linked in node_modules. Fix adds
a post-install step that creates symlinks for all packages/* entries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:49:46 +02:00
Till JS
4a5fe3bee8 feat(ux): notepad design, keyboard navigation, contenteditable across todo/calendar/contacts
Todo: Notepad redesign (A4 width, lined paper, red margin), contenteditable titles,
Arrow/Tab navigation between tasks, circular navigation with QuickInputBar,
debug borders (Ctrl+Shift+D), removed hover effects, collapsed completed section.

Calendar Agenda: contenteditable event titles, Arrow/Tab navigation, circular
navigation with InputBar, removed hover effects, separate detail button.

Contacts Alphabet: contenteditable contact names, Arrow/Tab navigation, circular
navigation with InputBar, removed card hover, avatar as detail button.

Guidelines: new sections for list navigation, contenteditable patterns, debug borders.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:37:56 +02:00
Till JS
b9232438cf fix: nested button in inventar list view, uload-server port 3041→3070
- inventar-web: second nested <button> in list view also converted to
  <div role="button"> to fix Svelte 5 HTML validation
- uload-server: port changed from 3041 to 3070 to avoid conflict with
  Forgejo which also binds port 3041

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:37:18 +02:00
Till JS
df19d3acc4 fix: Docker build failures for mana-media and inventar-web
- mana-media: strip workspace devDep before bun install (shared-drizzle-config
  is only needed for drizzle-kit, not at runtime)
- inventar-web: replace nested <button> with <div role="button"> to fix
  Svelte 5 HTML validation error during build

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:31:52 +02:00
Till JS
dffb5eb9dc docs(infra): update Forgejo docs to mirror-only, remove obsolete workflows
- Remove .forgejo/workflows/ (go-services, smoke-tests) — Forgejo is
  mirror-only, no CI/CD
- Remove setup-forgejo-runner.sh — runner removed (no macOS binary)
- Update MAC_MINI_SERVER.md: document Forgejo as mirror, fix CI/CD section
- Update FIX_COLIMA_MOUNTS.md: add root cause fix note (startup.sh)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:44:54 +02:00
Till JS
b44bd44666 fix(ci): stash local changes before mirror pull to prevent merge conflicts
The mirror workflow runs git pull on the server's working directory,
which fails if there are uncommitted changes (e.g., from manual edits).
Adding git stash before pull prevents this.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:33:21 +02:00
Till JS
81ae60d184 refactor(infra): remove Forgejo CD, keep as mirror-only
Forgejo runner has no macOS binary — Docker-based runner can't access
host filesystem/SSH needed for CD. GitHub CD via native self-hosted
runner handles all deployments. Forgejo remains a push-mirror for
backup and visibility.

- Remove .forgejo/workflows/cd-macmini.yml
- Remove forgejo-runner service from docker-compose
- Update mirror workflow comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:17:41 +02:00
Till JS
7ff72d6c2c feat(monitoring): auto-prune Docker + node_modules, 15-min disk check interval
- check-disk-space.sh: always prune dangling images, unused volumes, and
  build cache >7 days on every run (not just at critical threshold)
- check-disk-space.sh: auto-remove node_modules if found on server
  (never needed — Docker builds inside containers)
- disk-check launchd: reduce interval from 60min to 15min to catch
  disk issues faster (yesterday we hit 100% before hourly check caught it)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:14:13 +02:00
Till JS
4e370911e8 feat(monitoring): disk metrics via Pushgateway, Loki in Master Overview, Colima move script
- check-disk-space.sh now pushes mac_disk_used_percent + mac_colima_disk_used_gb
  to Pushgateway every hour so vmalert can alert on real macOS disk usage
- alerts.yml: replace broken node-exporter disk alerts with Pushgateway-based ones
- master-overview.json: add "Recent Errors (Loki)" section with live error log
  stream, error rate timeseries and top error sources barchart
- move-colima-to-external-ssd.sh: guided script to move 200GB Colima VM
  datadisk from internal SSD to /Volumes/ManaData (3.6TB external SSD)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:03:33 +02:00
Till JS
be1096ec85 fix(monitoring): update disk alerts to use mac_disk_used_percent metrics
node-exporter runs in VM and can't see host macOS disks directly.
Use custom mac_disk_used_percent metrics pushed via Pushgateway instead.
Also add ColimaVMDiskLarge alert when datadisk exceeds 150 GB.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 20:01:46 +02:00
Till JS
5fc34dafe8 fix(promtail): move monitoring drop from relabel to pipeline_stages
relabel drop removed the entire stream before labels were set, causing
the "at least one label pair required" error. pipeline_stages drop runs
after labels are established, which is correct for filtering by tier.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 19:50:04 +02:00
Till JS
aa26ae12ad fix(manadeck): switch web adapter from adapter-auto to adapter-node
adapter-auto does not produce a build/ directory for node deployments,
causing Docker builds to fail. Switch to adapter-node like all other apps.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:48:39 +02:00
Till JS
9de71c4be3 fix(citycorners): declare searchQuery and searching as $state
Both variables were used with bind:value but not declared.
Svelte 5 requires bind targets to be declared with $state().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 19:39:14 +02:00
Till JS
8049a53a2b fix(todo): fix DnD reorder flicker and remove project dot indicator
- Replace key-based sync with ID-set comparison to prevent $effect from
  reverting drag-and-drop reorders; use dropInProgress flag with 1s timeout
- Add proper dnd-shadow-placeholder div instead of filtering SHADOW_PLACEHOLDER_ITEM_ID
- Remove project dot from TaskItem (redundant visual indicator)
- Reduce content-wrapper padding (1rem → 0.5rem mobile, 1.5rem → 1rem desktop)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:37:42 +02:00
Till JS
79c6ab10ea fix(citycorners): move @const outside HTML element to satisfy Svelte 5 rules
{@const} must be immediate child of {#each}/{#if}/etc, not nested
inside HTML elements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 19:35:33 +02:00
Till JS
961cdfbcd2 fix(promtail): add default tier label to prevent empty label stream errors
Containers that don't match any tier regex had no labels, causing Loki to
reject the stream with "at least one label pair is required".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 19:35:28 +02:00
Till JS
222094d13f fix(monitoring): promtail depends_on service_started instead of healthy
Loki healthcheck interval is 5min — using service_healthy blocks Promtail
from starting for up to 5 minutes. service_started is sufficient since
Loki reports /ready immediately after startup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 19:33:48 +02:00
Till JS
0968c84eb4 feat(ci): GitHub→Forgejo mirror + Forgejo CD pulls from forgejo remote
- .github/workflows/mirror-to-forgejo.yml: on push to main, runner on Mac Mini
  pushes to Forgejo via local SSH (localhost:2222). Keeps Forgejo in sync.
- .forgejo/workflows/cd-macmini.yml: deploy step now pulls from forgejo remote
  (ssh://localhost:2222) instead of GitHub origin.

Flow: local → git push origin main → GitHub → mirror-to-forgejo runs on Mac Mini
      → pushes to Forgejo → Forgejo CD pipeline → deploys containers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 19:32:16 +02:00
Till JS
abb7712749 fix(forgejo): fix SSH port mapping + add Forgejo CD pipeline
- docker-compose: fix port mapping 2222:2222 → 2222:22 (sshd listens on 22)
- .forgejo/workflows/cd-macmini.yml: new CD pipeline for Forgejo Actions
  (mirrors .github/workflows/cd-macmini.yml, run_url points to git.mana.how)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 19:31:18 +02:00
Till JS
b46cbe403b fix(startup): remove colima delete --force to prevent image loss on reboot
colima delete wipes the entire VM disk on every power cycle, forcing
full image rebuilds. colima stop --force is sufficient to clear stale
process state after a hard shutdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 19:12:51 +02:00
Till JS
dee44807d1 fix(docker): add shared-links package to sveltekit-base image
todo-web, calendar-web, contacts-web, mana-web all depend on
@manacore/shared-links but it was missing from the base image COPY list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 18:51:15 +02:00
Till JS
c866c42a39 fix(startup): add /Users/mana mount to colima start (root cause fix)
The startup script runs `colima delete` on hard shutdown recovery,
wiping the colima.yaml mount config. Then `colima start` only added
/Volumes/ManaData but forgot /Users/mana — causing all file bind-mounts
to appear as empty directories (VirtioFS can't see host files).

This was the root cause of Synapse/SearXNG/Alertmanager/Loki crashing
after the power outage. Now both mounts are always passed explicitly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 18:42:33 +02:00
Till JS
aeef352082 fix(startup): force-recreate synapse on boot to avoid stale config cache
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 18:37:00 +02:00
Till JS
667d8cf96d fix(infra): simplify alertmanager config mount (direct file mount)
Now that VirtioFS is fixed (colima /Users/mana mount restored),
file bind-mounts work correctly. Replace the cp-in-entrypoint workaround
with a direct file mount to /etc/alertmanager/alertmanager.yml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 18:36:10 +02:00
Till JS
e21e09be1e fix(docker): fix vmalert rules scope + disable synapse OIDC
vmalert: was copying prometheus.yml into /etc/alerts/ causing parse
failure. Now only copies alerts.yml (the actual rules file).

synapse: mana-auth (Better Auth) has no OIDC discovery endpoint,
so disable OIDC and enable password auth until OIDC is implemented.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 18:33:56 +02:00
Till JS
d0c2302d39 fix(docker): fix multiline entrypoint YAML bug + searxng entrypoint path
YAML '>' block scalar preserves newlines for over-indented lines,
causing 'exec binary' to run without its arguments. Fix: use JSON
array format for all entrypoints to avoid YAML folding entirely.

Also fixes SearXNG entrypoint path: image updated from
dockerfiles/docker-entrypoint.sh to entrypoint.sh.

Affected: victoriametrics, loki, vmalert, alertmanager, searxng, synapse

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 18:29:44 +02:00
Till JS
ff19c7f062 feat(times): add NL time entry parser with multi-entry and quick-input
Create entry-parser.ts with duration extraction (2h, 30min, 1h30m),
time range parsing (9-12, 14:00-16:30), project (@), tags (#), billable
($), and date recognition. Multi-entry splitting via semicolons with
context inheritance. Integrate quick-input bar into EntryForm — type
"Meeting 2h @Client $; Review 1h" and press Enter to create multiple
entries at once.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:48:17 +02:00
Till JS
c33339b0cf rename(taktik): rebrand to Times
Rename taktik → times across the entire app: package names (@taktik →
@times), appId, localStorage keys, export filenames, type names
(TaktikSettings → TimesSettings), monorepo scripts, shared-branding,
mana-auth trustedOrigins, docker-compose, and documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:44:18 +02:00
Till JS
1eb370eaaa feat(manacore): tiling layout — resizable, splittable dashboard panels
Replace the fixed CSS Grid widget layout with a recursive tiling system
using a binary tree data model. Each node is either a leaf (widget) or
a split (horizontal/vertical) with a draggable resize handle.

New components:
- TilingLayout: Recursive renderer (leaf→TilePanel, split→flex+handle)
- TilePanel: Widget wrapper with edit controls (split H/V, change, close)
- TileResizeHandle: Draggable divider, H+V, keyboard accessible, 10-90%

Architecture:
- Binary tree model (TileNode = TileLeaf | TileSplit)
- Immutable tree operations in tiling-tree.ts (splitLeaf, removeLeaf, etc.)
- Tiling store with debounced IndexedDB persistence
- Widget registry extracted from WidgetContainer for shared use
- Mobile fallback: flattened vertical stack under 768px
- Default: Clock | Tasks | Calendar (3 panels)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:43:19 +02:00
Till JS
5f9c2a600d docs(contacts): document NL quick-input and duplicate detection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:15:33 +02:00
Till JS
451ab0338f feat(contacts): add NL quick-input and live duplicate detection
Add quick-input bar to NewContactModal that parses natural language
contact info (name, company, email, phone, tags) and pre-fills form
fields on Enter. Add live duplicate detection that checks name/email
against IndexedDB while typing, showing warnings for fuzzy name matches
(Levenshtein) and exact email matches. Both features run offline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:15:11 +02:00
Till JS
ad82a83f20 feat(manavoxel): add merchant trading UI and NPC loot drops
- Trade UI: merchant NPCs show 5 items (sword, wand, shard, herb, hammer)
  with stats preview, buy button adds item to inventory
- Loot system: defeated hostile/guard NPCs roll loot table drops
  (bone club, poison fang, dark crystal, iron shield, guard sword)
- Ground items: loot appears at NPC death position, pickup button
  when player is nearby
- Placeholder sprite generator for trade/loot items

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:06:51 +02:00
Till JS
45a17188e1 feat(manavoxel): complete game engine with behavior system, NPCs, lighting, and dialog
Major systems added to ManaVoxel:
- Behavior runtime: EventBus + 10 triggers + 11 action executors
- Item persistence: save/load items, inventory, area pixels to IndexedDB
- NPC system: 4 types (hostile/passive/merchant/guard), patrol/chase/attack AI
- Lighting: darkness overlay with emissive material light sources
- Day/night cycle: time-based ambient lighting on streets
- Sound system: 8 synthesized Web Audio API presets
- Sprite animation: multi-frame support in editor with play/stop
- Dialog system: NPC interaction with text bubbles and options
- Item properties: range, speed, durability, element all functional
- Health endpoint for Docker, durability bar in inventory UI

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