This is the community website for MegaVolts, a private server for the third-person shooter MicroVolts. It's where players check the rankings, dig through their match history and stats, read the news, manage their account and clan, and buy in-game currency.
Live at https://megavolts.online
Every request goes to Next.js first. For anything under /api/*, its middleware reads the BACKEND_TYPE setting and either answers the request itself or quietly forwards it to one of the other two backends. Cookies and request bodies pass straight through in both directions, so logging in and staying logged in works the same no matter which backend is active. In practice you pick a backend by choosing which Docker Compose file you run.
node Next.js API routes (the default)
java Spring Boot API
dotnet ASP.NET Core API
| Layer | What it uses |
|---|---|
| Frontend | Next.js (App Router), React 19, TypeScript, Tailwind CSS |
| Node backend | Next.js route handlers, mysql2, argon2, otplib |
| Java backend | Spring Boot 4, Java 21, JdbcTemplate, argon2-jvm |
| .NET backend | ASP.NET Core 10, C# 13, Dapper with MySqlConnector, Konscious argon2 |
| Database | MySQL / MariaDB, shared with the C++ game server (the site never changes the schema) |
| Auth | Server session cookies (httpOnly, SameSite Strict), argon2id, TOTP two-factor |
| Resend | |
| Uploads | ImgBB, for avatars, clan crests, and news banners |
| Payments | Paddle as the main one (work in progress), Paylink as the older one |
| GeoIP | MaxMind GeoLite2 (city and ASN), plus VPN and datacenter detection |
You sign up with an email code sent through Resend, then log in. Sessions are cookie based, passwords are hashed with argon2id, and the login cookie is httpOnly and lasts a week. You can turn on TOTP two-factor with a QR code, reset a forgotten password, and set a custom avatar from either the built-in characters or your own uploaded image.
The home and news pages are rendered on the server so they work well for search engines, and they follow whichever backend is active. Admins post news in categories like announcements, patch notes, events, and promotions.
The clubhouse has the player and clan rankings, searchable profiles with level badges and titles, guestbooks, and a lawful or chaotic reputation vote for each player. Clans can be created, joined, and left, and clan leaders can manage members, handle join requests, hand over leadership, set a crest, and use clan chat.
Everything here comes from the match data the game server uploads to the database at the end of each match, covering combat hits, in-match events, and who joined or left when.
- Public scoreboards for every match, with mode-aware stats, badges like MVP and Bullseye, and a performance rating worked out on the site.
- A kill feed timeline that plays like the in-game one, with a point-of-view picker, filters by event type, per-kill assist and damage details, headshot and directshot markers, and tags for players who left early.
- An accuracy map showing where a player's hits land across head, body, arms, and legs, either combined or per weapon.
- Achievements read straight from the account's achievement bitmask and grouped by weapon and discipline.
- Performance dashboards with average rating, win rate, consistency, K/D, ADR, a rating trend graph, an activity heatmap, and win rates per map.
- Clan versus clan matchups with the score and crests lined up to the clan you're viewing.
- Conduct pages that surface repeat leavers and vote-kick patterns.
Admins get a players browser (online, all, search, or by id) and a matches browser with full scoreboards. There are moderation logs for currency, items, room settings, chat, anti-cheat detections, login history, and bans. A transactions and revenue view charts income by day, month, or all time. A world map plots each account's most recent login location from GeoLite2 and flags VPN or datacenter IPs. There's also alt detection that groups accounts by shared IP and hardware history, a chat conversation viewer, and leaderboards for the worst leavers and the most vote-kicked players.
The store is being moved from Paylink to Paddle, and a small provider layer picks the active gateway from the PAYMENT_PROVIDER setting (Paddle by default). Paddle uses a hosted checkout and signature-verified webhooks, and it credits RockTokens once, with a check that the amount paid matches what was ordered. Paylink is the older path that creates a hosted invoice and polls for its status. Both share one transactions ledger and can post a note to Discord when a payment goes through.
Create apps/web/.env.local with the settings below.
| Variable | What it's for |
|---|---|
DB_HOST DB_PORT DB_NAME DB_USER DB_PASSWORD |
Game database connection, shared by all three backends |
NEXT_PUBLIC_SITE_URL |
Public site URL, used in SEO and email links |
RESEND_API_KEY EMAIL_FROM |
Sending email for sign-up codes and password resets |
IMGBB_API_KEY |
Image uploads for avatars, crests, and banners |
PAYMENT_PROVIDER |
Set to paddle (default) or paylink |
PADDLE_* NEXT_PUBLIC_PADDLE_* PADDLE_FORWARDER_CHECKOUT_URL |
Paddle checkout and webhook settings |
PAYLINK_BASE_URL PAYLINK_API_ID PAYLINK_SECRET_KEY |
Paylink settings |
DISCORD_WEBHOOK_URL |
Optional payment notifications |
GEOIP_DB_PATH GEOIP_ASN_DB_PATH |
MaxMind GeoLite2 files, placed in apps/web/data/ |
MAINTENANCE_MODE |
Set to true to show the maintenance page |
BACKEND_TYPE BACKEND_URL |
The backend switch, set for you by the Compose files |
For local development on the Node backend:
cd apps/web
npm install
npm run devThat serves the site at http://localhost:3000.
To run a full stack with Docker, from the repo root, stopping whatever is already running first:
# Node backend (default)
docker compose up -d
# Java backend
docker compose -f docker-compose.java.yml up -d --build
# .NET backend
docker compose -f docker-compose.dotnet.yml up -d --buildDuring development each backend also serves an API explorer, at :8080/swagger-ui.html for Java and :5000/swagger for .NET. Both are turned off in production.