Skip to content

Shiny Tracking

Hails edited this page Jul 15, 2026 · 7 revisions

Shiny Tracking

My Collection at /shinies is a personal checklist for logged-in users: record every shiny you have caught, in which form, with which costume, and from which event. The page shows what you own and what is still missing.

My Collection (/shinies)

Log in and open the Collection page to track your own shinies. Three tabs split the view:

  • All Shinies: the full dex with your caught entries highlighted
  • Caught: only what you own, with catch dates shown as "time ago", inline editing, and a remove button
  • Missing: everything you have not caught in any form yet

Regional forms (Alolan, Galarian, Hisuian, Paldean) whose shiny is released in GO appear as their own cards, sorted right after their base species: Growlithe and Hisuian Growlithe are separate checklist items with independent caught state, counts, and sprites. Searching a region word ("hisuian") filters to those cards. The unique counter counts species and region pairs, so both Growlithes count separately.

Alternate battle formes are tracked the same one-card-per-form way: the Therian formes of Tornadus, Thundurus, and Landorus, the Attack, Defense, and Speed formes of Deoxys, the Origin formes of Giratina, Dialga, and Palkia, and Sky Shaymin each get their own card and caught state alongside their default forme.

Vivillon patterns, Unown letters, and Scatterbug carry-through

Two species that come in many cosmetic forms are tracked form by form, the same way regional forms are:

  • Vivillon has a card for all 20 wing patterns: Meadow, Polar, Tundra, Continental, Garden, Elegant, Icy Snow, Modern, Marine, Archipelago, High Plains, Sandstorm, River, Monsoon, Savanna, Sun, Ocean, and Jungle, plus the two event only patterns Fancy and Poke Ball. Each pattern is ticked, counted, and searched on its own, shows its own artwork on the checklist and on public profiles, and hovering a card names the real world region that pattern is collected from (Elegant is Japan, Garden is the UK and Ireland, and so on).
  • Unown has a card for every form it comes in: A to Z, plus the exclamation mark (!) and the question mark (?), 28 in all. Each letter is ticked, counted, and searched independently, with its own artwork, so a shiny Unown F no longer looks the same as a shiny Unown G.

Both keep a plain card for a catch whose pattern or letter you never noted. If you remember it later, set it on the entry from the Caught tab and the entry moves to the correct card.

Scatterbug and Spewpa can be tagged with a Vivillon pattern the same way, but they stay a single card each: they look identical whichever region they came from, so tagging one does not split it out or change any count. The tag is remembered instead, and when you press Evolve the pattern rides up the line: an Elegant Scatterbug becomes an Elegant Spewpa becomes an Elegant Vivillon, with no need to re-pick the pattern.

Recording a catch

Click a Pokemon and fill in the add modal:

  • Form: Normal, Shadow, or Purified
  • Region: fixed by the card you clicked; adding from the Hisuian Growlithe card records a Hisuian entry. Region is stored separately from form, so a Shadow Alolan catch is representable.
  • Method: wild, egg, raid, research, evolution, photobomb, trade, or GO Tour
  • Costume: an autocomplete picker whose suggestions are now data driven per species, it offers only the costumes that this Pokemon actually received in GO (checked against real game assets) rather than a short generic list. Leave blank for an uncostumed catch.
  • Event: freeform text with autocomplete covering major events (GO Fest 2018 through 2026, GO Tour Kanto, GO Tour Johto, GO Tour Hoenn, GO Tour Sinnoh, GO Tour Unova, Community Day, and others). Leave blank when not event-specific.
  • Catch date: the day you actually caught it, which you can set both when adding and later when editing. It is validated to be no earlier than Pokemon GO's launch (2016-07-06) and no later than tomorrow. Leave it blank and the entry keeps whatever date it already has. Before this was settable the site quietly recorded the day you added the entry, which is not the same thing if you log a catch a few days later.

True duplicates are allowed, you can record the same species, form, costume, and event more than once if you caught multiples.

Grid view

The shiny grid shows one card per species you own. When you own more than one entry for a species, a blue xN badge appears in the top-left corner of that card (for example, x3 if you have three records for Pikachu). Costumed entries show the actual costumed sprite, Party Hat Pikachu displays with its hat, Nightcap Snorlax displays with the cap, rather than the plain base shiny sprite. Costumed sprites now render for every eligible Pokemon rather than a handful, including Party Hat Venusaur, the GO Fest Sun Crown and Moon Crown Eevee and Pikachu, and a large batch of the real Pikachu costumes; a few sprites that pointed at the wrong art were corrected in the process.

Caught list

Entries in the Caught tab show a subtitle line below the Pokemon name when any extra fields are set. The subtitle joins the set fields with a middle dot (form · costume · event), so an entry might read "Shadow · Party Hat · GO Fest 2025". The form badge is omitted when it is Normal; costume and event are omitted when blank.

Each entry can be edited inline: click the edit button to update the form (dropdown), region (dropdown, shown only for species that have shiny regional forms in GO), method (dropdown), costume (autocomplete dropdown filtered to costumes available for that species, Pikachu shows its regional caps and Lucha Libre; Snorlax shows Night Cap; etc.), or event (autocomplete dropdown). The region selector exists precisely so entries logged before regional support can be retroactively marked with their form; saving swaps the row to the correct regional sprite and moves the caught badge to the right card. A remove button deletes the entry entirely. A counter in the tab header tracks how many unique species and region pairs you have collected.

The Evolve button is region aware: a Galarian Meowth offers Perrserker (not Persian), an Alolan Rattata evolves into an Alolan Raticate, Galarian Slowpoke offers Galarian Slowbro or Slowking, and species whose base form cannot evolve in GO (base Qwilfish, base Linoone, base Mr. Mime) offer nothing until their entry is marked with the right region.

Collection on trainer profile pages

The 9 most recent shiny catches appear on a trainer's public profile page, below the achievements section. Each entry shows the shiny sprite (costumed or regional where applicable), the Pokemon name (prefixed with its region, e.g. "Hisuian Growlithe"), and any region, Shadow, or Purified badge. This section is visible to anyone who can view the profile.

Tap a shiny to open its detail modal. Clicking any entry (yours or another trainer's) opens it larger alongside everything that trainer recorded about it: the costume, the event, how it was caught (with an icon), the catch date, a Shadow or Purified badge, and an evolved indicator. Only the fields the trainer actually filled in are shown. On your own profile the modal adds an Edit link to /shinies?entry=<id> that jumps straight to that exact entry in your collection and highlights it, so you do not have to hunt through a long list to fix a typo.

To opt out, open Settings and enable Hide shiny collection under Privacy. When enabled, the shiny section does not appear on your public profile and the public collection endpoint returns an empty result.

The full collection is still accessible separately. When another trainer's profile is public and they have not hidden their collection, their complete shiny collection is shown on their trainer profile page, reached by clicking their card in the Trainer Directory.

Under the hood

Shiny availability (which Pokemon are released shiny and through which methods) comes from PoGoAPI (pogoapi.net/api/v1/shiny_pokemon.json), refreshed server side and delivered with the rest of the cached game data; see Data-Sources. Because PoGoAPI has stopped tracking some newer shiny releases, a locally curated supplement (internal/pogodata/fallback/shinies_supplement.json) is merged over the upstream data in memory; supplement entries always win and survive every refresh. The collection page is ts/shinies.ts.

Which regional forms exist per species (and their PokeAPI variant sprite ids) is a hand maintained table kept in two mirrored files: ts/shared/regionalForms.ts for the browser and internal/handlers/regional.go for the server. A unit test checks the species names against the shiny data so the mirrors cannot drift apart silently. Region aware evolution targets live in REGIONAL_EVOLUTION_NEXT in ts/shared/evolutions.ts. The per-form pattern tables sit in the same regionalForms.ts file: VIVILLON_PATTERNS (the 20 wing patterns, each carrying the real world geo region shown on hover) and UNOWN_LETTERS (A to Z plus ! and ?). Scatterbug and Spewpa entries are flagged patternOnly, so their pattern is stored and carried through evolution but never spawns a card of its own. All of these tags, the four geographic regions, the battle formes, the Vivillon pattern codes, and the Unown letter codes, share the single region column (VARCHAR(16)) on user_shinies.

Costumes come from the app's own mined-asset pipeline in internal/costumes, built from two files. catalog.json is generated (by make costumes, never hand-edited) from the mined PokeMiners asset tree: it holds every costume code that actually has shiny art and exactly which species can wear it, because the presence of a pm{dex}.{code}.s.icon.png file is the authoritative test for both. labels.json is the curated companion that maps the human labels trainers see and type onto those codes. Both files are go:embeded by the server and imported directly by ts/shared/costumes.ts, so the browser and server resolve from one source and cannot drift, there is no generated Go mirror to keep in sync. Resolution requires a catalog hit, so a label whose art does not exist upstream is simply inert, which is why a costume can be recorded before its release without any "pending" bookkeeping, and the picker only ever offers a species the costumes that really exist for it. Admins name new costumes from the Admin Guide Costumes tab; those names land in a server-side overlay merged over labels.json, so a costume named since the last deploy shows up immediately. Sprites are never hotlinked: each is pulled from the mined-asset CDN once, cached, and re-served immutably from GET /api/costume-sprite/{file}.

Non-costume sprites and audio come from PokeAPI: grid sprites use the PokeAPI GitHub sprite repository directly (the shiny variant lives under sprites/pokemon/shiny/), while costumed sprites are served by the app's own proxy above rather than PokeAPI. The modal's normal vs shiny pair, the Pokedex flavor text and genus, and the cry audio URL are fetched on demand from the PokeAPI REST API by ts/shared/pokedex.ts, which caches every response in memory for the session. Sprites that 404 simply hide themselves.

Your collection is stored per account through the /api/shinies endpoints: GET lists your entries, POST adds one (pokemon_id, form, region, method, costume, event_tag, and an optional caught_at date), PUT /api/shinies/{id} updates it (including caught_at), and DELETE /api/shinies/{id} removes it. The region value is one of the four geographic forms (alolan, galarian, hisuian, paldean), one of the battle formes that reuse the same field (therian, origin, attack, defense, speed, sky), a Vivillon pattern or Unown letter code for those species, or empty for the original form; any unrecognized value is rejected. The evolve endpoint also accepts the target region so regional and pattern lines stay consistent. All mutating calls carry the CSRF token from the page's meta tag.

The mobile companion app reaches the same collection through a versioned mirror under /api/mobile/v1/shinies (list, add, edit, delete, and evolve), Bearer-token authenticated instead of cookie plus CSRF. Every entry it receives carries a server-resolved sprite_url (costume, regional, or base), and a /shinies/reference endpoint feeds the app's region and method pickers, so a new region or method added on the site appears in the app without an update. See API-Reference for the mobile endpoint table.

Duplicate records are permitted, there is no unique constraint that would block recording the same (user, pokemon, form, costume, event) combination twice. Each row gets its own ID and can be edited or removed independently.

A separate public endpoint, GET /api/shinies/of/{username}, returns another user's collection when their profile is public and their collection is not hidden. It returns an empty array otherwise. The response includes sprite_url (shiny variant, resolved server side) in addition to the standard fields. See API-Reference for the full endpoint list and Accounts-and-Roles for how accounts work.

Clone this wiki locally