9.9 KiB
EpicNext-CMS v1.0.1
A modern, high-performance content management system for Habbo hotel emulators, built on Next.js 16 (App Router) with Prisma 7 and React 19. Designed to integrate seamlessly with Polaris / Arcturus Morningstar MySQL/MariaDB databases.
Features a premium animated homepage (typewriter hero, floating orbs, scroll counters), a full admin panel, NextAuth authentication (bcrypt with MD5-to-bcrypt upgrade), real-time RCON communication, Server-Sent Events for live radio data, smooth page transitions, and PM2 production deployment.
System Requirements
| Component | Version | Notes |
|---|---|---|
| Node.js | >= 22 | Required by Next.js 16 |
| pnpm | >= 10.33.4 | Package manager (npm/yarn not supported) |
| MySQL / MariaDB | 8.0+ / 10.6+ | Shared with the emulator |
| Redis | 7.x+ | Optional — caching, rate limiting, SSE |
| Java | 17+ | Required only if building the emulator |
| Maven | 3.9+ | Required only if building the emulator |
Quick Start
1. Clone & Install
git clone https://gitlab.epicnabbo.nl/remco/EpicNext-Cms.git
cd EpicNext-Cms
pnpm install
2. Database Setup
The CMS shares a database with the Polaris/Arcturus emulator. Use an existing database or create a new one:
CREATE DATABASE IF NOT EXISTS epicnext_cms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
The CMS reads emulator-owned tables (users, items, rooms, bans, etc.) directly. It never creates, alters, or drops them.
3. Configure Environment
cp .env.example .env
Edit .env with at minimum:
DATABASE_URL=mysql://user:[email protected]:3306/epicnext_cms
AUTH_SECRET=<random 32+ character string>
HOTEL_NAME=YourHotel
APP_URL=http://localhost:3000
See .env.example for all optional variables (RCON, email, Redis, OAuth, PayPal, etc.).
4. Generate Prisma Client
pnpm prisma:generate
Generates TypeScript types in src/generated/prisma/.
5. Run CMS Migrations
pnpm db:migrate
Creates all CMS-owned tables (website_*, radio_*, acl_*, admin_audit_log, etc.) via idempotent SQL files in prisma/migrations/. Emulator tables are never touched.
Check migration status:
pnpm db:migrate:status
6. Build & Start
# Development (hot reload)
pnpm dev
# Production
pnpm build && pnpm start
Open http://localhost:3000 in your browser.
7. First Login
- Register an account at
/register, or log in with an existing emulator account. - Grant yourself admin access:
UPDATE users SET rank = 7 WHERE username = 'yourname'; - Visit
/adminand configure your hotel via Admin → CMS Settings.
Production Deployment (PM2)
pnpm build
pm2 start pnpm --name "next" -- start
pm2 save
Restart after updates:
git pull
pnpm install
pnpm build
pm2 restart next
The CMS runs behind an nginx reverse proxy on the default port 3000. Static assets (media uploads) are persisted via /api/media/* and survive rebuilds.
Scripts
| Command | Description |
|---|---|
pnpm dev |
Start development server (hot reload) |
pnpm build |
Production build |
pnpm start |
Start production server |
pnpm typecheck |
Run TypeScript type checking |
pnpm test |
Run all tests (Vitest) |
pnpm db:migrate |
Apply pending SQL migrations |
pnpm db:migrate:status |
Show migration status |
pnpm analyze |
Build + open bundle analyzer |
pnpm jobs:worker |
Start background task worker (systemd / PM2) |
pnpm biome:check |
Lint and format code |
Performance Features
| Feature | Description |
|---|---|
| React Compiler | Automatic memoization — reduces unnecessary re-renders |
| View Transitions API | Native browser transitions between page navigations |
| Lenis Smooth Scroll | Fluid, customizable scrolling (respects prefers-reduced-motion) |
| Server-Sent Events | Real-time radio now-playing & listeners via SSE (no polling) |
| Redis Caching | Caches API responses (home, radio config) up to 30s in Redis |
| Bundle Analyzer | Run pnpm analyze to visualize and optimize bundle sizes |
| RCON (TCP Socket) | Live commands to the emulator (credits, badges, kick, ban) |
| Streaming & Suspense | Next.js App Router streaming for fast page loads |
| Automatic Image Optimization | next/image with Sharp for resizing and WebP/AVIF |
| CSS-based Animations | input-glow, btn-shine, Reveal scroll animations, floating orbs |
| Compression | Gzip compression enabled on all responses |
| Stale Times | Optimized router cache (30s dynamic, 180s static) |
| PWA | Service worker with skip-waiting, stale CSS chunk recovery |
| Biome | Fast linting and formatting (replaces ESLint + Prettier) |
Architecture
├── prisma/
│ ├── schema.prisma # ~190 models (emulator + CMS)
│ └── migrations/ # 16 SQL migrations for CMS tables
├── scripts/
│ ├── apply-migrations.ts # Custom migration runner
│ ├── jobs-worker.ts # Background task scheduler
│ └── sql-statements.ts # SQL parsing utilities
├── src/
│ ├── app/ # Next.js App Router (pages & API routes)
│ ├── actions/ # Server Actions
│ ├── components/ # UI components
│ ├── lib/
│ │ ├── auth/ # NextAuth, password hashing, 2FA, SSO tickets
│ │ ├── services/ # RCON, email, currency, PayPal, alerts
│ │ ├── prisma.ts # Database connection singleton
│ │ ├── redis.ts # Redis client (ioredis)
│ │ ├── redis-cache.ts # Redis caching utility for API routes
│ │ ├── cache.ts # In-memory cache fallback
│ │ ├── motion.ts # Framer Motion animation variants
│ │ └── use-event-source.ts # React hook for SSE subscriptions
│ ├── messages/ # i18n translations (en, nl, de, fr, es, it, pt, da, no, sv)
│ └── env.ts # Zod-validated environment schema
├── public/
│ ├── assets/ # Images, icons, fonts
│ └── scripts/ # Client-side scripts (theme-init.js)
├── update-Nitrov3.sh # Emulator & Nitro updater utility
├── next.config.ts # Next.js configuration
└── .env.example # Environment template with all options
Database Ownership
| Component | Type | Migrations |
|---|---|---|
Emulator tables (users, items, rooms, etc.) |
Existing Polaris schema | None — CMS reads/writes only |
CMS tables (website_*, radio_*, etc.) |
CMS-owned | prisma/migrations/*.sql (16 files) |
| Migration tracking | cms_migrations table |
Auto-created by migration runner |
Optional Integrations
Emulator — RCON
For live actions (credits, badges, rank changes, kick, ban, hotel alerts). The emulator must be running with RCON enabled at RCON_HOST:RCON_PORT.
Client — Nitro
The /client page loads the Nitro client. Configure the client URL via Admin → CMS Settings (nitro_client_url). See update-Nitrov3.sh for deployment.
Radio
Supports any streaming radio (e.g., Azuracast). Configure endpoints via CMS Settings:
radio_now_playing_api_urlradio_listeners_api_url
The radio player uses SSE for real-time updates (10s interval, no polling).
Background Jobs
Run as a persistent process:
pnpm jobs:worker
Scheduled tasks:
- Daily 03:00 — Emulator JAR backup (requires
EMULATOR_JAR_PATH+EMULATOR_BACKUP_DIR) - Daily 04:00 — Cleanup login logs (>30 days) and expired password reset tokens (>7 days)
CAPTCHA
Supports Cloudflare Turnstile and Google reCAPTCHA. Configure via CMS Settings.
Theming
12 preset themes with fully customizable colors via Admin → Theme (/admin/theme).
AI Content Moderation
Optional OpenAI-powered moderation for comments and guestbook posts. Set OPENAI_API_KEY.
Development
pnpm dev # Start with hot reload
pnpm typecheck # Type check all files
pnpm test # Run test suite
pnpm analyze # Build and analyze bundle sizes
pnpm biome:check # Lint and format
Contributing
- Ensure typecheck and tests pass:
pnpm typecheck && pnpm test - Follow existing code conventions (Server Components where possible, minimal client boundaries)
- Use the
src/lib/motion.tsanimation variants for consistent animations - SQL migrations in
prisma/migrations/must be idempotent
License
CC BY-NC-SA 4.0. See LICENSE for details.