Skip to content

HISTORY website

The website of HISTORY, a Metin2 private server: game-linked accounts, rankings, an item shop, referrals, live chat and an admin console, in 13 languages.

Recommended
Client
HISTORY Metin2 server
My role
Full-stack engineer & DevOps specialist
Type
Game website and platform
Timeline
Apr 2026 – present
Built with
  • Next.js
  • MongoDB
  • MySQL
  • Coolify
  • Cloudflare
  • JavaScript
  • next-intl
  • Jotai
  • Tailwind CSS
  • Socket.IO
  • Zod
  • Nodemailer
  • Git
  • GitHub
  • Telegram

Screens13 screens

Screen 1 of 13

The home pageDesktop · ⁦1 / 13⁩

Select the centre screen to see it full size.

Overview

HISTORY is an old-school Metin2 private server: level 99, five classes, rebuilt quests and an item shop that sells nothing that changes damage. Its website is where a player's life outside the game happens: creating and protecting the account, downloading the client, following the rankings, chatting, voting, referring friends and buying cosmetics.

I built the website and its admin console, and I keep maintaining both. It writes to the live game's MySQL databases and keeps its own data in MongoDB, so a registration, a ban or a shop purchase lands in the game itself. It launched on 26 September 2026 in 13 languages, Arabic right to left, and serves 400+ registered users, about 100 of them active daily. I'm still adding features.

What I delivered

  • Accounts created in the live game database, activated only by an emailed code
  • Game bans that apply on the site too, and email changes confirmed by a code sent to the new address
  • Four public rankings (levels, guilds, votes, playtime) read from the game, with staff hidden
  • An item shop with categories, packages, discounts and in-game delivery
  • Two prize wheels, one for votes and one paid in Dragon Coins or Dragon Marks
  • Manual top-ups (PayPal, Revolut, Binance, bank) decided from the console or Telegram
  • A referral and affiliate program with fraud checks, a wallet and withdrawals
  • A live realm chat with private aliases, reactions, reports and moderation
  • An admin console for users, bans, shop, payments, referrals, chat, news, FAQ and settings
  • 13 languages for both the interface and admin-written content, Arabic right to left
  • Professional SEO Optimization for every public page: canonical and 13 language alternates, social cards, structured data and a sitemap

How I built it

A website that writes to the live game

The game owns the truth. Accounts, characters, guilds, coins and bans live in three MySQL databases on the game server, and the website keeps only its own data (sessions, codes, chat, referrals, the shop's catalogue and ledger) in MongoDB. A data layer merges the two into one player, and every write goes where the game will read it: a registration creates the game account, a ban sets the game's status, and a purchase is delivered into the game's item table.

Accounts the game can trust

  • A new account is created in the game blocked, and only the code sent to its own inbox activates it.
  • Changing the email needs a code sent to the new address.
  • One address may hold at most two accounts, counted across Gmail dots and plus tags, and only Gmail, Outlook and Yahoo are accepted. Registrations and email changes on one address are serialised, so two at once can't both slip past the cap.
  • Verification belongs to the account that proved it, never to another account on the same inbox, because anyone can type someone else's address. A test enforces that rule.
  • The game decides bans. A banned player can't use the account pages or their actions, and the site mirrors the game's ban expiry.

Money handled by hand, safely

Top-ups are paid by PayPal, Revolut, Binance or bank transfer and claimed by the player with a proof. A moderator accepts or rejects it from the console or straight from a Telegram card. Both paths run the same pipeline, and every decision starts with an atomic claim, so two moderators can't credit the same payment twice. An accepted top-up attaches the referrer's commission.

Referrals that resist abuse

Players share a code and earn Dragon Coins for each referred player who qualifies; approved affiliates earn a percentage of their referrals' top-ups, at a private rate if one is set. Nothing pays instantly: self-referrals, shared IPs and shared inboxes are refused, rewards wait for daily qualification, and commissions stay locked through the chargeback window before a wallet can withdraw them. Every wallet change is an atomic update plus a ledger row in one transaction.

The shop, the wheels and the chat

The item shop sells cosmetics and convenience, never damage, and delivers into the game. The Wheel of Destiny spends vote spins, and a second wheel is paid in Dragon Coins or Dragon Marks. The realm chat is one live room over server-sent events, where players talk under a write-once alias that hides their login, and staff moderate reports from the console.

An item shop that opens in under two seconds

The item shop took 13.2 seconds to open, and its full item list 39 seconds. The queries themselves were fast: the cost was the link to the database, about 88 KB/s, and every view pulled whole item documents, descriptions in all 13 languages included. One bundle of 135 items fetched 1.1 MB of descriptions just to print 135 names. Reading only the fields a page shows cut both pages by 87% and 85%, and I checked that the rendered pages stayed byte-identical.

Then I cached the public half of the storefront in process for 30 to 60 seconds, cleared from inside the write functions so no caller can forget. A cold storefront now does 9 database reads and a warm one does 1: the player's own account, which is never cached. Prices, stock and balances are always read fresh at the moment of purchase, so a card can show a stale stock count but a sale can never be wrong.

Measured on the live catalogue Before After
/shop 13.2 s ~1.7 s
/shop/items 39 s ~5.8 s
Database reads per warm storefront view 9 1

Elsewhere, hot public reads (settings, news, the FAQ, changelogs) are cached for 30 seconds and cleared on write, and the rankings hide staff characters and apply the same filter to their count, so pagination never lies.

A designer's poster, made into a page

The server's presentation was designed by Gheby as one long poster, 29,817 px tall. I turned it into a real page: one scrolling document with a contents sidebar that follows the reader, reusable components for its tooltips and boards, and all 13 languages instead of a single image.

13 languages, admin content too

The interface ships in 13 languages, and so does what admins write: every translatable field is a per-language object with an English fallback, edited through one field component and bulk-translated by scripts. Every public page declares its 13 alternates, and the home page carries structured data for the server as an organisation, a website and a video game.

By the numbers

Launch 26 September 2026
Players 400+ registered, ~100 active daily
Item shop open time 13.2 s → ~1.7 s
Languages 13, Arabic right to left
Codebase ~54,600 lines, 38 MongoDB models, 3 game databases

Next project

The HISTORY logo, a dragon-headed sword, with the word WIKI beneath it

HISTORY Wiki

Wiki and CMS · 2025

The player wiki of HISTORY, a Metin2 private server: 1,600+ items, monsters, maps, quests and skills in 13 languages, edited in place by its admin.

Have a project like this one?

A few lines are enough: what you need, and roughly when.

Start a project