Building ShieldMod: A Full-Stack Licensing Platform
The Beginning of a 565,528 Line Journey
Me, starting this project with “general ideas to implement”
It’s been almost 2 months since I launched ShieldMod in early November - a licensing distribution system for game modding developers. The project is still actively evolving, and before I dive into the technical horror stories (yes, there will be many), let me set the stage for what this project involved.
Situation: The Problem I Set Out to Solve
Software distribution with proper licensing is a complex problem. Existing solutions were either:
- Too expensive for indie mod developers
- Too basic without proper hardware binding
- Too insecure with easily bypassable protections
- Too ugly with UX from the early 2000s
I needed a system that could:
- Authenticate users across multiple platforms (web browsers and desktop applications)
- Manage licenses with activation limits, expiration dates, and usage tracking
- Distribute files securely so only authorized users can access them
- Track devices to prevent license sharing while allowing legitimate multi-device use
- Monitor everything with comprehensive audit logs for security and debugging
Task: What I Needed to Build
From the start, I had four core principles:
- Secure - Because licensing systems are literally attack magnets
- Modern - No PHP spaghetti code here
- User-friendly - Even my non-technical users should get it
- Easy to Use - For developers integrating the system
The platform would need four interconnected components: a frontend dashboard, backend API, desktop client, and client module.
Action: How I Built It
The Tech Stack
Frontend: The Pretty Face
- Next.js 14 (React framework with App Router)
- TypeScript 5 (because
anyis not a type, it’s a cry for help) - TanStack Query v5 (server state management that doesn’t make you cry)
- Tailwind CSS 3.4 (utility-first or die)
- shadcn/ui (beautiful Radix UI components)
- React Hook Form + Zod (form validation)
- i18next (Korean/English internationalization)
Backend: The Brain
- Python 3.11+ with FastAPI 0.109 (async all the things!)
- PostgreSQL 15 (the only database that matters)
- Redis 7 (session storage, caching, rate limiting)
- SQLAlchemy 2.0 (async ORM)
- Alembic (database migrations)
- JWT (python-jose) (token-based auth)
- Argon2id / bcrypt (password hashing)
- AES-256-GCM (file encryption)
Desktop Client & Module: The Muscle
- C++17/C++20 (because performance matters)
- DirectX 11 + ImGui (modern dark-themed GUI)
- WinHTTP (HTTPS communication)
- ECDSA P-256 (signature verification)
- HKDF-SHA256 (key derivation)
- Lua C API (scripting engine)
Key Technical Implementations
1. Dual Authentication System
Supporting both web and desktop clients required two authentication methods simultaneously:
Web Dashboard (Session-based):
Browser → POST /auth/login → Set HTTP-only cookie → Done
Desktop Client (JWT-based):
Client → POST /auth/client/login (with HWID) → JWT tokens → Periodic refresh
The JWT system uses short-lived access tokens (15 minutes) and longer refresh tokens (7 days), with proactive refresh 2 minutes before expiry.
2. Secure File Distribution
Files are encrypted server-side with AES-256-GCM, and each user gets a unique decryption key derived via HKDF.
This means:
- Each user gets a unique decryption key
- Keys are derived, not stored (reducing attack surface)
- Stolen files are useless without valid credentials
- Plaintext never touches the disk
3. Multi-Device Management
Users can register multiple devices (up to a configurable limit), each tracked independently with:
- HWID binding (CPU ID, Motherboard Serial, BIOS Serial - NOT MAC addresses!)
- Device nicknames (“Gaming PC”, “Laptop”, etc.)
- First seen / last seen timestamps
- Monthly removal quotas
Result: The Numbers Don’t Lie
Starting in early October 2025, launching in November, and still actively developing:
| Metric | Value |
|---|---|
| Total Lines of Code | 565,528 lines |
| Total Commits | 2,721 commits across 4 repos |
| Bug Fix Commits | 1,060 fix commits (39% of total!) |
| Database Migrations | 25 Alembic migrations |
Yes, you read that right. 39% of my commits were bug fixes.
Codebase Breakdown
| Component | Language | Lines of Code | Commits | Fix Commits |
|---|---|---|---|---|
| Backend API | Python | 49,627 | 256 | 86 |
| Admin Dashboard | TypeScript/React | 166,901 | 331 | 136 |
| Desktop Client | C++ | 214,701 | 267 | 83 |
| Client Module | C++ | 134,299 | 1,867 | 755 |
That Client Module with 755 fix commits? That’s where the real fun happened. More on that in future posts.
Key Features Delivered
Admin Dashboard:
- Real-time statistics (users, sessions, licenses)
- Registration trend charts (30-day)
- License expiration analytics
- User management with ban/unban + HWID reset
- Comprehensive audit logs with filtering and export
User Portal:
- Personal dashboard with usage stats
- Device management (add/remove with quotas)
- License information display
- Session management
- Telegram integration setup
Desktop Client:
- Modern ImGui interface with DirectX 11
- Secure credential storage via Windows Credential Manager
- In-memory file decryption
- Automatic token refresh
- Multi-device support
What’s Coming Next
Over the next few posts, I’ll be sharing the most painful, educational, and sometimes hilarious bugs I encountered:
- The Infinite Redirect Loop Nightmare - How logout became an endless dance between
/loginand/dashboard - HWID Instability: When MAC Addresses Betray You - 47 support tickets in one week because I trusted network adapters
- Race Conditions in Token Refresh - When 5 requests all decide to refresh the token at the same time
- 12 Lessons from Building ShieldMod - Key takeaways with memes
Lessons Learned (Spoiler Alert)
If I had to summarize these months of development:
“Of course I didn’t plan everything since the beginning, but I have general ideas to implement”
— Me, underestimating everything
The truth is, starting is not that easy. You can have the best tech stack, the cleanest architecture diagrams, and the most detailed specifications - but the moment you write git init, reality starts fighting back.
Key Takeaways:
- Security is an architecture — It’s not something you add at the end; it must be designed in from the start.
- Async is essential — For any system handling concurrent users, blocking I/O is a bottleneck.
- Type safety saves time — The hours spent defining types are repaid in fewer bugs and easier refactoring.
- Cross-platform is hard — Web and desktop have fundamentally different models; abstracting the differences requires careful design.
- Monitoring is not optional — Without comprehensive logs, debugging production issues is nearly impossible.
Stay tuned for the next post where I’ll share how a simple logout button caused 200+ API requests in under 5 seconds and crashed browser tabs across the globe.
This is part 1 of my “Building ShieldMod” series. Subscribe to follow along as I share the triumphs and tragedies of building a full-stack SaaS platform from scratch.