← All projects

Android · React Native

Soreni

A full-featured Guild Wars 2 companion app for Android — legendary crafting planner, world boss timers, live inventory tracking, and a full account dashboard, all powered by the official GW2 API.

React Native TypeScript TanStack Query Zustand GW2 API v2 Notifee

Overview

Guild Wars 2 has a lot of systems — legendary crafting, world bosses, trading post, WvW, PvP, fractals, collections — and the official companion tools don't surface them well on mobile. I wanted a single app that gave me real-time access to all of it without switching between tabs or relying on slow browser tools.

Soreni grew into a fully-featured companion covering ten areas of the game. The core challenge was bridging the GW2 API's many endpoints — each with different schemas, rate limits, and authentication scopes — into a coherent, fast mobile experience. Two releases shipped; currently maintained and in active use.

Not affiliated with ArenaNet or NCSoft.

Role

Solo — design, development, API integration

Platform

Android (React Native bare CLI)

Status

Live — v1.1.0 released

Key features

Legendary crafting planner

Full BFS recipe tree resolving all nested components across every legendary. Shopping list grouped by source (craft / forge / timegated / buy / special), with live inventory cross-check across characters, bank, and material storage. Timegate tracker shows days required per gated material and a Wizard's Vault panel lets you subtract already-owned components.

Customisable dashboard

10 toggleable widgets including account wealth (wallet + bank + materials priced at live TP rates), reset countdown, world boss status, daily checklist with Wizard's Vault integration, mastery progress, character roster, and a 7-day gold trend sparkline built from daily wallet snapshots.

World boss & meta event timers

Live countdowns for every world boss and meta event, grouped by expansion from Core through Janthir. Per-stage progress bars for multi-phase events, waypoint codes on tap, and local push notifications configurable per event with 5–30 minute lead times.

Full account coverage

Characters with per-character inventory, equipment, and map completion. Live Trading Post — delivery box, buy/sell orders, transaction history, watchlist, and gem exchange. WvW match scores, objectives, and abilities planner. PvP standings, match history. Fractals, strikes, guild log, collections.

Screenshots

Soreni home dashboard

Dashboard

Soreni legendary crafting

Legendary planner

Soreni world boss timers

World boss timers

Soreni collections

Collections

Tech stack

Framework

  • React Native 0.76 (bare CLI)
  • TypeScript 5.3
  • React Navigation v6

Data & State

  • TanStack Query v5
  • Zustand + AsyncStorage
  • Axios · GW2 API v2

Features & Tooling

  • Notifee (local notifications)
  • ESLint + Prettier
  • Git + GitHub · Gradle

Challenges

  • The legendary crafting recipe tree is deeply nested — some legendaries require materials that are themselves crafted from other crafted components. Implementing BFS traversal to resolve the full tree and collapse duplicates into a single shopping list was the most algorithmically complex part of the project.
  • The GW2 API spans 10+ distinct endpoints with different schemas, auth scopes, and rate limits. Building a clean fetching layer with TanStack Query — where each screen composes multiple queries without duplicating network calls — required careful cache key design and coordination of loading states.
  • Scheduling local push notifications for world boss spawns across all timezones, and keeping them accurate after the app is closed, required understanding Android's background execution constraints and how Notifee handles trigger notifications.

What I learned

  • React Native is much closer to native development than I expected — understanding Android-specific behaviour (background limits, Gradle builds, APK signing) was as important as the JavaScript layer.
  • TanStack Query's stale-while-revalidate model works extremely well for game data that changes on a predictable cadence. Pairing it with Zustand for persistent user settings gave a clean separation between server state and client state.
  • Building a domain with as many interconnected systems as GW2 forced me to think more carefully about module boundaries. The src/ structure — splitting api/, hooks/, store/, and screens/ — paid off early when features started sharing data across tabs.

What I'd improve next

iOS support is the biggest gap — the React Native codebase is already largely cross-platform, but signing and distribution require an Apple developer account. On the feature side, I'd like to add a build comparison tool across characters and server-side caching for the Trading Post price history, which currently re-fetches on every load. Test coverage is also thin for the timer logic; that's the area most likely to produce silent bugs.