# EpicNext-CMS 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 full public-facing website, an administrative panel, NextAuth authentication (argon2id/bcrypt with MD5-to-argon2id upgrade), real-time RCON communication with the emulator, Server-Sent Events for live radio data, smooth page transitions, and extensive extensibility. --- ## 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 ```bash 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: ```sql 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 ```bash cp .env.example .env ``` Edit `.env` with at minimum: ```dotenv DATABASE_URL=mysql://user:password@127.0.0.1:3306/epicnext_cms AUTH_SECRET= 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 ```bash pnpm prisma:generate ``` Generates TypeScript types in `src/generated/prisma/`. ### 5. Run CMS Migrations ```bash 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: ```bash pnpm db:migrate:status ``` ### 6. Build & Start ```bash # Development (hot reload) pnpm dev # Production pnpm build && pnpm start ``` Open `http://localhost:3000` in your browser. ### 7. First Login 1. Register an account at `/register`, or log in with an existing emulator account. 2. Grant yourself admin access: `UPDATE users SET rank = 7 WHERE username = 'yourname';` 3. Visit `/admin` and configure your hotel via **Admin → CMS Settings**. --- ## 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 | | **AnimatePresence** | Framer Motion exit animations on modals, dialogs, and lightbox | | **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** | Base UI components use `data-open`/`data-closed` CSS animations | | **Compression** | Gzip compression enabled on all responses | | **Stale Times** | Optimized router cache (30s dynamic, 180s static) | --- ## 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) │ └── 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_url` - `radio_listeners_api_url` The radio player uses SSE for real-time updates (10s interval, no polling). ### Background Jobs Run as a persistent process: ```bash 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 ```bash pnpm dev # Start with hot reload pnpm typecheck # Type check all files pnpm test # Run test suite (312+ tests) pnpm analyze # Build and analyze bundle sizes pnpm biome:check # Lint and format ``` ### Contributing 1. Ensure typecheck and tests pass: `pnpm typecheck && pnpm test` 2. Follow existing code conventions (Server Components where possible, minimal client boundaries) 3. Use the `src/lib/motion.ts` animation variants for consistent animations 4. SQL migrations in `prisma/migrations/` must be idempotent --- ## License CC BY-NC-SA 4.0. See `LICENSE` for details.