Files
ECS-FullStack/README.md
2025-10-04 10:41:29 -04:00

6.6 KiB

ECS Full Stack

A full-stack example project that integrates a React frontend, an Express backend, and a Discord bot. The app provides a dashboard for server admins to manage bot settings and invites, plus Discord moderation/integration features via a bot running with discord.js.

This README documents how to get the project running, what environment variables are required, where to get Discord keys, how the invite token flow works, and basic troubleshooting tips.

Repository layout

  • frontend/ — React (Create React App) frontend. Uses REACT_APP_API_BASE to communicate with the backend in dev and production.
  • backend/ — Express backend and API server that also coordinates with the discord-bot library to manage guilds, invites, and settings. Uses environment variables for configuration.
  • discord-bot/ — small wrapper that logs the bot in and exposes the discord.js client used by the backend.
  • checklist.md, README.md, other docs and small scripts at repo root.

What this project does

  • Provides a React dashboard where a user can view servers the bot is connected to and manage per-server settings (welcome/leave messages, autorole, toggling commands, invite creation/listing/deletion).
  • Runs a Discord bot (discord.js) that performs moderation and server features. The backend and bot are closely integrated: the backend hosts the API and the bot client is shared to fetch guild data and manipulate invites/channels/roles.
  • Uses a short-lived token flow to authorize invite deletions from the frontend without embedding long-lived secrets in the client.

Quickstart — prerequisites

  • Node.js (recommended 18.x or later) and npm
  • A Discord application with a Bot user (to get DISCORD_CLIENT_ID and DISCORD_CLIENT_SECRET) — see below for setup steps
  • Optional: a VPS or Tailscale IP if you want to run the frontend/backend on a non-localhost address

Environment configuration (.env)

There are env files used by the backend and frontend. Create .env files in the backend/ and frontend/ folders for local development. Examples follow.

backend/.env (example)

PORT=3002 HOST=0.0.0.0 BACKEND_BASE=http://your-server-or-ip:3002 FRONTEND_BASE=http://your-server-or-ip:3001 CORS_ORIGIN=http://your-server-or-ip:3001 DISCORD_CLIENT_ID=your_discord_client_id DISCORD_CLIENT_SECRET=your_discord_client_secret ENCRYPTION_KEY=a-32-byte-or-longer-secret INVITE_TOKEN_SECRET=optional-second-secret-for-invite-tokens

  • PORT / HOST: where the backend listens.
  • BACKEND_BASE and FRONTEND_BASE: used for constructing OAuth redirect URIs and links.
  • CORS_ORIGIN: optional; set to your frontend origin to restrict CORS.
  • DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRET: from the Discord Developer Portal (see below).
  • ENCRYPTION_KEY or INVITE_TOKEN_SECRET: used to sign short-lived invite tokens. Keep this secret.

Note: This project previously supported an INVITE_API_KEY static secret; that requirement has been removed. Invite deletes are authorized via short-lived invite tokens by default.

frontend/.env (example)

HOST=0.0.0.0 PORT=3001 REACT_APP_API_BASE=http://your-server-or-ip:3002

Set REACT_APP_API_BASE to point at the backend so the frontend can call API endpoints.

Create a Discord Application and Bot (short)

  1. Go to the Discord Developer Portal: https://discord.com/developers/applications
  2. Create a new application.
  3. Under "OAuth2" -> "General", add your redirect URI:
    • For dev: http://your-server-or-ip:3002/auth/discord/callback
    • Make sure BACKEND_BASE matches the host/port you set in backend/.env.
  4. Under "Bot" create a Bot user and copy the Bot token (NOT committed to source).
  5. Under "OAuth2" -> "URL Generator" select scopes bot and applications.commands and select permissions (e.g., Administrator if you want full access for testing). Use the generated URL to invite the bot to your guild during testing.

Store the Client ID / Client Secret in your backend/.env as DISCORD_CLIENT_ID and DISCORD_CLIENT_SECRET.

Invite token flow (why and how)

  • To avoid embedding long-lived secrets in a web client, invite deletions are authorized with a short-lived HMAC-signed token.
  • The frontend requests a token with: GET /api/servers/:guildId/invite-token
  • The backend returns { token: '...' }. The frontend then calls DELETE /api/servers/:guildId/invites/:code with header x-invite-token: <token>
  • Token TTL is short (default 5 minutes) and is signed using INVITE_TOKEN_SECRET or ENCRYPTION_KEY from backend .env.

Security note: Currently the /invite-token endpoint issues tokens to any caller. For production you should restrict this endpoint by requiring OAuth authentication and checking that the requesting user is authorized for the target guild.

Run the app locally

  1. Backend
cd backend
npm install
# create backend/.env from the example above
npm start
  1. Frontend
cd frontend
npm install
# create frontend/.env with REACT_APP_API_BASE pointing to the backend
npm run start
  1. Discord bot
  • The backend boots the bot client (see discord-bot/), so if the backend is started and credentials are correct, the bot will log in and register slash commands. You can also run the discord-bot project separately if you prefer.

Troubleshooting

  • Backend refuses to start or missing package.json: ensure you run npm install in the backend folder and run npm start from that folder.
  • CORS errors: verify CORS_ORIGIN and REACT_APP_API_BASE match your frontend origin.
  • Invite delete unauthorized: ensure backend INVITE_TOKEN_SECRET or ENCRYPTION_KEY is present and token TTL has not expired. Check the backend logs for validation details.
  • Token issues: clock skew can cause tokens to appear expired — ensure server and client clocks are reasonably in sync.

Developer notes

  • The dashboard UI is in frontend/src/components/ (notable files: Dashboard.js, ServerSettings.js, Login.js).
  • The Express API is in backend/index.js and uses discord-bot (discord.js client) to operate on guilds, invites, channels and roles.
  • Invite delete flow: frontend fetches a short-lived token then requests DELETE with header x-invite-token.

Next steps / suggestions

  • Harden /api/servers/:guildId/invite-token to require an authenticated user and verify the user has admin permissions for the guild.
  • Add rate-limiting to token issuance and optionally keep the old INVITE_API_KEY option for server-to-server automation.

If you want, I can add step-by-step instructions to create the .env files from templates, or implement the production safe option of authenticating /invite-token requests. Tell me which you'd prefer.


Updated: Oct 4, 2025