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. 6 of 9 addressed via server-side mutations and validation.
3 FIXED — Fully server-side
3 MITIGATED — Server validation + caps
3 PENDING — Architecture change needed
| # | Issue | Status | Impact | Fix |
|---|---|---|---|---|
| 1 | Console state manipulation | MITIGATED | Full cheating | syncState caps + 10s cooldown |
| What was done: syncState now has a 10-second cooldown, caps stardust increase to +5000/call, limits battleWins to +5/call, and merges collection via Math.max (never overwrites with lower values). Console manipulation is still possible but the damage per exploit attempt is bounded. Remaining risk: Repeated calls over time still accumulate. Full fix requires server-authoritative game logic. | ||||
| 2 | Daily limits client-only | FIXED | Unlimited battles/packs | Server daily tracking |
What was done: Added server-side daily tracking: consumePack, consumeBattle, consumeRaid, consumePaidRaid, checkDaily mutations. Schema tracks freePacks, lastDailyReset, battlesToday, raidAttacksToday, paidRaidsToday per player. Server resets daily counters on first action of the day. | ||||
| 3 | Ad rewards no verification | PENDING | Free packs bypass | AdSense SSV |
| Status: Still uses client-side 30-second timer. AdSense integration is pending approval — once approved, Server-Side Verification (SSV) can be implemented. | ||||
| 4 | PvP battle client-side | MITIGATED | Fake wins | battleWins capped server-side |
What was done: Friend battles already use server-side battle:simulate mutation. Daily AI battles still run client-side, but syncState limits battleWins increase to +5 per call with 10s cooldown. Server also tracks wins via consumeBattle mutation.Remaining: Daily AI battle could be moved to server-side mutation for full fix. | ||||
| 5 | No real authentication | BY DESIGN | Impersonation | Unique visitorId (no login) |
| Decision: Deliberately keeping visitorId-based identity. No login requirement reduces friction for new players. visitorId is now verified on all 12 Convex mutations. Export save no longer exposes visitorId in shareable format. Trade with Space Gacha and Whale Gacha share the same identity. | ||||
| 6 | Gacha rates client-side | PENDING | Guaranteed SECRETs | Server pack opening |
Status: Pack opening RNG still runs in browser. Server-side consumePack deducts packs but doesn't generate cards. Full fix requires server to run RNG and return card results. | ||||
| 7 | Mutations callable by anyone | FIXED | API abuse | visitorId verification |
What was done: All 12 Convex mutations now require visitorId parameter and verify the caller matches the player record. Unauthenticated or mismatched calls are rejected. Rate limits (5s cooldown) added to trades, friends, and challenges. | ||||
| 8 | Redeem codes pattern guessable | FIXED | Infinite codes | Server code table |
What was done: Codes moved to server-side Convex table (codes.ts). No patterns in source. DONATE- prefix tracks by prefix not suffix (1 redemption per prefix per player). Admin-only addCode mutation requires admin key via environment variable. | ||||
| 9 | Import save arbitrary data | MITIGATED | Injected stats | validateSaveData() + syncState caps |
What was done: validateSaveData() caps all stats on import (stardust ≤9.9M, battleWins ≤10000, freePacks ≤100). Validates card IDs exist in ALL_CARDS. syncState applies same caps on server sync. Crafted save files can still inject within the cap limits. | ||||
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 | DONE | ~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 | DONE | ~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