Commit Graph
100 Commits
Author SHA1 Message Date
openhands 1673da5afe trigger pipeline
CI / runtime-diagnostics (push) Skipped
CI / check (push) Failing after 0s
CI / deploy (push) Skipped
CI / release (push) Skipped
2026-09-03 16:10:29 +02:00
openhands 5e598a08b4 fix: remove ssr:false from dynamic imports in server components
CI / runtime-diagnostics (push) Skipped
CI / check (push) Failing after 0s
CI / deploy (push) Skipped
CI / release (push) Skipped
Turbopack rejects ssr:false in Server Components.
Removed from 4 dynamic imports in:
- src/app/(site)/layout.tsx (RadioPlayerGate)
- src/app/admin/analytics/economy/page.tsx (RevenueChart)
- src/app/admin/analytics/page.tsx (DashboardChart, PeakHoursHeatmap)
- src/app/admin/media/page.tsx (AdminMediaGrid)
2026-09-03 16:04:48 +02:00
openhands 30c95b1a5c feat: comprehensive CMS improvements
CI / runtime-diagnostics (push) Skipped
CI / release (push) Skipped
CI / check (push) Failing after 0s
CI / deploy (push) Skipped
- Fix DOMPurify SSR crash (use isomorphic-dompurify)
- Fix SanitizedHtml to sanitize by default
- Add auth guards to studio/catalog maintenance pages
- Add update/edit to vouchers CRUD
- Add update/edit to rare-values CRUD
- Add approve workflow to applications page
- Add edit form to guilds detail page
- Add SEO metadata to all public pages (21 pages)
- Fix mobile nav accessibility (focus trap, aria attributes)
- Fix missing labels and table accessibility
- Add dynamic imports for heavy client components (6 components)
- Fix silent error swallowing (40+ locations)
- Add content scheduling for articles (publishAt, status)
- Wire up 12 missing webhook notification triggers
- Add global search to admin panel
- Add bulk actions to admin users table
- Fix JSON formatting and a11y issues
2026-09-03 16:00:32 +02:00
openhands b810b16672 fix: show/hide arrow always visible and null-safe
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m2s
- Show arrow (›) appears when toolbar is hidden, regardless of pos state
- Null-safe pos top/left (?. ?? 8) to prevent TS errors
- Arrow positioned fixed top-right instead of depending on balk-positie
2026-09-02 22:02:31 +02:00
openhands a30e4af32e feat: polish toolbar, live online count via SSE + emulator 3-state
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 30s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m5s
- Add emulator status 3-state (unknown/green/red) with tooltip
- Extract shared primary button style/constants for DRY toolbar code
- Add emulatorUnknown translations to all 25 locales
- Bump Next.js to 16.3.4
- Fix RCON delivery timeout caching (15s TTL / shared across clients)
- Who's-online tooltip throttled to max 1 request per 30s
2026-09-02 21:34:30 +02:00
openhands 67b67798b9 feat(client): polished toolbar, live online count via SSE
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m27s
- Redesign in-game client toolbar with refined glass styling and buttons
- Live online count + emulator status streamed over SSE multicast
- Who's-online tooltip throttled to reduce repeated requests
- Fix show button so it always returns the hidden toolbar
- Use theme CSS variables instead of hardcoded colors
- Add toolbar translations across all 25 locales
2026-09-02 21:14:42 +02:00
openhands e1ecb190bc docs(docker): clarify how to update (nightly cron + manual run) in README
CI / check (push) Successful in 34s
CI / runtime-diagnostics (push) Skipped
CI / deploy (push) Successful in 1m5s
CI / release (push) Skipped
2026-09-02 12:58:39 +02:00
openhands fb978612d7 docs(docker): also relax permissions on write volumes for imported asset dirs
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 57s
2026-09-02 12:53:10 +02:00
openhands c1cc1fdc1c fix(home): counter counts exactly once, no restart on value refresh
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 38s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m40s
AnimatedCounter restarted from 0 on every online-count cache refresh (~10s)
because the effect depended on value. Rewrote it as a single requestAnimationFrame
animation with ease-out; changes to value after the animation only update the
display statically.
2026-09-02 12:47:58 +02:00
openhands 037b295b93 feat(ci): automated docker update script + nightly cron
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m3s
- scripts/docker-update.sh: git pull --ff-only, host db:migrate, docker compose
  build + up -d, health-check wait, keeps host-side PM2 'next' stopped.
  Fails safe on dirty working tree (exit 1) and on health failure (exit 3).
- cron entry: daily 03:30 -> logs/docker-update.cron.log
- README: Automatic Updates section + docker commands row
2026-09-02 12:25:42 +02:00
openhands cb927db78d Docker: full Dockerized deployment (volumes, host networking, multi-package-manager build)
- docker-compose.yml: network_mode host so 127.0.0.1 refs (.env) keep working;
  mounts /var/www/Gamedata + write volumes; /api/health healthcheck; mem_limit
- Dockerfile: package-manager detection (pnpm/yarn/npm) + PACKAGE_MANAGER arg;
  runs as www-data (UID/GID 33) so gamedata is writable; .env loaded only for
  the build (no secrets baked in); build runs on the host network
- .dockerignore: .env stays in the build context (needed for NEXT_PUBLIC_*)
- README: Docker deployment section (paths, volumes, chown, migrations on host)
2026-09-02 12:25:42 +02:00
openhands 58c35a2920 feat: enforce no hardcoded colors across entire CMS
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 32s
CI / release (push) Skipped
CI / deploy (push) Successful in 58s
Added scripts/check-admin-colors.mjs — scans all src/ files for:
- text-white, text-black (use theme text vars)
- bg-white, bg-black (use theme background/overlay vars)
- bg/text/border/ring with gray/slate/zinc/stone palette
- bg/text/border/ring with red/green/blue/etc palette

Fixed 21 violations across 11 files:
- Overlays: bg-black/* → bg-foreground/*
- Text: text-white → text-primary-foreground
- Backgrounds: bg-white/10 → bg-background/10
- Green accents: bg-green-* → bg-primary
- Red accents: bg-red-* → bg-destructive

Integrated into:
- lint-staged: runs on every *.ts/*.tsx commit
- vitest: src/lib/no-hardcoded-colors.test.ts replaces old audit test
- Allowlist: shadcn/ui primitives (button, badge, dialog) + 4 graphical files
2026-09-01 19:33:50 +02:00
openhands 0fa832d577 fix: replace hardcoded text-white with theme-destructive-foreground
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 38s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m9s
2026-09-01 19:18:00 +02:00
openhands 844add04ef fix: confirm dialog is now a compact popup, not full-screen overlay
- Removed full-screen overlay backdrop (bg-black/95 + backdrop-blur)
- Dialog is centered via fixed left-1/2 top-1/2 -translate
- Compact design: max-w-sm, smaller text, smaller buttons
- Uses admin theme vars (admin-surface, admin-border, admin-text)
- Smooth scale+fade animation without overlay
2026-09-01 19:13:15 +02:00
openhands 93601e58e0 feat: Studio bulk ops, perf fixes, bug fixes, confirm dialog visibility
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m3s
Confirm Dialog:
- Overlay opacity 80% -> 95% (solid black)
- Card uses bg-surface with glow shadow ring-primary/40
- Added AlertTriangle icon for danger variant
- Removed backdrop-blur for maximum opacity

Studio features:
- Bulk delete: select imported items and delete in batch
- Bulk nitro regen: select items missing .nitro and regenerate all
- Added Trash2 and RefreshCw toolbar buttons for bulk actions

Performance:
- BatchProgress: React.memo + useMemo for entries/total/completed/percent
- BatchProgress: ETA interval uses useRef to avoid re-creation per completed
- CatalogRail: React.memo + useCallback for toggle
- Removed redundant double setBatchProgress calls
- Removed redundant new Map(initial) wrapping

Bug fixes:
- importBatch: stale batchDone closure always cleared progress panel (use ref)
- importBatch: added missing toast.error on HTTP failure
- bulkRegenNitro: now checks per-item results instead of marking all as succeeded
- single deleteItem: now removes classname from selected set
- retryFailed: clears progress panel on HTTP error and stream error
- Removed unused 'done' variable (2x) from cloneAllMissing/retryFailed

Lint:
- biome format fixes for selectedMissingNitro and setItems
2026-09-01 19:07:20 +02:00
openhands 4863f78795 fix: make confirm dialog fully opaque with solid background
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 50s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m6s
Replace bg-card with bg-background/100, upgrade shadow to 2xl, and
remove backdrop-blur on the dialog content to ensure maximum visibility.
2026-09-01 18:34:10 +02:00
openhands 52516a368d fix: skip heavy post-import consolidation on non-final clone chunks
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 38s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m2s
The flush after every 400-item chunk was running expensive operations
(reconcileOfferIds, rebuildCatalog, verifySpriteIds, rcon updates) which
caused the import to hang after ~800 items. Now only the final chunk
triggers the full consolidation. Also raised the per-request limit from
500 to 5000 items.
2026-09-01 18:29:06 +02:00
openhands d4fbbfa243 fix: make confirm dialog more visible with darker overlay and sharper shadow
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m18s
2026-09-01 18:24:00 +02:00
openhands c023436413 fix: align pnpm-workspace.yaml overrides with package.json specifiers
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m2s
The CI frozen-lockfile check was failing because pnpm-workspace.yaml
overrides had older version specifiers than package.json. Update overrides
for sharp, postcss, and @types/react-dom to match, and regenerate lockfile.
2026-09-01 17:52:35 +02:00
openhands d602ee59c7 chore: update all dependencies to latest versions
CI / runtime-diagnostics (push) Skipped
CI / check (push) Failing after 11s
CI / release (push) Skipped
CI / deploy (push) Skipped
- lucide-react 1.33.0 → 1.38.0
- mysql2 3.23.4 → 3.24.2
- next-intl 4.13.7 → 4.14.1
- otplib 13.4.1 → 13.5.0
- react-hook-form 7.85.0 → 7.87.0
- resend 6.21.0 → 6.25.0
- zod 4.4.3 → 4.5.4
- sharp 0.35.3 → 0.35.4
- @biomejs/biome 2.5.9 → 2.5.11
- @types/node 26.2.0 → 26.4.0
- @types/react-dom 19.2.4 → 19.2.5
- knip 6.32.2 → 6.33.0
- lint-staged 17.3.0 → 17.4.1
- tsx 4.23.12 → 4.23.13
- pnpm 11.24.0 → 11.25.0
2026-09-01 17:38:25 +02:00
openhands 1374bd332f Studio: add clone-all-per-hotel, per-item status detail, retry, ETA, and auto-translate
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 36s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m14s
- Add 'Clone all missing' button for clone sources with confirmation dialog
- Show per-item status badges: nitro, furnidata, catalog entry
- Add status filters: missing furnidata, missing catalog entry
- Add ETA and percentage to batch progress bar
- Add retry button for failed items after batch import
- Auto-translate all languages after clone-all completes
- Fix statusFilter 'all' bug that incorrectly filtered imported items
- Bulk-load FurnitureData + catalog references for O(1) per-item checks
2026-09-01 17:29:12 +02:00
openhands 1dc8d1d46f feat: add official furnidata sync button for importing all missing items
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 55s
- API endpoint: /api/admin/import/official/sync-all
  - Fetches all official Habbo furnidata
  - Compares with database to find missing items
  - Imports missing items via SSE batch with progress reporting
  - 500 item limit for safety
  - Proper abort signal support
- Client component: OfficialSyncClient with progress UI
- Updated StudioSyncPage to include Official Furnidata sync option
- Uses existing importSingleFurni infrastructure
2026-08-31 20:24:46 +02:00
openhands 2920a6521b feat: update StudioSyncPage with clone sync client
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 56s
- StudioSyncPage toont nu Clone Sources en Official Furnidata opties
- Clone sync gebruikt bestaande SSE infrastructuur met 60s idle timeout
- DeOfficial Furnidata sectie is uitgeschreven voor toekomstige uitbreiding
2026-08-31 19:27:37 +02:00
openhands 7556b1f3fa perf: prevent import hanging with timeouts and batching
CI / check (push) Successful in 31s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m1s
- verifyAndFixInteractionModesCount: paginated DB queries (500/batch)
  instead of loading all items into memory at once
- withFurniDataLock: add 60s chain timeout to prevent deadlocks
  when a lock holder stalls or crashes
- withGamedataLock: same timeout protection for gamedata locks
- conversion-pool: add 60s per-job timeout, fall back to main thread
- furni/batch: abort signal + post_import progress events + skip
  post-import steps when client disconnects
- furni/batch-regen: abort signal + early exit when disconnected
- clone/sync-all: pre-fetch furnidata once per source instead of
  per item (eliminates 2000+ redundant fetches)
- sse-client: add 60s idle timeout to prevent infinite hangs
2026-08-31 18:25:32 +02:00
openhands f70d96b81c fix: prevent import hanging by adding abort signals and idle timeouts
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
- Furni batch: wire request.signal to abort controller, send post_import
  progress events, skip post-import steps when aborted
- Clone sync-all: pre-fetch furnidata once per source instead of per item
  (eliminates 2000+ redundant DB reads + HTTP requests)
- SSE client: add 60s idle timeout to prevent infinite hangs when server
  stops responding
2026-08-31 18:11:54 +02:00
openhands 96c33efced fix: remove unused site-resolver.ts
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
2026-08-31 17:50:12 +02:00
openhands a7ccc98f84 fix: resolve pre-existing lint warnings
CI / check (push) Failing after 28s
CI / release (push) Skipped
CI / deploy (push) Skipped
- Remove unused siteSettings import in auth-precheck.test.ts
- Replace non-null assertions with proper null checks in furni-data-i18n.ts
- Replace non-null assertions with proper null checks in conversion-pool.ts
2026-08-31 17:48:36 +02:00
openhands adf0658916 feat: extend theme builder with block visibility, layout, effects, media, and custom CSS tabs
CI / check (push) Failing after 29s
CI / release (push) Skipped
CI / deploy (push) Skipped
- Add theme-blocks.ts registry with 24 themeable blocks across 4 categories
- Extend resolver to resolve blocks, layout, effects, media, and custom CSS per scope
- Add data-theme-block attributes to all site layout blocks
- Extend ScopedThemeVars to generate CSS for block visibility, layout vars, effect vars, media vars, and custom CSS
- Rewrite admin UI with 6 tabs: Colors, Blocks, Layout, Effects, Media, Custom
- Extend server actions to save/load all new setting types
- No database migration needed - uses existing theme_scope_values table with prefixed keys
2026-08-31 17:44:29 +02:00
openhands 3efd6c90f0 fix: use valid AuditState values for theme-builder migration entry
CI / check (push) Failing after 30s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-31 17:22:19 +02:00
openhands 4c8225720a fix: resolve test failures for theme builder integration
- Replace hardcoded text-white and text-red-* with CSS variables in theme-editor
- Add theme-builder migration entry to housekeeping matrix
- Update legacy page counts from 137 to 138 in housekeeping tests
- Add /admin/theme-builder to content test prefixes
2026-08-31 17:21:37 +02:00
openhands a98b194386 feat: add scoped theme builder system with per-route, per-module, and multi-site support
- Add theme_scopes and theme_scope_values database tables for scoped themes
- Implement theme resolver engine with inheritance: global > site > module > route
- Add module detection for 20+ routes (shop, guilds, radio, news, etc.)
- Create admin UI at /admin/theme-builder with scope tree and color editor
- Add ScopedThemeVars component for injecting scoped CSS via data-attributes
- Add ThemeScopeDetector client component for runtime module/route detection
- Add site-resolver for multi-site domain detection
- Add /api/themes/export endpoint (JSON, CSS, variables formats)
- Add /api/themes/export/embed.js for external integration widget
- Add server actions for full CRUD on scopes and theme values
- Add admin nav link and EN/NL translations
2026-08-31 17:15:42 +02:00
openhands b57697b2e0 Polish content pages: share AuthTopBar, page-grid helper and responsive tables
CI / check (push) Successful in 37s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
- Extract shared AuthTopBar frosted top bar; reuse in login & register
- Add .page-grid class replacing 48 inline grid styles
- Add .table-scroll + .table-cell-truncate helpers; wrap leaderboard/staff tables
- Constrain settings page width (max-w-5xl) and stack profile card on mobile
- Use theme background var for shop category icon (dark-mode safe)
2026-08-31 12:23:06 +02:00
openhands d4677972cd Refine dashboard hero, mobile nav, animations and touch polish
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 56s
- Stack the /me dashboard hero (avatar + info) on small screens instead of
  crowding them side by side; center the avatar and info on mobile
- Respect prefers-reduced-motion in the Reveal scroll animation
- Make the desktop pitch-in (NavDropdown) and mobile menu more consistent;
  give the mobile menu a max-height with overscroll containment so long
  navs scroll instead of overflowing on small phones
- Add safe-area insets for notched devices on header, nav and footer
- Polish whole-link content-cards (community tiles) with hover lift and a
  visible focus ring
- Enforce a comfortable min touch height on all .btn buttons
2026-08-31 12:11:04 +02:00
openhands c17ef0e7ab Fix flaky TTL cache test timing
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 55s
Use a 20ms TTL with a 40ms wait so the expiry window is long enough
for the immediate second read to hit the in-memory cache reliably.
2026-08-31 11:47:43 +02:00
openhands 903d175f2d Polish responsive design across all screen sizes and refine card blocks
CI / check (push) Failing after 26s
CI / release (push) Skipped
CI / deploy (push) Skipped
- Enhance SurfaceCard with refined borders, layered shadows, and polished
  primary-tinted header with an icon container
- Update homepage blocks (hero, features, stats, login, news, photos) for
  proper mobile/tablet/desktop responsiveness and tighter mobile spacing
- Improve content-card, stat-block, card-grid and card styling with subtle
  depth (layered shadow + inner hairline) and smoother hover states
- Refine site header, footer, top header and site layout spacing for small
  screens while keeping a consistent professional look on large screens
- Add min-tap-height targets and responsive typography on mobile
2026-08-31 11:45:02 +02:00
openhands b506b4499a fix: resilient DB backups and Dragonfly detection in health/status
CI / check (push) Successful in 41s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m49s
2026-08-30 19:17:50 +02:00
openhands 24d6cf7047 perf: precompress heavy assets and self-heal missing gamedata originals (gzip_static)
CI / check (push) Failing after 27s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-30 18:46:25 +02:00
openhands d57424a9ee style: fix biome formatting in sync-nitro-urls
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m3s
2026-08-30 18:24:07 +02:00
openhands 678d22ceab feat: bulletproof updater + fixes for client links (icons/furniture/gamedata)
CI / check (push) Failing after 8s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-30 18:19:46 +02:00
openhands f2ac4745d4 feat: redesign home and register pages for cleaner overview
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
Rebuild the home landing layout into a streamlined, more scannable
design: a centered focused hero, feature cards, a compact stats row,
and clearer news/users sections. Rework the register page into a
balanced two-column layout with a tidier intro panel and sticky form.
Add statsArticles translation key across locale files; verified with
tsc and biome.
2026-08-29 21:56:52 +02:00
openhands 3baac5e885 chore: update nextjs and react to latest versionb to fix cve eploits
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 43s
2026-08-29 21:30:44 +02:00
openhands a6e69fe00e perf: declutter home page by removing duplicated sections and queries
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 55s
The landing page showed the same information more than once. Drop the second
avatar grid (latest users) and its DB query, move the online users grid into
the left column, remove the register banner card and the bottom join CTA so
registration is only offered once in the hero, and show the online count a
single time in the hero badge instead of also in the stats row. The online
users query now fetches 12 rows instead of 30, saving bandwidth on every
uncached render. The avatar presentation contract test now expects one
thumbnail call site on the home page.
2026-08-29 21:26:30 +02:00
openhands b59d6c21af feat: prioritize game iframe, gated register terms and polished register page
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 55s
Fetch the Nitro client iframe with high priority so the browser starts the
game document before competing resources, and replace the bare /client
spinner with a branded boot screen. Preconnect and eager loading were already
in place; typing support for the iframe fetchPriority prop is added in a
React type augmentation.

Rework the register terms block into a single clickable accept control with
a custom check state, error shake and inline hint, and dim the submit button
until the terms are accepted. The register page gets labeled sections
(account details / credentials), a corrected banner overlay, translated
show/hide toggles and a captcha slot that reserves height to avoid layout
shifts. English is the source of truth; other locales fall back to it.
2026-08-29 21:14:02 +02:00
openhands 7f39ba4257 fix: harden SSO ticket flow and revoke tickets on logout
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
Reuse the outstanding auth_ticket instead of minting a fresh one on every
/client load, so reloading the page or opening a second tab no longer
invalidates a game session that is still connecting. New tickets are minted
with a guard against the previously-read value so concurrent launches
converge on the same ticket.

Revoke the auth_ticket when signing out (toolbar, header and sign-out
everywhere) so a leaked ticket can no longer be replayed against the
emulator, and prevent SSO leakage via referral by setting no-referrer on the
client iframe. Strip all whitespace from the ticket prefix and build the
launch URL through a tested helper that handles query strings, existing sso
params and URL fragments correctly.
2026-08-29 20:54:06 +02:00
openhands ca59a1065f perf: use lzma-wasm for SWF decompression and drop vite
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
Replace the pure-JS lzma decoder with lzma-wasm (Rust/WASM, base64-inlined,
zero-alloc decompress), giving an order-of-magnitude speedup on furni
imports. Remove the obsolete lzma type shim and the redundant top-level
vite dev dependency, which nothing imports directly.
2026-08-29 19:27:27 +02:00
openhands 7a41775c7e fix: disable route prefetching app-wide to avoid spurious requests
Wrap next/link in a shared Link component that ships prefetch=false by
default, so no route is ever prefetched (viewport or hover) anymore, and
drop the DNS prefetch hint. Removes hidden background requests that were
the source of intermittent issues.
2026-08-29 19:27:13 +02:00
openhands 944e8ff1d8 fix: harden update pipeline and restore a clean production build
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
- update-Nitrov3.sh: build CMS into .next-staging and swap atomically so a
  failed build never takes the live site down; auto-merge new variables
  from .env.example; validate env for duplicates/broken lines; restart the
  emulator/CMS only when rebuilt or unhealthy; fix step renumbering
- next.config.ts: support NEXT_DIST_DIR for staged production builds
- fix all TS errors (unused imports, missing tryDownloadCandidates helper)
  so tsc and the production build pass clean
- add Dockerfile/.dockerignore and switch docker-compose to a CMS container
- include prevailing UI/refactor changes (SurfaceCard, ticketing, tsconfig)
2026-08-28 12:48:04 +02:00
openhands 750fcb2e5c refactor: resolve hotel name directly from HOTEL_NAME env
CI / check (push) Successful in 41s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m1s
resolveHotelName() now returns env.HOTEL_NAME directly — the single source
of truth. The CMS hotel_name site setting and its DEFAULTS entry are removed
as dead code since they no longer influence the displayed name.

Call sites are unchanged (still await resolveHotelName()); only the lookup
behind it is gone, so the public site always shows the configured env name
with no DB round-trip and no preset.
2026-08-27 16:42:12 +02:00
openhands 164a4f4ef6 refactor: remove hotel-name fallback, fail fast when unconfigured
CI / check (push) Failing after 39s
CI / release (push) Skipped
CI / deploy (push) Skipped
Drop the hardcoded FALLBACK_HOTEL_NAME ("Atom") preset and the brand.ts
module. HOTEL_NAME is now a required env var: if it (and the CMS hotel_name
setting) is missing the site fails validation at startup/build with a clear
message instead of silently rendering a placeholder hotel name.

resolveHotelName() resolves CMS hotel_name -> required HOTEL_NAME only.
Callers that used the preset (api/home route catch branch, CMS settings form
default, mobile-nav/logo-generator prop defaults) now use the configured name
or an empty default; the real name is already passed in by server parents.
2026-08-27 16:35:00 +02:00
openhands 555c783d55 refactor: consolidate card components into a single SurfaceCard
CI / check (push) Successful in 41s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m22s
Replace the three near-identical public card primitives (ContentCard for
content pages, SectionCard for auth/account, and the new SurfaceCard) by
merging SectionCard into SurfaceCard, which now supports an optional header
(title/icon/action). Every remaining ad-hoc inline `rounded-2xl border`
card across (site) is converted to SurfaceCard, preserving each card's unique
visuals (background images, blur, gradients) via the style passthrough.

Net result: the public site uses exactly two card components — ContentCard
(CMS/content pages) and SurfaceCard (everything else) — and the shadcn Card
in components/ui/card.tsx is left untouched for admin.

Also deletes the now-unused components/home-section.tsx.
2026-08-27 16:17:09 +02:00
openhands ed6eaf33a0 style: convert remaining ad-hoc inline cards to shared SurfaceCard
CI / check (push) Successful in 40s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m11s
Introduce components/surface-card.tsx (Card + CardBody) mirroring the
.content-card / SectionCard token set, and use it on the (site) pages that
still hand-rolled card markup: me, search, and verify. This puts every
public page on one of the shared card components (ContentCard, SectionCard,
or SurfaceCard) for consistent radius/shadow/border.
2026-08-27 15:59:15 +02:00
openhands a3e3356ea7 style: align both card systems to shared design tokens
CI / check (push) Successful in 37s
CI / release (push) Skipped
CI / deploy (push) Successful in 58s
Unify the public site by making SectionCard and the verify status card use
the same --radius-lg / --shadow-card tokens and primary-tint header as the
existing CSS .content-card used by all content pages. This makes the entire
(site) group visually consistent without rewriting every page, and keeps the
shadcn Card in components/ui/card.tsx (used by admin) intact.
2026-08-27 15:51:32 +02:00
openhands b3340dbfdf style: unify remaining site card headers with SectionCard
CI / check (push) Successful in 35s
CI / release (push) Skipped
CI / deploy (push) Successful in 57s
Convert the settings page neon gradient section headers (blue/purple/green)
to the shared SectionCard, and replace the verify page's harsh multi-stop
status gradients with subtle status-tinted headers while keeping the
green/amber/red/blue semantics. The me page already used a consistent
rounded-2xl card style, so it needed no change.
2026-08-27 15:42:30 +02:00
openhands 087dd7d873 style: apply consistent professional layout to login page
CI / check (push) Successful in 35s
CI / release (push) Skipped
CI / deploy (push) Successful in 52s
Reuse the SectionCard component to unify the neon section headers, center
the page in a max-w-6xl container, and give the welcome panel and login
card consistent rounded corners and subtle shadows, matching the home
and register pages.
2026-08-27 15:32:32 +02:00
openhands 9f0ee74ce8 style: apply consistent professional layout to register page
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m4s
Reuse the SectionCard component to unify the green/purple/blue neon
section headers, center the page in a max-w-6xl container, and give the
welcome panel and form card consistent rounded corners and subtle
shadows, matching the home page.
2026-08-27 15:24:59 +02:00
openhands 005af25773 style: make home page layout more professional
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m1s
Unify the per-section neon gradient headers (blue/green/purple) into a
single consistent SectionCard component with a calm surface header and
hairline divider, constrain the page to a centered max-w-6xl container,
and soften the hero/cards with rounded-3xl corners and subtle shadows.
2026-08-27 15:21:25 +02:00
openhands 89c1751e79 refactor: extract shared login credential verification into auth/login-core
CI / check (push) Successful in 35s
CI / release (push) Skipped
CI / deploy (push) Successful in 58s
The username normalization, dummy-hash constant, password check and
email-verification gate were duplicated between precheckLogin and the
NextAuth credentials authorize handler. Move them into a single
login-core module so both paths share one source of truth and stay
consistent.
2026-08-27 15:17:54 +02:00
openhands e3ed37d170 build: align pinned Node.js version with CI runtime (26.8.1)
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m1s
.nvmrc and package.json engines.node must match the exact version the
CI environment runs, otherwise scripts/check-node-toolchain.mjs fails
the strict equality assertion.
2026-08-27 15:12:03 +02:00
openhands ac5cd6bc3f fix: normalize username and password with NFC in login flow
CI / check (push) Failing after 5s
CI / release (push) Skipped
CI / deploy (push) Skipped
precheckLogin already normalized the username with NFC, but the
NextAuth credentials authorize handler only trimmed it. This caused a
mismatch for accounts with accented/non-ASCII usernames: the precheck
passed while the actual sign-in lookup found no user and returned
'invalid username or password'.

Also normalize the password to NFC in both the precheck and the
authorize handler to match how register.ts hashes it.
2026-08-27 15:09:43 +02:00
openhands 9d0da5d65a Perf: cache Nitro client assets and parallelize client page
CI / check (push) Successful in 31s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
- Serve /swf and /nitro-assets (~2.8GB) with 7-day Cache-Control plus
  stale-while-revalidate so client opens stop re-fetching hundreds of
  files while asset updates still propagate in the background
- Issue the SSO ticket and the online count query in parallel on the
  client page to shave a round-trip off the critical render path
2026-08-26 15:06:16 +02:00
openhands e7f70bb429 Chore: remove unused e2e register debug script
Flagged by knip as unused. It was a one-off DB smoke test with a
hardcoded database password that should never have been committed.
2026-08-26 15:06:14 +02:00
openhands f25a26a93e Register: auto sign-in to /me and speed/cleanup improvements
CI / check (push) Failing after 30s
CI / release (push) Skipped
CI / deploy (push) Skipped
- Send the verification email after the response via after() so it
  never blocks sign-up
- Invalidate the cached login lookup right after account creation so
  the automatic sign-in always finds the fresh row
- Auto sign in with the submitted credentials and go straight to /me,
  with a fallback to /login?registered=1 if sign-in is refused (e.g.
  email verification required)
- Cache the register page's online/latest user queries to cut DB load
  under traffic
- Fix terms checkbox label double-toggle cancelling the selection
- Add pages.register.redirecting translation to all locales
2026-08-26 14:57:51 +02:00
openhands 2d09a4a92c Add missing migrations
CI / check (push) Failing after 26s
CI / deploy (push) Skipped
CI / release (push) Skipped
2026-08-26 14:28:28 +02:00
openhands 0201d21c38 Fix site crash by restoring next-intl plugin and lost next.config.ts options
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
Recent optimization commits accidentally gutted next.config.ts, removing
the createNextIntlPlugin wrapper. This caused every page to crash at
runtime with 'Couldn't find next-intl config file', showing the error
page after a successful build.

Restores:
- next-intl plugin (./src/i18n/request.ts)
- Security headers (HSTS, X-Frame-Options, nosniff, etc.)
- Redirects from /admin/import/* to /admin/studio/*
- Cache headers for /assets and /images, AVIF/WebP image formats
- compress and productionBrowserSourceMaps

Keeps recent improvements: reactStrictMode and optimizePackageImports.
2026-08-25 23:01:54 +02:00
openhands 3070d85423 Perf: Optimize next.config.ts for Next.js 16
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 38s
2026-08-25 22:35:46 +02:00
openhands f31530b3d7 Optimize next.config.ts with package import optimizations
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 47s
2026-08-25 22:31:05 +02:00
openhands 3cc201a0ce Optimize next.config.ts with SWC minification and React strict mode 2026-08-25 22:30:35 +02:00
openhands 94b0b65ca0 Remove unused dependencies flagged by Knip
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 38s
2026-08-25 22:28:02 +02:00
openhands 4eded4ec61 Apply Biome lint fixes
CI / check (push) Failing after 26s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-25 22:26:05 +02:00
openhands f63ca708fe Fix deploymentId in next.config.ts
CI / check (push) Failing after 26s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-25 22:20:41 +02:00
openhands e06596391e Fix Turbopack module resolution for lzma and restore path imports 2026-08-25 22:19:59 +02:00
openhands a5044c80d7 fix: resolve biome linter warnings and code formatting
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 46s
2026-08-25 21:54:02 +02:00
openhands 416c31643b perf: optimize dashboard database queries and remove unused imports
CI / check (push) Failing after 10s
CI / deploy (push) Skipped
CI / release (push) Skipped
2026-08-25 21:52:18 +02:00
openhands 3a76dbdb97 feat: rename Nitro-V3 to Octane, add auto-setup and old Nitro cleanup
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 52s
- Rename all references from Nitro-V3/Nitro_Render_V3 to Octane/Octane-Renderer
- Update default paths to /var/www/Octane and /var/www/Octane-Renderer
- Update ASCII art banner from NITRO to OCTANE
- Add GIT_REPO_CLIENT and GIT_REPO_RENDERER constants (configurable via .env)
- Add auto_setup_missing_repos() - clones, installs deps, and builds frontend
- Add cmd_setup command (menu option 22 / CLI: setup/init)
- Preflight check now auto-clones missing repos instead of dying
- Add cmd_cleanup_old_nitro() - detects old Nitro dirs and safely removes them:
  Updates symlinks, nginx configs, and systemd services before deletion
- Add cmd_cleanup_old_nitro command (menu option 23 / CLI: cleanup-nitro)
- Add translations for NL, FR, ES, DE, IT
- Update notification text to [Octane Update]
2026-08-25 15:15:17 +02:00
openhands 1a0d20fae5 i18n: add pages.admin.studio namespace to all 22 locale files (EN placeholders + Dutch)
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 42s
2026-08-24 20:48:13 +02:00
openhands 6ae7c09682 perf: offload per-import localized patch to worker + cache FurnitureData parse
CI / check (push) Successful in 41s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
Per single furni import, patchLocalizedFurniDataEntries ran for every
language and did a full 100k-entry JSON.parse + scan + JSON.stringify on the
main thread. That CPU spike is now offloaded to the translation worker
(init/prepare/finalize reuses the same pure core helpers), so importing
never blocks the event loop. The main thread only does async file I/O and the
network LibreTranslate calls. Falls back to the same helpers on the main
thread if no worker is available.

Also cache readFurniData() by file mtime+size so the 100k-entry JSON is
parsed once per change instead of on every import/fix/reconcile read
(invalidated on write).
2026-08-24 19:29:21 +02:00
openhands f94246e067 perf: offload FurnitureData translation build to a worker thread
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
The translation build's CPU-heavy work (deep clone of the 100k+ entry
master, the two full scans and JSON.stringify per language) now runs in a
worker thread, so "Alles vertalen" no longer blocks the main event loop.
Network/DB parts (official Habbo fetch, LibreTranslate, file writes) stay
on the main thread. The pure helpers were extracted to furni-data-i18n-core
(no server-only deps) so the worker can import them. Falls back to the same
helpers on the main thread when no worker is available or in tests.
2026-08-24 19:10:33 +02:00
openhands 8d1b09f151 perf: offload SWF→Nitro conversion to a worker-thread pool
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
The synchronous convertSwfToNitro / extractIconFromSwf calls (pure CPU,
no DB/network) now run in a small worker pool so the main Node event
loop stays free during imports — the dominant import-time CPU spike is
moved off the request thread. The pool degrades gracefully to a
synchronous fallback if workers can't be created, and is skipped in the
test environment.
2026-08-24 19:02:19 +02:00
openhands 7116f49e2b perf: eliminate lag spikes and redundant work in furnidata i18n
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m1s
- patchLocalizedFurniDataEntries now only touches the wanted classnames
  instead of scanning the whole 100k file, reads the master once (was
  twice), and uses the batched translator instead of one HTTP call per
  text.
- Remove the now-unused serial translateWithLibre.
- buildLocalizedFurniDataFiles yields between the two section scans and
  before stringify so a single language no longer blocks the event loop
  for the whole pass at once.
2026-08-24 18:52:55 +02:00
openhands 5efd004533 perf: throttle localized furnidata build to avoid 100% CPU spikes
CI / check (push) Successful in 32s
CI / release (push) Skipped
CI / deploy (push) Successful in 56s
Lower LibreTranslate concurrency to 2 and yield the event loop between
languages so the 13x deep-clone + stringify loop no longer pins a core
continuously. The build is also already opt-in (off by default on import).
2026-08-24 18:43:07 +02:00
openhands 4a95b53b02 feat: add "Vertaal alles" button to translate the whole catalog on demand
CI / check (push) Successful in 32s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
Lets admins import fast with translation disabled, then build every
language for the full catalog later via the existing build-languages
action.
2026-08-24 18:39:21 +02:00
openhands 3a292a44f1 feat: make catalog-pages dedup a choosable step in Fix alles
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m3s
The maintenance "Fix alles" now has a checkbox to include or skip the
duplicate catalog_pages merge, so admins can choose whether to run it.
removeDuplicates takes an includePages flag and fixEverything threads it
through to the action.
2026-08-24 18:35:00 +02:00
openhands 6dced0fb54 feat: per-import translation toggle and language picker in studio
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 53s
Furni imports can now choose whether to translate (per import) and which
languages to build, instead of always rebuilding all 13 FurnitureData_<lang>
files. The studio header also has a global switch that persists the
furnidata_translate_enabled setting, seeding the per-import default.
2026-08-24 18:16:42 +02:00
openhands d6af754211 feat: dedupe duplicate catalog_pages to prevent double links
The maintenance "Fix alles" now collapses catalog_pages that share the same
caption_save + parent_id into a single survivor (moving catalog_items and
reparenting child pages before deleting duplicates), so the catalog tree
never renders double links. The duplicate-page count is also surfaced in the
health panel.
2026-08-24 18:16:28 +02:00
openhands 02f8ffc0bc chore: remove dead files flagged by knip
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Successful in 51s
Delete two unreachable files with no importers:
- src/components/ui/dropdown-menu.tsx
- src/lib/admin/verify-interactions.ts
2026-08-24 17:20:34 +02:00
openhands c7ba04bda1 feat: relocate import tools into studio and harden catalog/furnidata integrity
CI / check (push) Failing after 26s
CI / release (push) Skipped
CI / deploy (push) Skipped
- Move /admin/import/* tools under /admin/studio/* and add studio nav, layout and tabs
- Add shared catalog maintenance panel plus a /admin/studio/maintenance tab
- Make furnidata reconciliation overwrite conflicting entries with the
  DB-authoritative items_base classname/id (surfaced via fixedConflicts)
- Add furnidata_translate_enabled setting to skip the heavy localized
  furnidata build during import (manual build-languages still forces it)
- Update staff smoke contract test for the studio hub
2026-08-24 17:13:03 +02:00
openhands c2e61dc324 fix: reduce import concurrency to prevent 100% CPU during SWF→Nitro conversion
CI / check (push) Successful in 42s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m43s
- Default batch concurrency: 3→1 (max 5→3)
- Default batch-regen concurrency: 3→1 (max 5→3)
- Default IMPORT_BATCH_CONCURRENCY: 12→3
- Added setImmediate yields between items to prevent event loop blocking

Fixes gatje and other complex furniture imports consuming 100% CPU and stalling the catalog studio.
2026-08-23 19:51:04 +02:00
openhands c043af318b Collapse catalog_items duplicates by (page_id, item_ids) so same item on a page is removed regardless of price
CI / check (push) Successful in 43s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m12s
2026-08-23 15:52:20 +02:00
openhands 2b7b445b73 Fix catalog_items_bc dedup/health: use its actual schema (no cost columns)
CI / check (push) Successful in 41s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m11s
2026-08-23 15:39:07 +02:00
openhands 34475e9bc2 Fix dedup to also remove duplicate catalog_items/catalog_items_bc rows (comma-list-aware item_ids remap)
CI / check (push) Successful in 37s
CI / release (push) Skipped
CI / deploy (push) Successful in 58s
2026-08-23 15:30:52 +02:00
openhands 5a73ba292e Add one-click 'Fix alles' button to catalog page header (runs full furni maintenance)
CI / check (push) Successful in 45s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m25s
2026-08-23 15:21:26 +02:00
openhands cd418e0390 Register diagnostic scripts as knip entry points to fix CI unused-files check
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m6s
2026-08-23 15:14:40 +02:00
openhands fd603129aa Fix hardcoded palette color in catalog maintenance page (admin theme audit)
CI / check (push) Failing after 29s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-23 15:11:27 +02:00
openhands ca1756fbb0 Fix pre-existing type errors in diagnostics scripts (blocked pre-push tsc hook)
CI / check (push) Failing after 31s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-23 15:07:58 +02:00
openhands 536b61c7e7 Add catalog maintenance page with sprite-id, dedup and FurnitureData id-alignment repairs 2026-08-23 15:05:49 +02:00
openhands 02a3176dca Batch LibreTranslate furnidata translations via the array API
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m7s
Translate deduplicated texts in batches of 48 with 4 parallel workers
instead of one request per string, serve cached hits locally, and
persist results so rebuilds never re-call the API for the same text.
2026-08-23 13:43:02 +02:00
openhands 5311ee1fb8 Force catalog_items.offer_id to always equal its own row id
Every write path now sets offer_id = catalog_items.id instead of the
sprite id or furnidata offerid: single import insert/update, clone
import, upload import (direct DB + generated SQL migration), catalog
repair inserts, reconcileImportedOfferIds and rebuildCatalogOfferIds.

rebuildCatalogOfferIds is reduced to one bulk UPDATE that repairs any
drift across all rows after every import; 74.838 legacy rows were
repaired on the live database with this change.
2026-08-23 13:42:47 +02:00
openhands adb56eb80b Revert EMULATOR_MODE to rcon default, restore RCON config
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
2026-08-22 22:32:24 +02:00
openhands f24426c1fa Enable FurnitureData.json writes during furniture import
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m3s
- Change skipFurniDataWrite from true to false in both import routes
- Previously: FurnitureData.json entries were deferred/skipped during import
- Now: Entries are written immediately after each furniture item import
- Result: FurnitureData.json is updated directly, translations work again, offer_id fix preserves correctly set values
2026-08-22 21:12:06 +02:00
openhands 19450d56c5 Fix rebuildCatalogOfferIds to preserve correctly set offer_id during import
CI / check (push) Successful in 32s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m23s
- Change condition from  to
- Prevents overwriting offer_id that was correctly set to sprite_id during furniture import
- Fixes catalog showing wrong furniture when offer_ids and sprite_ids don't match
2026-08-22 20:52:23 +02:00