Personal project
CactusPlay - Marketplace for games and in-game items

Tech stack
Services
- →Co-founding and fullstack engineering
- →Node.js scrapers for PlayStation Store and Xbox Store
- →WooCommerce storefront with custom PHP extensions
- →Differential price sync pipeline and alert system
- →Payment gateway and digital delivery integration
- →Yandex.Market integration: offer mapping, price sync and instant code delivery
- →Five custom WordPress plugins: sync engine, pricing, digital codes, social sign-in, campaigns
- →Go cover-styling service and self-hosted FreeScout support desk
Deliverables
- ✓Gaming marketplace with thousands of live SKUs across PS and Xbox
- ✓Automated daily price sync, with zero manual updates
- ✓Price-change alert system for promotional opportunity detection
- ✓CIS payment gateway integrations with digital key delivery
- ✓End-to-end price chain: PS Store, site and then Yandex.Market, no manual step
- ✓Fully attributed Yandex.Market product cards
Challenge
CIS gamers buying PlayStation and Xbox titles faced a fragmented market: official store prices varied significantly by region, gift card resellers were scattered across forums, and there was no single place to compare and buy. Co-founded CactusPlay to fill that gap, a marketplace for games and in-game items with real pricing data from official sources.
The core technical challenge: PlayStation Store and Xbox Store don't expose public APIs. Keeping thousands of SKUs priced accurately in near-real-time required building a scraping and synchronisation layer from scratch.
Discovery
Initial research mapped the full buyer journey: discover a game, compare price across regions, buy the cheapest legitimate key, redeem. The pain was at the compare and buy steps. Sellers existed but were fragmented; buyers had no trust signals. A marketplace with consistent pricing data, verified sellers, and a clean checkout could own that middle of the funnel.
Options Considered
- Manual price entry by admins: rejected. Doesn't scale; prices change daily, sometimes hourly during sales.
- Third-party price aggregation API, none existed for CIS PlayStation/Xbox at the time.
- Custom Node.js scrapers + WordPress/WooCommerce storefront: chosen. Scrapers give real data ownership; WooCommerce gives a battle-tested commerce layer without building checkout from scratch.
Decision
Node.js scrapers running on a cron schedule hit PlayStation Store and Xbox Store endpoints, parse the response, and push price/availability updates to WooCommerce via its REST API. WordPress + WooCommerce handles the storefront, cart, and payment gateway integrations. Custom PHP extensions handle seller onboarding flows that WooCommerce didn't support out of the box.

cactusplay.ru, scrollable snapshot of the live storefront
Implementation
Built reverse-engineered scrapers for both storefronts, handling session management, region switching, and anti-bot measures. Set up a differential update system: only changed prices trigger WooCommerce updates, keeping API load low. A price-change alert system notifies admins when a product drops below a threshold, enabling promotional timing decisions.
Integrated payment gateways supporting CIS payment methods. Custom PHP WooCommerce extensions handled digital delivery (key codes) and seller payout logic. Deployed on a VPS with automated deployment via Git hooks.
The system behind the storefront
The shop is one face of a larger system. A Node.js grabber walks the official PlayStation Store, and the Xbox Store on the same abstraction, pulling 20,000+ positions every hour. It iterates games, DLC and services separately, renames categories to the shop's own taxonomy, and merges store tags, so the catalogue arrives structured rather than as a flat dump.
Five custom WordPress plugins carry the rest:
- slave-api. The synchronisation engine. It owns the platform abstraction (one interface over the PlayStation and Xbox APIs), the product handlers that change visibility or retire SKUs, CLI commands for full and partial syncs, and versioned upgrade scenarios so a catalogue rule can be rolled out across a live shop without a manual pass.
- product-manager. The storefront side of pricing. It queries the PlayStation Store for live prices across currencies, picks one through a pluggable price strategy (the shipped one takes the lowest legitimate regional price), caches the result in transients so a product page never waits on an upstream call, and injects the custom fields the flow needs into the product form, cart, checkout and order.
- product-code-manager. The digital delivery half. It generates and stores product codes, resolves and activates them, and exposes a JWT-authenticated API so an order placed anywhere in the system can be fulfilled without a person in the loop. Order handlers react to creation and status changes, which is what makes a code arrive immediately after a digital purchase instead of after a manual dispatch.
- aw-auth, sign-in. It puts VK, Yandex, Steam and Discord on the WordPress and WooCommerce login forms behind one provider contract, so each new network is a client, a service and a settings screen rather than a fork of the flow. Steam is verified against OpenID 2.0 signatures, the rest through an OAuth code exchange; a returning visitor is matched to their existing account and a new one is created only when no match exists. Because a callback can arrive twice, each code is claimed in a lock table with a hit counter. The second request waits for the first and follows its redirect instead of minting a duplicate account. Steam hands over no email address, so those users land on a details form for email and phone before checkout. Login is email-only by policy, addresses must sit on a .ru domain to satisfy Russian data residency rules, and the private page cache is purged on login so nobody meets a stale signed-out page.
- mail-manager. The shop's own campaign engine, so customer mail did not depend on an outside provider. Audiences are categories, campaigns attach to categories, and the pending queue is derived by join: a recipient who already has a delivery row for a campaign is never picked again, so an interrupted run resumes exactly where it stopped. A cron tick sends a fixed batch with a pause between messages, keeping the shop inside the SMTP rate limit instead of firing a burst that gets the domain flagged. Sending starts disabled after activation and an interceptor logs messages instead of delivering them, so a copy of the production database cannot email real customers; the admin table reports pending, sent and failed per campaign. Open and click columns and a tracking endpoint are scaffolded, delivery is the part that shipped.
Yandex.Market: one price chain, end to end
The marketplace integration closes the loop. Offers are mapped to Yandex.Market's schema through a dedicated mapper layer, with per-store configuration, and a price service keeps them current. The chain runs without a human at any step: a price changes in the official PlayStation Store, the grabber picks it up, the site updates and then the Yandex.Market offer updates. Codes are shipped fast enough that a digital purchase on the marketplace is fulfilled in the same session, and the product cards carry every attribute Yandex.Market accepts rather than the minimum required to publish.
Cover styling service, built, not shipped
A separate Go service composed marketplace-ready covers: original art, a blurred bleed to fill the required aspect, a shop-branded header and edition badges. It was finished and produced the result below, but the integration into the catalogue pipeline was never completed. The covers went out unstyled.

Support desk
Customer support runs on a self-hosted FreeScout at support.cactusplay.ru, taking web chat and Telegram into one inbox, with the customer's recent orders pulled in beside the conversation so an agent answers without switching systems.

Outcome
The grabber sustains 20,000+ positions an hour, and price changes reach both the shop and the Yandex.Market listing without anyone touching them. The platform handled real transactions from launch, and the scraping infrastructure survived multiple PlayStation and Xbox Store front-end redesigns through targeted selector updates.
Open for contract collaboration
I am available for contract-based collaboration. If you have an interesting project idea, schedule a call via Calendly.
Schedule a 30-min call