Mission Control
Space Gacha development dashboard. Built 2026-03-14 to 2026-03-16. Everything tracked, nothing lost.
Total Cards
710+
Series 1 + Series 2
Features Built
20+
This session alone
Bugs Fixed
22
Security + UX + logic
Dead Code Removed
740
Lines (14% of file)
What's Done (v1.11)
Full Card Catalog / Pokédex (OWNED / ALL / MISSING)
Visual Battle UI for daily PvP
Daily Login Calendar (7-day streak)
Welcome Back Bonus (3+ days absence)
Share Card Image (canvas PNG + watermark)
Pull History Log (last 100 pulls)
Card Lore links (Wikipedia / NASA)
Starter Guarantee (first pack = SR+)
Series 2 Type Advantages
Rarity sounds wired during reveal
Security hardening (XSS, trades, auth, codes)
SEO meta tags + JSON-LD
iOS scroll fix
Dead code cleanup (740 lines)
What's Next
Duplicate Recycling / Stardust Forge
Category Completion Rewards & Badges
PWA / Add to Home Screen
Invite / Referral System
Ranked Seasons
Procedural Ambient Music
Reskin: Cryptid / Dino / Myth / Deep Sea / Pixel Gacha
Battle Pass monetization
List on itch.io, post to Reddit
Enable Cloudflare Web Analytics
Version History
v1.11 — The Big Update LIVE
Features: Card Catalog, Visual Battle UI, Login Calendar, Welcome Back Bonus, Share Card, Pull History, Card Lore, Starter Guarantee, S2 Type Advantages, Rarity Sounds
Security: XSS protection, trade validation, server-side codes, caller verification, syncState caps, rate limiting
Fixes: DEF sort, starter guarantee, trade button, toast spam, event leaks, iOS scroll, dead code cleanup (740 lines)
SEO: JSON-LD, canonical URL, noscript, og fixes, aria-labels, reduced-motion
Security: XSS protection, trade validation, server-side codes, caller verification, syncState caps, rate limiting
Fixes: DEF sort, starter guarantee, trade button, toast spam, event leaks, iOS scroll, dead code cleanup (740 lines)
SEO: JSON-LD, canonical URL, noscript, og fixes, aria-labels, reduced-motion
v1.3 — UI Polish
Pack selector fixes, series buttons, spacing, cut canvas, trade sorting
v1.2 — Nebula Chronicles
210 new S2 cards, 10 SECRETs, 8 categories, 5 new pack types
v1.1 — Social Update
Server battles, friends, chat, trading, lobby, 9 ranks, raid boss
v1.0 — Launch
500+ cards, pack opening, PvP, daily missions, Netlify deploy
Security Fixes Applied
All critical vulnerabilities found and patched on 2026-03-16. Click any item to expand details.
XSS Protection
Trade System
Server-Side Hardening
Remaining Vulnerabilities
Found in second hacker simulation after hardening. Sorted by severity. Click to expand.
Inherent Limitations
Fundamental to the client-authoritative single-HTML architecture. Requires major rewrite to fix.
| # | Issue | Impact | Fix Requires |
|---|---|---|---|
| 1 | Console state manipulation | Full cheating | Server-side game logic |
Detail: All game state is accessible via browser console. S.stardust=9999999, S.cards={...}, save() — complete control over local state. syncState then pushes tampered data to server.Architectural root cause: Single-HTML file means all game logic is client-side JavaScript. No server authority over game state. This is the fundamental tradeoff of the architecture — simplicity and zero-backend deployment vs. security. | |||
| 2 | Daily limits client-only | Unlimited battles/packs | Server daily tracking |
| Detail: Daily pack limits, battle limits, and mission resets are tracked in localStorage. Clearing storage or modifying the date check gives unlimited daily resources. Fix approach: Server tracks daily action counts per player with date-based reset. Each pack open / battle / mission claim is a server mutation that checks and increments the counter. | |||
| 3 | Ad rewards no verification | Free packs bypass | AdSense SSV |
| Detail: When a player "watches an ad" for bonus packs, the reward is granted client-side without verifying the ad was actually viewed. Player can call the reward function directly. Fix approach: Implement AdSense Server-Side Verification (SSV). Google sends a callback to your server confirming the ad was viewed, then the server grants the reward. | |||
| 4 | PvP battle client-side | Fake wins | Server battle mutations |
| Detail: Both players run battle logic independently on their own clients. There's no authoritative server to determine the true outcome. A modified client always wins. Fix approach: Server battle mutations — both players submit teams, server runs deterministic battle logic, server announces winner and distributes rewards. | |||
| 5 | No real authentication | Impersonation | Clerk/Auth0 integration |
| Detail: Players are identified by a random visitorId stored in localStorage. Anyone who knows a player's visitorId can impersonate them. IDs are exposed in multiplayer interactions. Fix approach: Integrate Clerk or Auth0 for real authentication. Convex has built-in Clerk support. Players log in with email/Google/Discord, server verifies identity via JWT. | |||
| 6 | Gacha rates client-side | Guaranteed SECRETs | Server pack opening |
Detail: Pack opening RNG runs in the browser. Player can modify the rate tables or re-roll until they get the desired result. Math.random = () => 0.999 guarantees SECRET pulls.Fix approach: Server-side pack opening — client requests a pack, server runs RNG with its own Math.random, returns the cards. Client only displays the result. | |||
| 7 | Mutations callable by anyone | API abuse | Convex auth |
| Detail: Convex mutations are essentially public API endpoints. Anyone with the deployment URL can call any mutation with arbitrary arguments from their own code. Fix approach: Convex authentication — mutations check that the caller has a valid auth token from Clerk/Auth0. Unauthenticated calls are rejected at the framework level. | |||
| 8 | Redeem codes pattern guessable | Infinite codes | Server code table (done) |
| Detail: Original codes followed predictable patterns (SPACE-[WORD], LAUNCH-[WORD]). Brute-forcing was trivial. Fix applied: Codes moved to server-side Convex table. No pattern to guess. Each code has a max-uses limit and tracks which players have redeemed it. This one is actually fixed. | |||
| 9 | Import save arbitrary data | Injected stats | Server-authoritative state |
| Detail: The import/export save feature lets players paste arbitrary JSON that becomes their game state. Even with validation caps, clever manipulation can still inject favorable states. Fix approach: Fully server-authoritative state eliminates the import feature entirely. Or, import goes through a server validation mutation that cross-references against known game data. | |||
Feature Proposal
Top 10 features from 8-persona analysis. 8 of 10 implemented. Click any row to expand details.
| # | Feature | Status | Effort | Personas |
|---|---|---|---|---|
| 1 | Full Card Catalog / Pokédex | DONE | ~50 lines | 4 personas |
| What: Browse ALL cards in the game with OWNED / ALL / MISSING filter tabs. Search by name, filter by rarity and category. Shows completion percentage per category. Why: Collectors need to see what they're missing. Drives engagement by showing progress toward completion. Creates "gotta catch 'em all" motivation loop. Personas: The Completionist (primary), The Collector, The Explorer, The Social Player (shows off collection) Implementation: ~50 lines. Filters existing card database, renders grid with owned/missing indicators, category progress bars. Uses existing card rendering components. | ||||
| 2 | Visual Battle UI | DONE | ~150 lines | 3 personas |
| What: Animated battle screen showing both player's cards facing off. HP bars, attack animations, type advantage indicators, turn-by-turn combat log. Why: Battles were previously just "you won/lost" text. Visual feedback makes battles exciting, gives meaning to card stats, and makes type advantages visible. Personas: The Battler (primary), The Competitive Player, The Social Player Implementation: ~150 lines. Card-vs-card layout, CSS animations for attacks, HP bar transitions, type advantage glow effects. Uses Web Audio for hit/win/lose sounds. | ||||
| 3 | Daily Login Calendar | DONE | ~80 lines | 5 personas |
| What: 7-day streak calendar with escalating rewards. Day 1: 500 stardust, Day 7: guaranteed SR pack. Visual calendar grid shows claimed/upcoming days. Why: Daily login rewards are the #1 retention mechanic in gacha games. Creates habit formation. Streak anxiety prevents churn. 5 of 8 personas specifically requested this. Personas: The Daily Player (primary), The F2P Grinder, The Collector, The Casual, The Completionist Implementation: ~80 lines. localStorage tracks streak count and last claim date. Calendar UI with 7 slots, CSS animations for claiming. Streak resets if a day is missed. | ||||
| 4 | Welcome Back Bonus | DONE | ~30 lines | 4 personas |
| What: Special bonus popup for players returning after 3+ days of inactivity. Grants stardust and bonus packs based on days away (up to 7 days of rewards). Why: Re-engages lapsed players instead of punishing them for leaving. Reduces permanent churn. Makes returning feel rewarding rather than overwhelming. Personas: The Returning Player (primary), The Casual, The Collector, The Explorer Implementation: ~30 lines. Check lastLoginDate on load, calculate days absent, show modal with accumulated rewards. One-time claim per return. | ||||
| 5 | Duplicate Recycling | PENDING | ~60 lines | 4 personas |
| What: "Stardust Forge" — sacrifice duplicate cards for stardust or craft materials. Higher rarity = more stardust. Bulk recycling option for mass duplicates. Why: Duplicates currently have zero value, making pulls feel wasted. Recycling gives every pull meaning. Creates a stardust sink that balances the economy. Personas: The F2P Grinder (primary), The Collector, The Completionist, The Battler Implementation: ~60 lines. Select duplicates (keep at least 1), confirm sacrifice, animate destruction, award stardust. Rates: N=10, R=50, SR=200, SSR=500, UR=1000. | ||||
| 6 | Share Card Image | DONE | ~100 lines | 5 personas |
| What: Generate a shareable PNG image of any card with the Space Gacha watermark. One-tap save/share to social media. Includes card stats, rarity border, and player name. Why: Social sharing is the #1 organic growth driver for gacha games. "Look what I pulled!" drives FOMO and virality. Zero-cost marketing from every rare pull. Personas: The Social Player (primary), The Collector, The Competitive Player, The Explorer, The Content Creator Implementation: ~100 lines. Canvas API renders card at 1080x1920 with rarity-colored border, card image, stats overlay, and spacegacha.pages.dev watermark. Uses toBlob() for PNG export. | ||||
| 7 | Category Completion Rewards | PENDING | ~80 lines | 4 personas |
| What: Badges and bonus rewards for completing entire card categories (e.g., all Nebulae, all Exoplanets). Visual badge display in profile. Special frame for 100% completion. Why: Gives collectors concrete goals beyond "get everything." Category focus makes the collection feel structured. Badges provide social status and bragging rights. Personas: The Completionist (primary), The Collector, The Explorer, The Social Player Implementation: ~80 lines. Check owned vs total per category, award badge at 100%, display in profile grid. Reward: category-specific card back + stardust bonus. | ||||
| 8 | Pull History Log | DONE | ~40 lines | 3 personas |
| What: Scrollable log of last 100 pulls with timestamp, pack type, and cards received. Color-coded by rarity. Filterable by rarity tier. Why: Players want to track their luck. Transparency about pull rates builds trust. Data-driven players use this to analyze their actual rates vs published rates. Personas: The Analyst (primary), The F2P Grinder, The Competitive Player Implementation: ~40 lines. Array in localStorage, push on each pull, render as timestamped list in Stats tab. Auto-prunes at 100 entries. | ||||
| 9 | Starter Guarantee | DONE | ~5 lines | 2 personas |
| What: First pack opened by any new player guarantees at least one SR or higher card. Ensures an exciting first experience. Why: First impression is everything. A first pack of all N/R cards is devastating for retention. Guaranteeing a shiny card hooks the player immediately. Personas: The New Player (primary), The Casual Implementation: ~5 lines. Check if totalPulls === 0, if so force one card in the pack to SR rarity minimum. Simple conditional in pack opening function. | ||||
| 10 | Dead Code Cleanup | DONE | 740 lines removed | All |
| What: Removed 740 lines of unused code — unreachable functions, commented-out features, duplicate logic, unused CSS, dead event listeners. Why: 14% of the file was dead weight. Slows page load, increases parse time, makes maintenance harder, and increases attack surface (dead code can still have vulnerabilities). Personas: All personas benefit from faster load times and reduced bundle size. Implementation: Systematic audit of every function, CSS rule, and event listener. Verified no callers before removing. 740 lines removed, zero regressions. | ||||
Tier 2 Ideas
Interactive Tutorial
PWA / Home Screen
Mobile Bottom Nav
Friend Activity Feed
Invite / Referral
Ranked Seasons
SECRET Pity Timer
Offline Pack Bank
UX Audit Findings
5 user personas traced through actual code paths. Click any card to expand full findings.
Revenue Strategy
Multiple revenue streams from premium cosmetics to white-label services. Click any projection to expand details.
Quick Wins (This Week)
Tiered Ko-fi rewards ($3/$10/$25)
Stripe: $2.99/month Stardust Pass
5 purchasable card backs ($0.99 each)
Amazon affiliate links in card modals
TikTok pack opening clips
Revenue Projections
Framework Analysis
77% reusable framework, 23% theme-specific. Minimum reskin: 4-6 hours. Click any proposal to expand full details.
Framework
77%
Reusable across themes
Theme Content
23%
~1,085 lines to change
Min Reskin
4-6h
With emoji cards
Full Reskin
1-2d
With real images
Top 5 Reskin Proposals
SEO & Marketing Plan
Immediate (This Week)
Add canonical URL + JSON-LD schema
Fix Whale Gacha OG tags
Add noscript fallback
Enable Cloudflare Web Analytics (free)
Create 1200x630 OG banner image
Short-Term (This Month)
List on itch.io
Add Share button (card image generator)
Post to r/WebGames
Create @spacegacha Twitter
Key Marketing Angles
NASA hook: "I turned NASA's image library into a free gacha card game"
No P2W: Free game, no predatory monetization
Educational: Real astronomical facts on every card
Best subs: r/WebGames (600K), r/space (25M), r/gachagaming (400K)
No P2W: Free game, no predatory monetization
Educational: Real astronomical facts on every card
Best subs: r/WebGames (600K), r/space (25M), r/gachagaming (400K)
Performance Audit
Click any item to expand technical details.
WCAG Audit
Critical
user-scalable=no prevents zoom (WCAG 1.4.4)
Nav tabs are div not button — no keyboard access (WCAG 2.1.1)
33+ clickable divs not keyboard-accessible
Zero ARIA attributes on modals, tabs, progress bars
Most img tags missing alt text
Fixed
prefers-reduced-motion CSS added
aria-labels on 6 form inputs
Toast: role="alert" aria-live="assertive"
Audio Improvement Plan
For Chandler the audio engineer. All Web Audio API, zero audio files.
FIXED Rarity Sounds Never Played
N/R/SR/SSR/UR/SECRET SFX were defined but never called during card reveal. Now wired up.
Synthesis Improvements
Replace playTone() with synthVoice() — ADSR, filtering, vibrato, detune
Algorithmic reverb (feedback delay network)
Stereo width via Haas effect on UR/SECRET
Global 300Hz highpass (except tear boom)
Bitcrusher for SECRET cards (WaveShaperNode)
Procedural Ambient Music
3-4 detuned oscillators with slow LFO
Contextual moods: space / calm / tense / warm
2-second crossfade on tab switch
Battle music intensification (layers as HP drops)
Separate SFX / Music volume sliders
Pack Timing Tuner
Fine-tune pack opening speed. Visualize phase breakdown, compare against industry standards, and copy values directly into game code.
Interactive Timing Slider
Total Pack Open Time
1.0s
0.3s (Instant)1.0s (Balanced)3.0s (Dramatic)
Split Animation
0.60s
60% of total
Card Delay
0.40s
40% of total
CSS Transition
0.60s
transform + opacity
Dblclick Cut
150ms
proportional scale
// Pack opening timing (1.0 seconds) topHalf transition: transform 0.60s, opacity 0.60s bottomHalf transition: transform 0.60s, opacity 0.60s setTimeout delay: 400ms dblclick cut step: 150ms
A/B Comparison Timeline
| Version | Total Time | Split Anim | Card Delay | Feel |
|---|---|---|---|---|
| Original (v1.0) | ~1.8s | 0.8s | 0.7s + 0.3s buffer | Dramatic, slow |
| Current (v1.11) | ~1.0s | 0.6s | 0.5s | Balanced |
| Fast | ~0.5s | 0.4s | 0.3s | Snappy, arcade |
v1.0 (1.8s)
v1.11 (1.0s)
Fast (0.5s)
Industry Comparison
0s1s2s3s4s
Slow tension, 1 card at a time
Shooting star, dramatic color reveal
Dramatic lid pop, all items at once
Fast spin per item
Cut + split + instant cards
Snappiest possible
Visual Timeline Animation
Play animation to preview feel
CUT
SPLIT ANIM
DELAY
CARDS
0.05s
0.60s
0.40s
0.05s
Phase 1: Cut/swipe (user action)
Phase 2: Pack split animation
Phase 3: Transition delay
Phase 4: Cards appear