A modern, real-time admin dashboard for Hytale game servers. Built with Next.js 16, React 19, and TypeScript.
- Real-time Monitoring - Live server stats, TPS/MSPT metrics, player counts, and memory usage
- Player Management - View online players, inventory, teleport, change game mode, kick, ban, mute
- World Overview - Monitor worlds with time/weather controls and entity management
- Live Console - Real-time server log streaming via WebSocket
- Live Chat - Monitor in-game chat messages in real-time
- Admin Panel - Execute commands, broadcast messages, manage players
- WebSocket Events - Real-time player join/leave/chat and server status updates
- JWT Authentication - Secure API access with token-based auth
- Dark Theme - Modern dark UI with blue accents
| Dashboard | Players | Admin |
|---|---|---|
| Server stats, metrics, memory chart, live activity | Player list, inventory viewer, teleport, gamemode | Console, chat, command, broadcast tabs |
- Bun (recommended) or Node.js 20+
- Hytale API Plugin running on your Hytale server (see below)
This dashboard requires the Hytale API Plugin(https://github.com/leonardoxr/hytale-api) to be installed and running on your Hytale server. The plugin provides a REST API and WebSocket server that this dashboard connects to.
To create credentials for the dashboard:
- Choose a client ID (e.g.,
dashboard) - Generate a secure password
- Hash it with bcrypt:
htpasswd -nbBC 12 "" "your-password" | tr -d ':\n' | sed 's/$2y/$2a/' - Add the client to the
clientsarray inconfig.jsonin the plugin - Use the plain-text password when logging into the dashboard
-
Clone the repository
git clone https://github.com/leonardoxr/hytale-dashboard.git cd hytale-dashboard -
Install dependencies
bun install
-
Configure environment
cp .env.local.example .env.local
Edit
.env.localwith your Hytale API server details:NEXT_PUBLIC_API_URL=http://localhost:8080 NEXT_PUBLIC_WS_URL=ws://localhost:8080/ws
-
Start development server
bun run dev
-
Open the dashboard
Navigate to http://localhost:3000 and log in with your API client credentials.
# Build for production
bun run build
# Start production server
bun run startFROM oven/bun:1 AS builder
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
FROM oven/bun:1-slim
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["bun", "server.js"]src/
├── app/ # Next.js App Router
│ ├── (dashboard)/ # Protected dashboard routes
│ │ ├── page.tsx # Overview with metrics
│ │ ├── players/ # Player management
│ │ ├── worlds/ # World management
│ │ └── admin/ # Admin panel with console/chat
│ ├── login/ # Login page
│ └── layout.tsx # Root layout
├── components/
│ ├── ui/ # Reusable UI components
│ ├── layout/ # Sidebar, header
│ ├── console-panel.tsx # Live server logs
│ ├── chat-panel.tsx # Live chat viewer
│ ├── metrics-card.tsx # TPS/performance display
│ ├── inventory-viewer.tsx # Player inventory grid
│ ├── teleport-dialog.tsx # Teleport form
│ ├── gamemode-selector.tsx # Game mode dropdown
│ ├── time-weather-control.tsx # World controls
│ └── entity-list.tsx # Entity table
└── lib/
├── api/ # API client & endpoints
│ ├── client.ts # HTTP client with JWT
│ ├── types.ts # TypeScript interfaces
│ ├── server.ts # Server endpoints
│ ├── players.ts # Player endpoints
│ ├── worlds.ts # World endpoints
│ ├── inventory.ts # Inventory endpoints
│ ├── chat.ts # Chat endpoints
│ └── admin.ts # Admin endpoints
├── auth/ # Authentication context
├── websocket/ # WebSocket client & hooks
└── utils.ts # Utility functions
The dashboard connects to the following Hytale API endpoints:
| Endpoint | Method | Description |
|---|---|---|
/auth/token |
POST | Authenticate and get JWT |
/server/status |
GET | Server status and memory |
/server/stats |
GET | Detailed server statistics |
/server/version |
GET | Game and API version |
/server/metrics |
GET | TPS, MSPT, CPU usage |
/server/plugins |
GET | List loaded plugins |
/server/whitelist |
POST | Manage whitelist |
/server/save |
POST | Force world save |
| Endpoint | Method | Description |
|---|---|---|
/players |
GET | List online players |
/players/{uuid} |
GET | Player details |
/players/{uuid}/stats |
GET | Player stats |
/players/{uuid}/location |
GET | Player position |
/players/{uuid}/teleport |
POST | Teleport player |
/players/{uuid}/gamemode |
GET/POST | Get/set game mode |
/players/{uuid}/permissions |
GET/POST | List/grant permissions |
/players/{uuid}/groups |
GET/POST | List/add groups |
/players/{uuid}/message |
POST | Send private message |
/players/{uuid}/inventory |
GET | Full inventory |
/players/{uuid}/inventory/hotbar |
GET | Hotbar slots |
/players/{uuid}/inventory/armor |
GET | Armor slots |
/players/{uuid}/inventory/give |
POST | Give item |
/players/{uuid}/inventory/clear |
POST | Clear inventory |
| Endpoint | Method | Description |
|---|---|---|
/worlds |
GET | List worlds |
/worlds/{id} |
GET | World details |
/worlds/{id}/stats |
GET | World statistics |
/worlds/{id}/time |
GET/POST | Get/set world time |
/worlds/{id}/weather |
GET/POST | Get/set weather |
/worlds/{id}/entities |
GET | List entities |
/worlds/{id}/blocks/{x}/{y}/{z} |
GET/POST | Get/set block |
| Endpoint | Method | Description |
|---|---|---|
/admin/command |
POST | Execute server command |
/admin/kick |
POST | Kick player |
/admin/ban |
POST | Ban player |
/admin/broadcast |
POST | Broadcast message |
/chat/mute/{uuid} |
POST | Mute player |
Real-time events via WebSocket at /ws:
| Event | Description |
|---|---|
player.connect |
Player connecting |
player.join |
Player joined the server |
player.leave |
Player left the server |
player.chat |
Chat message sent |
player.gamemode |
Game mode changed |
entity.remove |
Entity removed from world |
server.status |
Periodic server status updates |
server.log |
Server console log output |
- Framework: Next.js 16 with App Router & Turbopack
- UI Library: React 19
- Styling: Tailwind CSS
- Components: Radix UI primitives
- Charts: Recharts
- Icons: Lucide React
- Runtime: Bun
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_API_URL |
http://localhost:8080 |
Hytale API server URL |
NEXT_PUBLIC_WS_URL |
ws://localhost:8080/ws |
WebSocket endpoint URL |
# Start dev server with Turbopack
bun run dev
# Run linter
bun run lint
# Type check
bunx tsc --noEmit
# Build for production
bun run buildContributions are welcome! Whether you're fixing bugs, adding features, improving documentation, or suggesting ideas, we appreciate your help.
-
Fork the repository
gh repo fork leonardoxr/hytale-dashboard --clone cd hytale-dashboard -
Install dependencies
bun install
-
Set up your environment
cp .env.local.example .env.local # Edit .env.local with your API server details -
Start the development server
bun run dev
Before opening an issue, please:
- Search existing issues - Check open issues and closed issues to avoid duplicates
- Use issue templates - Select the appropriate template (bug report or feature request)
Include the following information:
- Clear description of the bug
- Steps to reproduce
- Expected behavior vs actual behavior
- Browser and OS version
- Screenshots or screen recordings if applicable
- Console errors (if any)
- API server version (if relevant)
Include:
- Clear description of the feature
- Use case / problem it solves
- Proposed implementation (optional)
- Mockups or examples (optional)
Use descriptive branch names with prefixes:
feature/- New features (e.g.,feature/player-search)fix/- Bug fixes (e.g.,fix/websocket-reconnect)docs/- Documentation changes (e.g.,docs/api-examples)refactor/- Code refactoring (e.g.,refactor/auth-context)style/- UI/styling changes (e.g.,style/dark-mode-tweaks)
Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat- New featurefix- Bug fixdocs- Documentation onlystyle- Formatting, missing semicolons, etc.refactor- Code change that neither fixes a bug nor adds a featureperf- Performance improvementtest- Adding testschore- Maintenance tasks
Examples:
git commit -m "feat(inventory): add item tooltip with enchantments"
git commit -m "fix(websocket): handle reconnection during auth refresh"
git commit -m "docs(readme): add API permissions table"-
Create your feature branch
git checkout -b feature/amazing-feature
-
Make your changes
- Write clean, readable code
- Follow the existing code style
- Add comments for complex logic
- Update documentation if needed
-
Test your changes
bun run lint # Check for lint errors bun run build # Ensure build passes bunx tsc --noEmit # Type check
-
Commit your changes
git add . git commit -m "feat(scope): add amazing feature"
-
Keep your branch updated
git fetch origin git rebase origin/main
-
Push and create PR
git push origin feature/amazing-feature
-
Open a Pull Request
- Go to the repository on GitHub
- Click "Compare & pull request"
- Fill out the PR template:
- Title: Clear, concise description
- Description: What changes were made and why
- Related Issues: Link any related issues (e.g., "Closes #123")
- Screenshots: Include before/after screenshots for UI changes
- Testing: Describe how you tested the changes
- Automated checks - Ensure lint and build pass
- Code review - A maintainer will review your code
- Feedback - Address any requested changes
- Approval - Once approved, your PR will be merged
Tips for faster reviews:
- Keep PRs focused and small (< 400 lines when possible)
- One feature/fix per PR
- Write clear PR descriptions
- Respond to feedback promptly
- Use TypeScript for all new code
- Define interfaces for all props and API responses
- Avoid
anytype - useunknownif type is truly unknown - Use descriptive variable and function names
// Good
interface PlayerCardProps {
player: PlayerInfo
onKick?: (uuid: string) => void
}
// Avoid
interface Props {
data: any
callback?: Function
}- Use functional components with hooks
- Keep components small and focused (< 200 lines)
- Extract reusable logic into custom hooks
- Use
'use client'directive only when needed
// Good - focused component
export function PlayerStats({ player }: { player: PlayerInfo }) {
return (
<div className="grid gap-4">
<StatCard label="Health" value={player.stats.health} />
<StatCard label="Mana" value={player.stats.mana} />
</div>
)
}- Use Tailwind CSS classes
- Use the
cn()utility for conditional classes - Follow existing color patterns (use CSS variables)
- Keep responsive design in mind
// Good
<div className={cn(
"rounded-lg border p-4",
isActive && "border-primary bg-primary/10"
)}>- Place components in
src/components/ - Place API functions in
src/lib/api/ - Place hooks in
src/lib/or with related components - Use barrel exports (
index.ts) for cleaner imports
Looking to contribute but not sure where to start? Check out issues labeled:
good first issue- Simple issues for newcomershelp wanted- Issues where we need community helpdocumentation- Documentation improvements
- GitHub Discussions - For questions and ideas, use Discussions
- Issues - For bugs and feature requests, use Issues
This project is licensed under the MIT License - see the LICENSE file for details.
- Hytale API Plugin - The backend REST API and WebSocket plugin that powers this dashboard. Required for the dashboard to function.
Made with Next.js and React