VulCode

WaveHost: a website, client panel and game panel as one system

WaveHost is a provider of game server, VPS and dedicated server hosting. We built it a new sales site with its own back end, a new client panel that provisions services automatically, and the move of accounts out of the old client panel.

The new WaveHost site: the hero section

Four parts of one brand

The site, the client panel, the game panel and the team bot run separately, each with its own deployment. The customer moves through them in one brand: from the offer on the site, through the order in the panel, to their own game server.

  • Sales site

    Game, VPS and dedicated server offers with a configurator, DDoS protection, reviews, questions and contact, in eight languages and three currencies. The WaveHost team changes the content and prices in the admin panel.

  • Client panel

    Orders, a wallet with invoices, services with a console, the affiliate programme, tickets and account settings, in six languages. A worker sets up every service that is ordered.

  • Game panel

    Pterodactyl in WaveHost colours. The client panel creates game servers in it through its API, and the customer also gets their console, power and settings in the client panel.

  • Team bot

    On the team's Discord it shows the site's stats: page views, clicks on offers, questions opened and traffic from referral links. It sends a report every day and says when a figure passes the next milestone.

The WaveHost sales site

It leads from the offer to the order in the client panel. The WaveHost team changes the texts in eight languages, the prices and all the content itself, in the site's admin panel.

Offers on the WaveHost site: service cards with starting prices

Offers

Every kind of service has a card with its starting price: web hosting, Discord bots, Minecraft, VPS, GTA and SCP:SL. The card leads to the packages, and prices convert to euro and dollars at the NBP rate.

The scrolling strengths section of the WaveHost site

Strengths one by one

Five themes of the brand in one scrolling section. The list on the left stays in place and its progress line shows which theme the reader is at.

Questions and the footer of the WaveHost site

Questions and footer

Questions open one under another, and the button under them takes the conversation to WaveHost's Discord. The footer gathers the game offers, contact and company details.

One offer list for the site and the panel

The WaveHost team enters prices, packages and the VPS configurator once, in the site's admin panel. The client panel takes them from there, and a worker makes sure only a package that fits on the servers is on sale.

The site's admin panel

  • Offers and packages

    The name, price, description, feature list, highlight and visibility of every package.

    Client panel: the package becomes an offer in the panel's shop
  • VPS configurator

    The steps, questions, options and surcharges a customer builds their own server from.

    Client panel: the same configurator with the same prices
  • Content and traffic

    Questions, reviews, files, the about page and texts in eight languages, plus analytics, referral links and discounts.

  • Running the client panel

    A separate area with its own sign-in: users, customer servers, IP addresses, nodes, locations, support and email.

Client panel

  • A shop with the site's offer

    Categories and packages come from the site. A package removed from the site is only hidden, so running services keep their offer.

  • The same configurator

    The panel reads the configurator from the site, so a new price or option works in it without a new deployment.

  • Technical parameters

    The team sets the node, game, cores, memory and disk, and the panel fills empty fields from the package's feature list.

  • A node for each order

    The customer picks a location, and the panel puts the service on the least loaded node there with free IP addresses.

Resource check

  • Free room on the nodes

    Every few minutes a worker checks each node's free memory and disk, with a margin, and its free IP addresses.

  • Packages leave and return on their own

    A package that no longer fits drops out of sale, and returns once resources free up.

    Client panel: the offer leaves the shop or comes back to it
  • Manual mode

    The team can switch any offer's availability to manual and decide on it themselves.

  • A node that does not answer

    An unreachable node leaves its offers as they are, instead of flipping them back and forth.

The client panel step by step

The customer orders, pays and runs a service from one account, in any of the panel's six languages. The dashboard shows the balance, services, the next payment, recent activity, invoices and the referral link at once.

The WaveHost client panel dashboard
  1. Order

    A VPS as a ready package or built in the configurator, a game server with a choice of location and game version, Paper or Vanilla for Minecraft for example.

  2. Payment from the wallet

    The customer tops up the balance through Stripe: BLIK, Przelewy24 or a card. The wallet pays for orders and renewals, and every payment comes with an invoice to print.

  3. Running the service

    A VPS has a console, power, stats, backups, a firewall, reinstall and sub-users. A dedicated server powers on and shows its hardware over IPMI or Redfish.

  4. Renewal and a bigger package

    A longer renewal period costs less, and moving to a bigger package costs only the difference for the days left in the period.

The service sets itself up

Once paid, the order goes into a BullMQ queue in Redis, and a separate worker sets up the service with nobody from the team involved. The panel API only adds the job, so the customer sees the service installing right away.

VPS

A virtual machine through the Proxmox API

A node in the location

The panel picks the least loaded node in the customer's location that has free IP addresses and a template of the chosen system.

Install from a template

The worker creates the machine from the system's template, with its IP addresses and the password or SSH key the customer gave.

Access details by email

The customer gets the address, port and user: SSH and root for Linux, or RDP and Administrator for Windows.

Service active

The panel marks the machine active and gives the console, power, stats and backups right away.

Game server

A server in Pterodactyl through its API

An account in the game panel

The worker creates the customer an account in Pterodactyl, or uses the one the customer already has.

Room on a node

With a location chosen, Pterodactyl picks the node itself; without one, the panel takes a free port on the node.

Limits from the package

Memory, disk and CPU come from the package, and the game's empty passwords, RCON for example, get a random value.

First start

Where the game needs it, the panel waits for the install to finish, uploads the start files, Minecraft's eula.txt for example, and only then starts the server.

A service from installation to removal

A worker moves every service through its states by its expiry date, so the WaveHost team does not watch deadlines by hand.

  1. Installing

    The worker

    Creates the machine or the game server. Until the install is done, the panel holds back actions that could get in its way, a renewal for example.

  2. Active

    The customer

    Runs the service and renews it from the wallet for one, two or three months. Every renewal comes with an invoice and an entry in the activity log.

  3. Suspended

    The worker

    Past the expiry date, it stops the VPS or suspends the game server in Pterodactyl. The data stays in place for seven days.

  4. Removed

    The worker

    After seven days without a renewal, it removes the machine or the game server, so its room on the node goes back on sale.

  • Suspended

    Renewal after expiry

    The customer

    Paying for a suspended service brings it back as active, with a new period counted from the day of payment.

    Active
  • Active

    System reinstall

    The customer

    The customer picks another system, the machine installs from scratch, and the new access details arrive by email.

    Installing
  • Active

    A bigger package

    The customer

    Changing the package adds resources until the end of the paid period, and the customer pays only the difference for the days left.

    Active

Tickets land on the team's Discord

The customer writes in the panel, and the WaveHost team answers where it works anyway: on its own Discord. A support bot joins the two sides of the conversation.

  • Customerin the client panel
  • Client panelAPI and ticket database
  • Support boton the WaveHost Discord
  • WaveHost teamin the ticket channel
  1. CustomerClient panel

    Step 1 of 5: A new ticket

    The customer gives the subject, priority and first message in the Support tab, without leaving the panel.

  2. Client panelSupport bot

    Step 2 of 5: A private ticket channel (in the background)

    The bot opens a channel only the team can see and pins a card in it with the subject, priority, first message and a button with the customer's details.

  3. WaveHost teamCustomer

    Step 3 of 5: A reply from Discord

    A message written in the channel reaches the thread in the panel. The bot marks it delivered, and read once the customer opens it.

  4. CustomerWaveHost team

    Step 4 of 5: The conversation goes on

    The customer's replies appear in the channel under their name, and the team sees when the customer is typing. Replies can also be sent from the Support tab of the admin panel.

  5. WaveHost teamClient panel

    Step 5 of 5: Closing

    The customer closes the ticket in the panel, or the team with a button in the channel after confirming. The channel locks and stays in the history as closed.

A migration script moved the accounts

WaveHost's customers had their accounts, credit and payment history in the previous panel. We wrote a script that moves them to the new panel: it reads the old database with SQL queries and writes through the new panel's model, with its validation.

scripts/migrate-legacy-panel.tstypescript
const DRY_RUN = process.argv.includes("--dry-run"); const LEGACY_ID_PREFIX = "legacy-panel:"; const migratedId = (legacyId: string) => `${LEGACY_ID_PREFIX}${legacyId}`; async function main() {  await migratePartnerLevels();  await migrateUsers();  await migratePayments();  await migrateOrders();  await migrateEarningsHistory();}
  1. Everything the customer had

    Partner levels, accounts with their wallet credit, referrals, payments, orders and commission history, in the order they depend on each other.

  2. A trial run

    With the --dry-run flag the script only lists what it would move and writes nothing, so the team sees the result before the database changes.

  3. No duplicates

    Every moved row carries its identifier from the old panel, so running the script again skips what has already moved.

  4. No guessing

    Old referral codes get a prefix so they cannot clash with new ones, and an order with no counterpart in the new catalogue waits for a manual check.

An account that holds money and servers

The panel holds customers' credit and access to their machines, so the protection covers sign-in, access to services and payments.

  • Two-factor sign-in

    TOTP codes from an authenticator app, and passkeys the customer signs in with and no password.

  • A confirmed email address

    An account works once its address is confirmed. A worker removes an account not confirmed within a day.

  • Protected forms

    Cloudflare Turnstile on sign-up, sign-in and password reset, and separate attempt limits in Redis for sign-in, payments, purchases, reinstalls and the firewall.

  • Sub-users with permissions

    The owner gives another person access to one service and chooses what they may do: power, console, backups, firewall or renewal. A co-manager can pass on only what they hold themselves.

  • Log and devices

    Sign-ins, renewals and actions on services are recorded with their time, and in the settings the customer sees their signed-in devices and can sign them out.

  • Payments signed by Stripe

    The balance grows only after a Stripe event with a checked signature, and every payment from the wallet gets an invoice.

Questions about this project

Is your project like this one?

Describe what you want to build. We reply within an hour with questions and a free quote.

Client review

Vulcode.com built our website and we're very happy with the result. The site runs smoothly, is well optimised and displays correctly on every device. The whole rollout went without a hitch, and the source code is clean and ready for further development. We appreciate the punctuality and the technical support at every stage.

WaveHostSzymonCEO, WaveHostTrustpilot