Exemple8 min de lecture

Test

Je test

t
themuslimarketer ·

Discord Bot Manager Dashboard

A modern SaaS dashboard for managing Discord bots hosted in Docker containers. Users can create, monitor, and operate bots, with tier-based billing via Stripe and quota enforcement.

Stack

ComponentTechnologyVersion
FrameworkNext.js16
RuntimeNode.js22
UI LibraryReact19
LanguageTypeScript5 (strict)
StylingTailwind CSS4
Component Libraryshadcn/uibase-nova
State ManagementReact Query5
Formsreact-hook-form7
ValidationZod4
NotificationsSonner2
Themenext-themes0.4
ChartsRecharts3
E2E TestsPlaywright1.59
Unit TestsVitest4

Quick Start

Prerequisites

  • Node.js 22+
  • npm 10+
  • A Discord OAuth application (for login)
  • Stripe publishable key (for billing)

Installation

  1. Clone and install:

    cd dashboard
    cp .env.example .env.local
    npm install
    
  2. Configure environment variables in .env.local:

    • NEXT_PUBLIC_API_URL — API backend URL (default: http://localhost:3001)
    • API_URL — Server-side API URL (must match NEXT_PUBLIC_API_URL for same-origin cookies)
    • NEXT_PUBLIC_DISCORD_LOGIN_URL — Discord OAuth entry point (from bot API)
    • NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY — Stripe publishable key for billing
    • NEXT_PUBLIC_APP_URL — Dashboard public URL (for OAuth callback)
  3. Start development:

    npm run dev
    

    Dashboard runs at http://localhost:3000

  4. API connection:

    • Option A (Recommended): Start the bot API at http://localhost:3001
      cd ../bot
      npm run dev
      
    • Option B (Offline mode): Use MSW mocks — set in .env.local:
      NEXT_PUBLIC_API_MOCKING=true
      
      All API endpoints are served by Mock Service Worker locally. Useful for frontend-only development when the bot API is unavailable.

Scripts

CommandPurpose
npm run devStart Next.js dev server (port 3000, Turbopack)
npm run buildBuild for production (outputs .next/standalone)
npm startRun production build (port 3000)
npm run lintRun ESLint on all TypeScript/JavaScript files

Testing scripts (vitest, playwright) are installed but not in package.json yet. Add them once test suites are created.

Environment Variables

VariablePurposeDev ExampleProd Example
NEXT_PUBLIC_API_URLAPI base URL (client-side)http://localhost:3001https://api.botmanager.xyz
API_URLAPI base URL (server-side, must match above)http://localhost:3001https://api.botmanager.xyz
NEXT_PUBLIC_WS_URLWebSocket base URL (live logs, stats)ws://localhost:3001wss://api.botmanager.xyz
NEXT_PUBLIC_DISCORD_LOGIN_URLDiscord OAuth entry pointhttp://localhost:3001/auth/discordhttps://api.botmanager.xyz/auth/discord
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYStripe publishable keypk_test_*pk_live_*
NEXT_PUBLIC_APP_URLDashboard public URL (OAuth callback)http://localhost:3000https://dashboard.botmanager.xyz
NODE_ENVEnvironment modedevelopmentproduction
NEXT_PUBLIC_API_MOCKINGEnable MSW mocks (offline mode)trueNever in prod

Project Structure

src/
├── app/                              # Next.js App Router
│   ├── (public)/                     # Public pages (landing, pricing)
│   ├── (auth)/                       # Auth routes (login, OAuth callback)
│   │   ├── login/page.tsx            # Discord OAuth flow
│   │   └── callback/page.tsx         # OAuth redirect handler
│   ├── (app)/                        # Protected routes (require session)
│   │   ├── dashboard/page.tsx        # User overview
│   │   ├── bots/                     # Bot management
│   │   │   ├── [id]/logs/            # Live logs via WebSocket
│   │   │   ├── [id]/stats/           # Performance metrics
│   │   │   └── [id]/env/             # Environment variables
│   │   ├── billing/page.tsx          # Stripe billing
│   │   ├── settings/page.tsx         # User settings & API keys
│   │   └── admin/                    # Admin panel (user list, audit log)
│   ├── api/[...path]/route.ts        # Proxy to bot API (cookie forwarding)
│   └── layout.tsx, providers.tsx     # Root layout & React providers
├── lib/
│   ├── api/                          # API client & endpoints
│   │   ├── types.ts                  # Shared TypeScript types
│   │   ├── fetcher.ts                # Fetch wrapper with error handling
│   │   └── endpoints/                # Endpoint builders (me, bots, billing, admin)
│   ├── query/                        # React Query configuration
│   │   ├── client.ts                 # QueryClient setup
│   │   ├── keys.ts                   # Query key factory
│   │   └── queries.ts                # Query definitions
│   └── ws/                           # WebSocket client
│       └── client.ts                 # Live logs & stats connection
├── hooks/                            # Custom React hooks
│   ├── use-bot-logs.ts              # Stream bot logs via WS
│   ├── use-bot-stats.ts             # Stream bot stats via WS
│   └── use-mobile.ts                # Responsive design breakpoint
├── components/
│   ├── ui/                           # shadcn/ui components
│   ├── layout/                       # Header, sidebar, navigation
│   ├── auth/                         # Login, logout UI
│   ├── bots/                         # Bot CRUD, actions
│   ├── billing/                      # Stripe checkout, plan selector
│   ├── common/                       # Reusable components
│   └── msw-provider.tsx              # MSW mock worker init
└── mocks/
    ├── handlers.ts                   # MSW request handlers
    ├── fixtures.ts                   # Mock data (users, bots, plans)
    ├── browser.ts                    # MSW browser worker setup
    └── server.ts                     # MSW server worker for tests

Features

Authentication

  • Discord OAuth 2.0: Login via Discord (handled by bot API at /auth/discord)
  • Session cookies: First-party cookies set by bot API, forwarded via dashboard proxy
  • Protected routes: /dashboard, /bots, /billing, /settings, /admin require active session

Bot Management

  • Create/Edit/Delete: Full CRUD operations on Discord bots
  • Environment variables: Pass secrets and config to bot containers
  • Container control: Start, stop, restart bots (mapped to Docker containers)
  • Status monitoring: Real-time bot status (running, stopped)

Monitoring & Logs

  • Live logs: Stream container logs via WebSocket (/bots/:id/logs)
  • Live stats: Stream CPU, memory, network metrics via WebSocket (/bots/:id/stats)
  • Charts: Visualize metrics over time (Recharts)

Billing & Quotas

  • Stripe integration: Manage subscriptions (free, pro, team tiers)
  • Quota enforcement: Limit bot creation based on plan
  • Customer portal: Self-service invoice & billing management
  • Checkout flow: Upgrade/downgrade tiers with Stripe Hosted Checkout

API Keys

  • Create/revoke keys: Generate personal API keys for bot operations
  • Scope-based access: Assign permissions (bots:read, bots:write)
  • Track usage: Last-used timestamp for key rotation

Admin Tools

  • User list: View all users, tier, quota usage
  • Audit log: Track actions (bot created, deleted, restarted)

Offline Support

  • MSW mocks: Toggle NEXT_PUBLIC_API_MOCKING=true to run dashboard without bot API
  • Mock data: Pre-defined users, bots, plans, billing fixtures
  • Full feature parity: All endpoints return realistic responses

How Authentication Works

  1. User clicks "Login with Discord" on /login
  2. Redirect to /auth/discord (on bot API at NEXT_PUBLIC_DISCORD_LOGIN_URL)
  3. Discord OAuth flow (handled by bot API)
  4. Bot API sets session cookie on response (HTTP-only, Secure, SameSite)
  5. Redirect back to /callback with authorization code or session
  6. Dashboard reads cookie and redirects to /dashboard
  7. Subsequent requests include the session cookie automatically
  8. Dashboard proxy (/api/[...path]/route.ts) forwards all requests to bot API with cookies intact

Key point: The dashboard itself doesn't handle OAuth — it proxies to the bot API. The bot API is responsible for creating and validating the session cookie.

MSW Mocking Mode

When NEXT_PUBLIC_API_MOCKING=true:

  • MSW worker intercepts all fetch requests in the browser
  • Mock handlers (src/mocks/handlers.ts) return realistic responses
  • In-memory state persists for the browser session
  • Useful for:
    • Frontend development without backend
    • Testing UI flows offline
    • Demo/staging without API access

Disable in production — set NEXT_PUBLIC_API_MOCKING=false (or omit it).

Testing

Vitest and Playwright are included but test suites are not yet configured.

Unit & Integration Tests (Vitest)

  • Run: npm run test (once configured)
  • Coverage: npm run test:coverage
  • Config: Add vitest.config.ts with jsdom environment

E2E Tests (Playwright)

  • Run: npm run test:e2e (once configured)
  • Config: Add playwright.config.ts
  • Focus on critical flows:
    • Discord login → redirect to dashboard
    • Create/delete bot
    • Upgrade subscription via Stripe
    • Admin user list (if accessible)

See DEPLOY.md for production testing checks.

Security

  • Content Security Policy (CSP): Strict headers configured in next.config.ts
  • HTTP security headers: HSTS, X-Frame-Options, Referrer-Policy, etc.
  • No hardcoded secrets: All credentials come from environment variables
  • Standalone build: Minified output, no source maps in production
  • Strict TypeScript: All code type-checked (strict mode enabled)
  • Bot API & Manager: ../bot/ — Discord bot hosting backend, internal REST API, Stripe webhook handler
  • Database & Infrastructure: ../docker-compose.yml — PostgreSQL + pgAdmin shared across projects

Deployment

See DEPLOY.md for:

  • Production build and runtime
  • Environment setup
  • Reverse proxy configuration (Caddy)
  • Domain & SSL with Cloudflare (IPv6-only VM)
  • Docker deployment
  • Post-deploy verification

Development Workflow

Local Setup

  1. Start bot API: cd ../bot && npm run dev (port 3001)
  2. Start dashboard: cd dashboard && npm run dev (port 3000)
  3. Open http://localhost:3000

Offline Mode

  1. Set NEXT_PUBLIC_API_MOCKING=true in .env.local
  2. Run npm run dev
  3. Use mock users and bots (no API required)

Code Quality

  • Linting: npm run lint (ESLint, TypeScript strict mode)
  • Formatting: Prettier configured via ESLint (use editor integration)
  • Type checking: TypeScript strict mode enabled in tsconfig.json

License

See root LICENSE file.

Partager𝕏in
t

themuslimarketer

Auteur

Entrepreneur musulman passionné par le marketing, l'IA et l'entrepreneuriat halal. Je partage ici mes apprentissages pour aider la communauté à construire des projets solides et alignés avec nos valeurs.