| backend | ||
| frontend | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| CHECKUP.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| LICENSE | ||
| README.md | ||
| screenshot.png | ||
VRCMT
A full-stack web application designed to help moderation teams manage reports, appeals, bans, and watchlists for a VRChat group or community.
Overview
This platform provides a centralized interface for moderators and administrators to handle common moderation tasks efficiently. It includes public forms for submitting reports and ban appeals, a private dashboard for the moderation team and an optional discord bot for reporting directly from a discord server.
Features
- Public Forms:
- Submit detailed incident reports with evidence uploads (images/MP4).
- Submit ban appeals.
- Moderator/Admin Dashboard:
- View report statistics (Total, Open, Investigating, High Priority).
- List, filter, and search reports.
- View detailed report information (submitter, reported user, incident details, evidence, notes, activity log).
- Update report status and priority.
- Assign reports to specific moderators (Admin).
- Add internal notes to reports.
- List, filter, and search ban appeals.
- View detailed appeal information (applicant details, reason, notes, voting).
- Cast votes on pending appeals (Approve/Deny).
- Make final decisions on appeals (Admin).
- View aggregated user profiles (reports against/by, appeals, ban status, watchlist status, notes).
- Manage a user watchlist (Add/Remove).
- Record user bans (from reports or user profiles - Admin/Owner).
- View list of actively banned users.
- Unban users (deactivate bans - Admin/Owner).
- Admin Panel:
- Create new moderator or admin accounts.
- View list of existing moderators/admins.
- Delete moderator accounts (Owner can delete Admin accounts).
- Owner Settings Panel:
- Change the site header title dynamically.
- Configure Discord notification webhook URL.
- Import bans from VRChat group JSON data.
- User Settings:
- Change own display name (username).
- Change own password.
- Delete own account (requires password confirmation; Owner account cannot be deleted this way).
- Authentication:
- Secure login using JWT.
- Role-based access control (Moderator, Admin, Owner).
- "Remember Me" option on login (extends session to 30 days).
- Forced password change on first login for newly created users or if required by an admin.
- Deployment: Production-ready Docker Compose setup with optimized builds and volume persistence. Automatic database setup on first launch.
Tech Stack
- Backend: Node.js, Express.js, SQLite3, bcryptjs, jsonwebtoken, cors, dotenv, multer, file-type
- Frontend: React, Vite, Tailwind CSS, Axios, React Router, date-fns, react-hot-toast, react-icons, react-select
- Database: SQLite
- Deployment: Docker, Docker Compose
Prerequisites
- Node.js (v20+ recommended)
- npm (v9+ recommended)
- Docker
- Docker Compose
Getting Started (Development)
- Clone the repository:
git clone https://git.eidenz.moe/Eidenz/VRCMT cd VRCMT - Backend Setup:
cd backend npm install cp .env.example .env # Create .env file (adjust JWT_SECRET and other variables as needed) npm run db:setup # Initialize the SQLite database npm run dev # Start the backend dev server (usually on port 5001) - Frontend Setup:
cd ../frontend npm install # For frontend, Vite uses .env files like .env.development, .env.production cp .env.example .env.development # Create .env.development for local dev # Edit .env.development and set VITE_API_URL=http://localhost:5001/api (or your backend port) npm run dev # Start the frontend dev server (usually on port 5173 or similar) - Access: Open your browser to the frontend development server URL provided by Vite. Default admin login:
admin/password(change immediately).
Running in Production (Docker)
This is the recommended way to run the application for deployment.
- Clone the repository (if you haven't already).
- Ensure Docker & Docker Compose are installed.
- Create Data Directories:
mkdir -p ./data/database mkdir -p ./data/uploads/evidence # Adjust permissions if necessary (e.g., sudo chown -R $USER:$USER ./data) - Create Production Environment File:
- Copy or rename
.env.exampleto.envin the project root. - IMPORTANT: Open
.envand set a strong, uniqueJWT_SECRET. - Review and set other variables like
FRONTEND_BASE_URLfor CORS and webhook link generation. - Do not commit
.envto version control.
- Copy or rename
- Build and Run with Docker Compose:
# Build the image and start the container in detached mode docker compose up --build -d- The first time this runs, the
entrypoint.shscript will automatically create and set up the database file (moderation.db) inside the./data/databasedirectory on your host via the volume mount.
- The first time this runs, the
- Access: Open your browser to
http://localhost:8080(or the host port you mapped indocker-compose.yml). Default admin login:admin/password(change immediately). - View Logs:
docker compose logs -f vrcmt - Stop:
docker compose down
Environment Variables
Configure the application using environment variables. Create a .env file in the project root for Docker production runs. For backend development, use a .env file in the backend directory. For frontend development, use .env.development in the frontend directory.
Key Variables (primarily for backend .env / root .env for Docker):
NODE_ENV: Set toproductionfor Docker,developmentotherwise.PORT: Port the backend server listens on inside the container (default:5001).FRONTEND_BASE_URL: Full URL of the deployed frontend (e.g.,https://yourdomain.com). Used for CORS and link generation in webhooks.JWT_SECRET: CRITICAL - A strong, random secret key for signing authentication tokens.JWT_EXPIRES_IN: Default token validity (e.g.,1h,1d,7d).JWT_EXPIRES_IN_REMEMBER_ME: Token validity when "Remember Me" is checked (e.g.,30d).DATABASE_PATH: Path to the SQLite database file relative to the backend directory or an absolute path (e.g.,database/db/moderation.dbfor default, or/app/backend/database/db/moderation.dbinside Docker).UPLOAD_PATH: Path to the evidence upload directory relative to the backend directory or an absolute path (e.g.,uploads/evidencefor default, or/app/backend/uploads/evidenceinside Docker).GROUP_BAN_PAGE_URL: (Optional) URL to your VRChat group's ban management page for quick access after banning a user.LOGIN_MAX_FAILED_ATTEMPTS: Max failed login attempts before lockout (default: 5).LOGIN_ATTEMPT_WINDOW_MS: Time window for counting failed attempts in ms (default: 15 mins).LOGIN_LOCKOUT_PERIOD_MS: Duration of lockout in ms (default: 30 mins).
Frontend Specific (frontend/.env.development, frontend/.env.production):
VITE_API_URL: Full URL to the backend API (e.g.,http://localhost:5001/apifor dev). For production build within Docker, this is often set to/apito use a relative path if served from the same domain or proxied.VITE_GROUP_BAN_PAGE_URL: (Optional) URL to your VRChat group's ban management page. Mirrors the backend variable for frontend use.
Folder Structure
/
├── backend/ # Node.js/Express API
│ ├── controllers/
│ ├── database/ # SQLite DB file (if not in data/) and setup script
│ ├── middleware/
│ ├── node_modules/
│ ├── public/ # Frontend build output (copied during Docker build)
│ ├── routes/
│ ├── uploads/ # Evidence uploads (if not in data/)
│ ├── utils/
│ ├── .env.example # Example environment variables for backend
│ ├── server.js # Express server entry point
│ └── package.json
├── data/ # Persistent data (mounted via Docker volumes) - gitignored
│ ├── database/ # Host location for the SQLite DB file
│ └── uploads/ # Host location for evidence uploads
├── frontend/ # React Frontend Application
│ ├── node_modules/
│ ├── public/ # Static assets for frontend
│ ├── src/ # Frontend source code
│ ├── .env.example # Example environment variables for frontend
│ ├── index.html
│ └── package.json
├── .dockerignore # Files/folders ignored by Docker build
├── .env # Root environment variables for Docker Compose (gitignored)
├── .env.example # Example for root .env
├── .gitignore
├── docker-compose.yml # Docker Compose configuration
├── Dockerfile # Defines the production Docker image build
├── entrypoint.sh # Script for initial container setup (e.g., DB init)
└── README.md # This file
