Admin Panel Overzicht
Web-based administratie interface voor game beheer.
Architectuur
┌─────────────────────────────────────────────────────────┐
│ Admin Panel (Next.js) │
│ ┌─────────────────────────────────────────────────────┐│
│ │ Pages ││
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ ││
│ │ │Dashboard│ │ Items │ │ Spelers │ │ Assets │ ││
│ │ └─────────┘ └─────────┘ └─────────┘ └──────────┘ ││
│ └─────────────────────────────────────────────────────┘│
│ │ │
│ ┌─────────────────────────────────────────────────────┐│
│ │ SpacetimeDB Client (TS SDK) ││
│ └─────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────┐
│ SpacetimeDB │
│ (Admin Reducers) │
└────────────────────────┘
Tech Stack
| Component | Technologie |
|---|---|
| Framework | Next.js 15 |
| UI | Tailwind CSS |
| State | React Query |
| SpacetimeDB | TypeScript SDK |
| Auth | NextAuth.js |
Features
Dashboard
- Online spelers teller
- Actieve quests
- Recent aangemaakte accounts
- Server metrics
Items Beheer
- Item definities CRUD
- Container types beheren
- Bulk import/export (JSON)
Spelers
- Speler zoeken
- Inventory bekijken
- Resources aanpassen
- Ban/unban
Asset Pipeline
- Ticket management
- Designer toewijzing
- Review workflow
- File uploads naar R2
Authenticatie
Admin accounts zijn gescheiden van spelers:
// lib/auth.ts
export const authOptions: NextAuthOptions = {
providers: [
CredentialsProvider({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
// Check admin_user tabel in SpacetimeDB
const admin = await spacetime.getAdmin(credentials.email);
if (admin && verifyPassword(credentials.password, admin.hash)) {
return { id: admin.identity, email: credentials.email };
}
return null;
}
})
]
};
Project Structuur
admin/
├── app/
│ ├── page.tsx # Dashboard
│ ├── items/
│ │ ├── page.tsx # Items lijst
│ │ └── [id]/page.tsx # Item editor
│ ├── players/
│ │ ├── page.tsx # Spelers lijst
│ │ └── [id]/page.tsx # Speler detail
│ ├── assets/
│ │ ├── page.tsx # Tickets overzicht
│ │ └── [id]/page.tsx # Ticket detail
│ └── api/
│ └── [...spacetime]/ # API routes
├── components/
│ ├── ItemForm.tsx
│ ├── PlayerCard.tsx
│ └── TicketBoard.tsx
├── lib/
│ ├── spacetime.ts # SpacetimeDB client
│ └── auth.ts # Authentication
└── types/
└── index.ts # TypeScript types
SpacetimeDB Verbinding
// lib/spacetime.ts
import { SpacetimeDBClient } from '@spacetimedb/sdk';
const client = new SpacetimeDBClient({
host: process.env.SPACETIME_HOST!,
moduleName: process.env.SPACETIME_MODULE!,
});
export async function createItem(item: ItemDefinition) {
return client.call('create_item_definition', [
item.itemId,
item.category,
item.displayName,
item.description,
item.iconPath,
item.maxStack,
item.isTradeable,
item.rarity
]);
}
export async function getPlayers() {
return client.query('SELECT * FROM player ORDER BY created_at DESC');
}
Development
cd admin
npm install
npm run dev
Environment Variables
# .env.local
SPACETIME_HOST=ws://localhost:3000
SPACETIME_MODULE=milenas-treehouse
NEXTAUTH_SECRET=your-secret-here
NEXTAUTH_URL=http://localhost:3001