Back to resume

Newsletter Rewards System

A small web app I built for a Minecraft network to reward players who sign up for its newsletter. The reward is a coupon for the network’s online store, powered by Tebex, which players can use to get in-game items. The newsletter runs on Ghost CMS.

The goal was to let players claim a store coupon after joining the newsletter, while making sure each Minecraft account could only claim the reward once. Using only an email address or Minecraft username would allow repeated claims with different emails or username changes. To prevent this, I added in-game verification to link each claim to the Minecraft account’s UUID, which stays the same when the username changes.

How it works

  1. A player subscribes to the Ghost CMS newsletter.
  2. Ghost CMS sends a webhook to the app when the signup is created.
  3. The app sends the player an email with a link to claim their reward.
  4. On the website, the player enters their Minecraft username and gets a verification code.
  5. They run /verify <code> on the Minecraft server through a custom plugin I also made.
  6. The server sends the code and player UUID back to the app, which verifies the request and links the in-game UUID to the newsletter account.
  7. The app creates a coupon through the Tebex API.
  8. The coupon is shown on the website and also sent to the player by email.

What I built

The project included the web app, backend, database, Minecraft plugin, Ghost CMS and Tebex integrations, email templates, and a custom Ghost theme to match the branding.

I used Nodemailer to send emails and MJML to build responsive email templates with broad compatibility across email clients.

I also set up Docker for the application and database, with GitHub Actions building the application image and publishing it to GitHub Container Registry (GHCR). On the production server, I set up Watchtower to pull new images and update the running container automatically.

Tech Stack

I chose this stack because the app is simple and I didn’t want to bring in Next.js with all of its extra features and complexity I don’t need. This seemed like a significantly lighter, faster, and less resource-intensive alternative for a cheap VPS. It may be more setup than a small app like this needs, but it was also a good chance to try something new. I also wanted to leave room for a possible admin dashboard to manage rewards and email templates later. This stack is also known as the BHVR stack.

  • Frontend: React, Vite, TypeScript
  • Backend: Bun, Hono, Zod
  • Database: MySQL, Drizzle
  • Minecraft plugin: Java, Spigot API
  • Integrations: Ghost CMS, Tebex API
  • Emails: Nodemailer, MJML
  • Deployment: Docker, GitHub Actions, GHCR, Watchtower

Flow Diagram

Back to resume