# CLAUDE.md — LetsBe Hub ## Purpose You are the engineering assistant for the LetsBe Hub Dashboard. This is the admin dashboard and API for managing the LetsBe Cloud platform. The Hub provides: - **Admin Dashboard**: Next.js admin UI for platform management - **Customer Management**: Create/manage customers and subscriptions - **Order Management**: Process and track provisioning orders - **Server Monitoring**: View and manage tenant servers - **Netcup Integration**: Full server management via Netcup SCP API - **Token Usage Tracking**: Monitor AI token consumption ## Tech Stack - **Next.js 15** (App Router) - **TypeScript** (strict mode) - **Prisma** (PostgreSQL ORM) - **TanStack Query** (React Query v5) - **Tailwind CSS** + shadcn/ui components - **NextAuth.js** (authentication) ## Project Structure ``` src/ ├── app/ # Next.js App Router │ ├── admin/ # Admin dashboard pages │ │ ├── customers/ # Customer management │ │ │ └── [id]/ # Customer detail with order creation │ │ ├── orders/ # Order management │ │ │ └── [id]/ # Order detail with DNS, provisioning │ │ ├── servers/ # Server monitoring │ │ │ └── netcup/ # Netcup servers management │ │ │ └── [id]/ # Netcup server detail │ │ ├── settings/ # Admin settings │ │ └── layout.tsx # Admin layout with sidebar │ ├── api/v1/ # API routes │ │ ├── admin/ # Admin API endpoints │ │ │ ├── customers/ # Customer CRUD │ │ │ ├── orders/ # Order CRUD + provisioning │ │ │ ├── netcup/ # Netcup SCP API integration │ │ │ └── servers/ # Server management │ │ └── public/ # Public API endpoints │ └── (auth)/ # Authentication pages ├── components/ │ ├── admin/ # Admin-specific components │ │ ├── create-order-dialog.tsx # Order creation wizard │ │ ├── netcup-auth-setup.tsx # Netcup OAuth setup │ │ ├── netcup-server-link.tsx # Link orders to Netcup servers │ │ └── dns-verification-panel.tsx # DNS verification UI │ └── ui/ # Reusable UI components (shadcn/ui) ├── hooks/ # React Query hooks │ ├── use-customers.ts # Customer data hooks │ ├── use-orders.ts # Order data hooks │ ├── use-netcup.ts # Netcup API hooks │ └── use-dns.ts # DNS verification hooks ├── lib/ # Utilities and shared code │ ├── prisma.ts # Prisma client singleton │ └── services/ # Backend services │ ├── netcup-service.ts # Netcup SCP API client │ ├── dns-service.ts # DNS verification service │ └── settings-service.ts # System settings storage └── types/ # TypeScript type definitions ``` ## API Routes ### Admin Endpoints (authenticated) ``` # Customers GET /api/v1/admin/customers # List customers GET /api/v1/admin/customers/[id] # Get customer detail PATCH /api/v1/admin/customers/[id] # Update customer # Orders GET /api/v1/admin/orders # List orders POST /api/v1/admin/orders # Create order GET /api/v1/admin/orders/[id] # Get order detail PATCH /api/v1/admin/orders/[id] # Update order GET /api/v1/admin/orders/[id]/logs # Get provisioning logs (SSE) POST /api/v1/admin/orders/[id]/provision # Start provisioning # DNS Verification GET /api/v1/admin/orders/[id]/dns # Get DNS status POST /api/v1/admin/orders/[id]/dns/verify # Trigger DNS verification POST /api/v1/admin/orders/[id]/dns/skip # Manual DNS override # Servers GET /api/v1/admin/servers # List servers (derived from orders) # Netcup Integration GET /api/v1/admin/netcup/auth # Get auth status / poll for token POST /api/v1/admin/netcup/auth # Initiate device auth flow DELETE /api/v1/admin/netcup/auth # Disconnect Netcup account GET /api/v1/admin/netcup/servers # List all Netcup servers GET /api/v1/admin/netcup/servers/[id] # Get server detail POST /api/v1/admin/netcup/servers/[id]/power # Power actions POST /api/v1/admin/netcup/servers/[id]/rescue # Rescue mode GET /api/v1/admin/netcup/servers/[id]/metrics # Performance metrics GET /api/v1/admin/netcup/servers/[id]/snapshots # List snapshots POST /api/v1/admin/netcup/servers/[id]/snapshots # Create snapshot # Dashboard GET /api/v1/admin/dashboard/stats # Dashboard statistics ``` ## Netcup SCP Integration The Hub integrates with Netcup's Server Control Panel API for full server management. ### Authentication Uses OAuth2 Device Flow: 1. Hub initiates device auth, gets `user_code` and `verification_uri` 2. User visits Netcup and enters the code 3. Hub polls for token exchange 4. Tokens stored in `SystemSettings` table 5. Access tokens auto-refresh (5min expiry, offline refresh token) ### Capabilities - **Server List**: View all Netcup servers with live status - **Power Control**: ON/OFF/POWERCYCLE/RESET/POWEROFF - **Rescue Mode**: Activate/deactivate rescue system - **Metrics**: CPU, disk I/O, network throughput (up to 30 days) - **Snapshots**: Create, list, delete, revert snapshots - **Server Linking**: Link orders to Netcup servers by IP ### Key Service: `netcup-service.ts` ```typescript // Core methods netcupService.initiateDeviceAuth() // Start OAuth flow netcupService.pollForToken(deviceCode) // Complete OAuth netcupService.getServers() // List with IPs from interfaces netcupService.getServer(id, liveInfo) // Detail with live status netcupService.powerAction(id, action) // Power control netcupService.getServerInterfaces(id) // Get IP addresses netcupService.getAllMetrics(id, hours) // CPU/disk/network metrics ``` ## Development Commands ```bash # Start database (required first) docker compose up -d # Install dependencies npm install # Start development server npm run dev # Run database migrations npx prisma migrate dev # Generate Prisma client npx prisma generate # Seed database npm run db:seed # Type checking npm run typecheck # Build for production npm run build # App available at http://localhost:3000 ``` ## Key Patterns ### React Query Hooks All data fetching uses React Query hooks in `src/hooks/`: - `useCustomers()`, `useCustomer(id)` - Customer data - `useOrders()`, `useOrder(id)` - Order data - `useServers()` - Server list - `useDashboardStats()` - Dashboard metrics - `useNetcupServers()`, `useNetcupServer(id)` - Netcup servers - `useNetcupAuth()` - Netcup authentication status - `useServerMetrics(id, hours)` - Server performance metrics - `useServerSnapshots(id)` - Server snapshots Mutations follow the pattern: - `useCreateOrder()`, `useUpdateOrder()` - `useNetcupPowerAction()`, `useNetcupRescue()` - `useCreateSnapshot()`, `useDeleteSnapshot()`, `useRevertSnapshot()` - Automatic cache invalidation via `queryClient.invalidateQueries()` ### API Route Pattern ```typescript export async function GET(request: NextRequest) { // Auth check const session = await auth() if (!session || session.user.userType !== 'staff') { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } // Parse query params const searchParams = request.nextUrl.searchParams // Database query with Prisma const data = await prisma.model.findMany({...}) // Return JSON response return NextResponse.json(data) } ``` ### Component Pattern ```typescript 'use client' export function MyComponent() { const { data, isLoading, error } = useMyData() if (isLoading) return if (error) return return
...
} ``` ### Service Pattern Backend services in `src/lib/services/`: ```typescript class MyService { private static instance: MyService static getInstance(): MyService { if (!MyService.instance) { MyService.instance = new MyService() } return MyService.instance } async doSomething(): Promise { // Implementation } } export const myService = MyService.getInstance() ``` ## Database Schema (Key Models) ```prisma model Customer { id String @id @default(cuid()) name String email String @unique company String? orders Order[] } model Order { id String @id @default(cuid()) status OrderStatus domain String customerId String serverIp String? serverPassword String? netcupServerId String? # Linked Netcup server automationMode AutomationMode @default(MANUAL) customer Customer @relation(...) dnsVerification DnsVerification? } model SystemSettings { id String @id @default(cuid()) key String @unique value String @db.Text } ``` ## Coding Conventions - Use `'use client'` directive for client components - All API routes return `NextResponse.json()` - Use Prisma for all database operations - Follow existing shadcn/ui component patterns - Use React Query for server state management - TypeScript strict mode - no `any` types - Services are singletons exported from `lib/services/` - Environment variables in `.env.local` (never commit)