Compare commits

..

238 Commits

Author SHA1 Message Date
Josh Creek 669d0cdeaa Merge pull request #99 from jcreek/perf/pokedex-grid-transport
Perf/pokedex grid transport
2026-09-15 18:39:28 +01:00
Josh Creek 7373bf005d docs(performance): record the pokédex investigation and hosting evaluation
Keeps the measurements, the implementation notes and the hosting comparison next
to the code they justify.
2026-09-15 17:49:04 +01:00
Josh Creek 3ee69f0d04 refactor(api): drop the redundant setSession in export-integrations
requireAuth has already resolved the session on locals.supabase.
2026-09-15 17:49:04 +01:00
Josh Creek 0c1de9a93d fix(a11y): trap focus inside the pokédex modal
Tab moved to the page behind the open dialog and closing it left focus nowhere.
Keep Tab within the dialog, move focus to the close button on open, restore it
to the trigger on close, and give the dialog an accessible name.
2026-09-15 17:49:04 +01:00
Josh Creek 03b74089a0 feat(offline): open entry details from the saved snapshot
Opening an entry while offline needed a request that could not be made. Read it
from the snapshot claimed by the signed-in account instead, re-checking
ownership after the read so a sign-in mid-read cannot surface another account's
data, and let controls marked data-offline-action stay usable in read-only mode.
2026-09-15 17:48:57 +01:00
Josh Creek 56b676b04a perf(startup): defer offline sync and backup status until the grid is interactive
Both fired during hydration and competed with rendering the grid, and the layout
waited for the user store before it could show a signed-in shell even though the
server already knew who the user was.

Seed the user from the layout data, and queue the offline sync and backup
refresh behind the grid's interactive mark; an explicit refresh, a reconnect or
an edit still runs straight away. Backup refreshes now share one in-flight
request per generation, and a change of account cancels the pending startup
refresh and clears the stale status.
2026-09-15 17:48:49 +01:00
Josh Creek 19abb34693 fix(sync): keep queued catch-record writes from crossing an account change
The queue held whole records and flushed whatever was in it, so edits made
before a sign-out could be written against the account that signed in next.

Queue patches and merge them per key, so two edits to one entry combine instead
of one replacing the other; drop everything when the owning account is no longer
the current one; and stop scheduling flushes while offline, where they could only
fail and back off.
2026-09-15 17:48:34 +01:00
Josh Creek 54eaa6d776 fix(catch-records): stop bulk upserts clobbering fields a toggle never touched
Toggling one checkbox sent the whole record, so a stale copy of the other fields
could overwrite newer values. Send only the fields that changed, group rows by
the columns they carry, and upsert each group with defaultToNull: false so
omitted columns keep their stored value. Results are returned in the caller's
order rather than whatever order the groups came back in.
2026-09-15 17:48:34 +01:00
Josh Creek 2042e5a65a test(performance): add a local pokédex benchmark and run it in CI
Measures the pokédex load against a local Supabase with a generated fixture, and
compares runs so a regression shows up as a number rather than a hunch. Wired
into test:ci and given its own job so the artifacts survive a failure.
2026-09-15 17:47:21 +01:00
Josh Creek 2766e5ea67 build(cloudflare): add a Cloudflare preview build target
DEPLOY_TARGET now selects the adapter; Netlify stays the default and NODE_ADAPTER
keeps working. Cloudflare compresses in transit, so the Worker build aliases
$lib/server/compression to a pass-through that leaves the streaming body alone.

CI builds and dry-run deploys this target. That is compilation and packaging
coverage only, not a production compatibility gate: native sharp still blocks the
share-preview route in the Worker runtime.
2026-09-15 17:47:14 +01:00
Josh Creek b2b750115f perf(sprites): serve grid-sized thumbnails from an immutable URL space
Every grid cell downloaded the full detail sprite. Generate a smaller
/sprites-grid/v1/ set at build time and let the grid ask for those first,
falling back through the existing detail URLs when a thumbnail is missing so
detail resolution is unchanged. The new prefix is versioned, so it can be cached
forever, and the service worker recognises it alongside the other sprite roots.

The placeholder is now an empty box rather than a spinner: a thousand spinners
cost layout work and announced nothing useful.
2026-09-15 17:46:49 +01:00
Josh Creek 26b9e3b8c1 perf(pokedex): fetch dex scopes with the pokédex row
findById made a second round trip for scopes on every page load; embed
pokedex_dex_scopes in the select instead.
2026-09-15 17:46:23 +01:00
Josh Creek acaf760b36 perf(pokedex): send the box grid as packed rows with the page
The server load fetched a full combined-data page at a 9999 item page size,
carrying detail text and ownership fields the grid never renders, and the client
re-fetched the same payload after hydration.

Load a trimmed grid row instead and pack it as positional tuples so field names
are not repeated for every one of a thousand-plus entries. Entry detail is
fetched on demand from the new per-entry endpoint when a cell is opened, and the
grid marks itself interactive so other page-start work can queue behind it.
2026-09-15 17:46:19 +01:00
Josh Creek 4c268ba15c feat(pokedex): add opt-in Server-Timing for the pokédex load
POKEDEX_PERFORMANCE=true reports auth, ownership, scopes, entries and catches
with fixed labels only: no IDs, query strings, cookies or entry content ever
reach the header. Auth is measured in the hook, where the session is actually
resolved, and handed to the page load through locals.
2026-09-15 17:46:07 +01:00
Josh Creek 31fd959350 Merge pull request #98 from jcreek/perf/page-load-and-lighthouse
perf: fix slow page loads and gate performance in CI
2026-09-14 21:41:59 +01:00
Josh Creek 7603116369 ci(lighthouse): stop lhci reading the form factor as a CLI flag
lhci treats every LHCI_* environment variable as a command-line option, so
LHCI_PRESET=mobile reached `lhci assert` as an invalid --preset and failed
both jobs after the audits had run. Use LIGHTHOUSE_FORM_FACTOR instead.

Also upload the reports: upload-artifact v4+ skips dot-directories such as
.lighthouseci unless include-hidden-files is set.
2026-09-14 21:19:20 +01:00
Josh Creek 5d41462d35 test(bdd): find the account menu by its new accessible name
The avatar's alt text changed from "usericon" to "Account menu" as part of
the accessibility fixes, so the sign-out and offline-guide steps now look it
up by that name.
2026-09-14 20:59:38 +01:00
Josh Creek ff29095c47 perf: fix slow page loads and gate performance in CI
- Ship one hashed Tailwind stylesheet instead of two (one render-blocking)
- Compress responses in-app (brotli/gzip, streaming-safe) and precompress
  the node build so local and CI measurements match production
- Validate the Supabase session once per request
- Render the homepage immediately and stream public stats
- Stream a Pokedex's entries with the page instead of fetching after
  hydration, running the rows and count queries in parallel
- Shrink the avatar and offline placeholder images, fix layout shift,
  contrast, link names and missing meta descriptions
- Add Lighthouse CI (mobile + desktop) with score and metric budgets,
  bundle-size budgets in the build tests, and signed-in speed scenarios
2026-09-14 20:53:53 +01:00
Josh Creek 556f120f16 Merge pull request #97 from jcreek/fix/backup-reconnect-and-offline-guide
fix(backup): pause revoked backups and tell users to reconnect
2026-09-14 20:16:58 +01:00
Josh Creek 7786d46078 fix(backup): don't let a stale export pause a reconnected backup
- An export now pauses a revoked integration only if its row is
  unchanged since the export read it, using the trigger-maintained
  updatedAt column as the row version. If the user reconnected in the
  meantime, the stale failure no longer disables the fresh credentials
  or asks the user to reconnect again. updateExportStatus now reports
  whether a row was written.
- The backup status store ignores a response overtaken by a newer
  refresh, or by the status being flagged, cleared or set directly, so
  a slow response can't overwrite newer state.
- Unit tests cover the whole integration repository, the guarded pause
  and stale status responses. Coverage thresholds are raised to the
  new baseline.
2026-09-14 19:03:29 +01:00
Josh Creek fb95b43b30 fix(backup): pause revoked backups and tell users to reconnect
Google answers a revoked or expired refresh token with invalid_grant.
Every save then retried the dead token, and reconnecting never cleared
the old error, so it kept showing on Backup Settings afterwards.

- The Google Drive and Dropbox OAuth callbacks clear lastError when a
  provider is reconnected.
- An invalid_grant, or a missing refresh token, now pauses the
  integration with a readable "reconnect" message instead of retrying
  it on every catch update. Other failures still retry as before.
- A banner on every page and an alert on the Pokédex page point to
  Backup Settings, which shows a "Reconnect needed" badge. The Pokédex
  page re-checks backup status after each export, because saving a
  catch record also exports on the server and may pause a provider
  first.
- Offline sync status and the "Save all artwork" link move from every
  page to a new /offline-guide page, linked from the user menu and the
  home and welcome pages. Only the offline read-only banner stays
  sitewide.
- Unit tests cover every export path and the backup status store. BDD
  covers revocation and reconnecting for both providers, and the
  offline guide. The mock provider can now reject token refreshes, and
  mock control calls fail loudly if a stale mock is reused. Coverage
  thresholds are raised to the new baseline.
2026-09-14 18:46:09 +01:00
Josh Creek 5c25a763c0 Merge pull request #96 from jcreek/fix/offline-data-usage
Fix/offline data usage
2026-09-14 17:10:35 +01:00
Josh Creek 9ddca18f54 revert(sprites): keep the original 512px sprites
The resize to 192px isn't worthwhile now that sprites are only downloaded
when viewed or saved on request, and then kept forever. Restore the
original files and the script's no-resize default, drop the detail view
size cap, and regenerate the sprite manifest with the original sizes.
2026-09-14 16:53:31 +01:00
Josh Creek 030571fd14 perf(offline): stop re-downloading artwork and the offline snapshot
- Sprites are cached as they are viewed instead of bulk-downloaded after
  every sign-in, in one shared cache that is never pruned and survives
  sign-out and account changes, since sprites never change.
- A "Save all artwork for offline" link saves every remaining sprite on
  request, shows the remaining size, and is hidden once all are saved.
- Page loads reuse an offline snapshot under 15 minutes old; edits,
  retries and a new sign-in still sync immediately.
- An expired session no longer wipes offline data; only the Sign Out
  button does.
2026-09-14 16:19:22 +01:00
Josh Creek 721c44dcd0 perf(sprites): ship 192px sprites and a manifest of every sprite
Sprites were shipped at 512x512 but render at 44-64px in the box grid.
Resizing to 192px halves each file (median 15.5KB -> 7.6KB); a full dex
of artwork drops from 16.6MB to 7.6MB.

The sprite build now also writes static/sprites-small/manifest.json,
listing every sprite (all forms, shiny and female variants) with its
size, so the offline worker can save the complete set and report what
is missing. A unit test keeps it in step with the files on disk.
2026-09-14 16:19:22 +01:00
Josh Creek b7d2db4959 fix(auth): stop stale session cookies signing users out on refresh
@supabase/ssr 0.1.0 never removed the old unchunked session cookie once a
refreshed session grew past one cookie, and always read that stale copy
first. Every load then retried an already-used refresh token, which the
hosted auth server rejects, signing the user out.

Upgrade @supabase/ssr to 0.12 (and supabase-js to match) and move to the
getAll/setAll cookie API, which clears stale chunks when writing.
2026-09-14 16:19:20 +01:00
Josh Creek f382176804 Merge pull request #95 from jcreek/feat/shareable-pokedex 2026-09-14 15:29:59 +01:00
Josh Creek 3f8daea8d2 ci: serve local sprites in the bdd job
Stops each BDD run downloading every Living Dex sprite from GitHub.
2026-09-14 15:22:05 +01:00
Josh Creek c3a3d43883 fix(offline): cache sprite artwork once instead of on every sync
Each sync created a new artwork cache and re-fetched every sprite with no-cors. Opaque responses are padded to several MB each for storage quota, so a Living Dex grew to tens of GB, syncs never finished, and the offline copy could fail to save.

Artwork now lives in one cache per user that is topped up with only missing sprites, fetched with CORS so they count at their real size, with a per-fetch timeout. The offline copy is committed before any artwork, legacy per-sync artwork caches are removed first, and sprites shown online are cached on first load. Also requests persistent storage.
2026-09-14 15:22:05 +01:00
Josh Creek f2d8451c34 chore(deps): match Node engine range to sharp
sharp is now a runtime dependency and requires ^18.17.0 || ^20.3.0 || >=21.0.0.
2026-09-14 14:47:27 +01:00
Josh Creek ca7f9c0e48 test(pokedex): cover shared dex loading and preview badges
Adds loadSharedPokedex unit tests and a share preview case for every badge, restoring the branch coverage gate. Gives the offline sync BDD poll 30s so a full Living Dex snapshot can finish caching on CI.
2026-09-14 14:47:27 +01:00
Josh Creek 27274171fe test(pokedex): cover shared dex privacy 2026-09-14 14:25:22 +01:00
Josh Creek 7240376e00 feat(pokedex): add shareable read-only dex links 2026-09-14 14:25:09 +01:00
Josh Creek 951c9b2878 Merge pull request #94 from jcreek/chore/test-suite-hardening
Chore/test suite hardening
2026-09-14 13:50:01 +01:00
Josh Creek 2c5fc0d459 ci: run workflow jobs on Node 24 2026-09-14 13:46:58 +01:00
Josh Creek 4b2f076e50 ci: upgrade GitHub Actions Node runtimes 2026-09-14 13:46:21 +01:00
Josh Creek 3ea194f87c fix: harden review findings and Netlify install 2026-09-14 12:56:09 +01:00
Josh Creek 86f1c21e4d fix: remediate branch review findings 2026-09-14 11:47:58 +01:00
Josh Creek 4af33709a3 test: make the suite's assertions falsifiable and its state isolated
Several assertions could not fail:

- "the catch update remains saved" was `caught.isChecked() || notes.includes(...)`
  shared by two scenarios, so either half satisfied both. Split into two steps
  that each assert the outcome their own scenario is about.
- The token-refresh check read a global counter with `> 0` and asserted an upload
  had happened `some(...)`, both already satisfied by the preceding scenario. It
  now asserts exactly one refresh, ordered before the upload.
- The box step ignored its box argument and asserted on the first N entries on
  the page; it now scopes to that box and checks its full contents.
- The filter step asserted on whichever entry was first after filtering; it now
  records the caught entry beforehand and names it, and checks the filter did not
  exclude everything.
- The empty-state precondition asserted emptiness instead of establishing it,
  which a fresh user satisfies for free.
- Offline coverage was `caches.keys().length > 0`. It now checks the precache
  contract: one workbox cache holding the shell and a revisioned web manifest,
  with _app/immutable assets cached without a revision query. The scenario that
  claimed to test a trailing slash did not; it is replaced with real offline
  client-side navigation.

The mock provider kept recorded requests, its refresh counter and the
fail-uploads switch in one process-wide object that only one step reset, so
scenario order was load-bearing and the failing-upload scenario poisoned
everything after it. An auto fixture now resets it per scenario, and the mock no
longer records its own control-plane calls. That reset is why the suite stays on
a single worker, which is now documented.

Coverage was gated at 90% per file over an allowlist of exactly the five files
that had tests, so new code was invisible to it permanently. It now measures all
of src/lib with global thresholds at the measured baseline, and no longer runs
the unit tests twice.

Also: a global teardown removes the users each run creates, the Supabase wrapper
distinguishes a stopped stack from a broken CLI call and detects an unseeded
database, the sign-in rate limit is raised above what one serial run needs, and
the integration suite no longer falls back to a hard-coded anon key that would
mask a misconfigured run.

The password-reset scenarios are renamed to what they actually cover: following a
real recovery link bounces to /signin, because the browser client persists no
cookies and so cannot keep the session it parses out of the URL. The helper for
the real flow is left in place and the gap is documented.
2026-09-13 17:38:42 +01:00
Josh Creek 3a2c18bbeb fix: repair defects surfaced by gating CI on lint and typecheck
`npm run check` reported 15 errors and `npm run lint` 20, all pre-existing, so
neither gate could pass. Fixing them turned up three real bugs:

- SignOut destructured `{ error }` off `.then(() => {})`, which resolves to
  undefined, so every sign-out threw a TypeError - after the signed-out event had
  already been emitted. Sign-out also left the user on the protected page they
  were on, still showing its content; it now returns them to the home page and
  re-runs the server loads.

- SignUp passed `redirectTo`, which is not a signUp option and was silently
  ignored, so the confirmation link has always used Supabase's configured site
  URL. Documented rather than changed, since pointing it elsewhere needs an
  absolute allow-listed URL.

- The Pokédex page tracked totalRecordsCreated but never passed it to the box
  view, so the "Processed N entries so far" progress message never rendered.

The rest is typing and dead code: cookie callback parameters in hooks.server.ts
and +layout.ts, the untyped supabase props, a query-builder type that made
PostgREST rows untyped downstream, an unused session destructure, and
`while (true)` paging loops rewritten as `for (;;)`.
2026-09-13 17:38:42 +01:00
Josh Creek 92d6460765 fix(export): restrict provider endpoint overrides to loopback test servers
The endpoint overrides are read through `$env/dynamic/private`, so they are
evaluated per request in production, not baked in at build time. That made a
single injected environment variable enough to redirect the authorization-code
and refresh-token POSTs - which carry the OAuth client secret and the user's
refresh token - to an arbitrary host, and to redirect the user's authorize hop
to an arbitrary URL.

Overrides are now ignored unless ALLOW_PROVIDER_ENDPOINT_OVERRIDES is exactly
"true" and the value is a loopback URL. `npm run test:bdd` sets the flag;
nothing else should. resolveProviderEndpoints is pure so the refusals are unit
tested, including near-miss hosts such as http://127.0.0.1.example.

Also drops the unused `pokedex` parameter from buildCsv rather than silencing it
with `void`, and the dead hasGigantamaxed field from its fallback record.
2026-09-13 17:38:42 +01:00
Josh Creek f9b7bbdf0a fix(pwa): honour the adapter flag and precache an offline entry point
Three defects that together meant `npm run test:build` could not pass in any of
its four variants:

- svelte.config.js constructed adapter-netlify inline and never used the
  `adapter` export from adapter.mjs, so NODE_ADAPTER=true still produced a flat
  build/ directory while the build test expects the node adapter's build/client
  layout. adapter.mjs now returns netlify (the deployment target) or node, and
  svelte.config.js consumes it.

- No route is prerendered, so workbox's glob found no HTML document and a
  generateSW build precached nothing navigable: the app had no offline support
  in that mode at all. Adds the root entry and a navigation fallback, matching
  what prompt-sw.ts already did by hand for injectManifest builds.

- The build scripts used by the tests skipped the tailwind step that `build`
  runs, so static/output.css was never generated on a clean checkout and the
  app under test had no stylesheet.

The offline entry point assertion now also accepts the unquoted object key that
prompt-sw.ts's own precache call survives minification as.
2026-09-13 17:38:42 +01:00
Josh Creek de39dc78ea test: replace ad-hoc tests with a layered suite and CI workflow
Splits testing into five layers so a failure points at the responsible one:

- tests/unit    isolated utility, repository and service tests
- tests/data    validates the tracked Pokémon, game, region and dex files
- tests/integration  schema, views, constraints, RLS and repositories
- tests/bdd     executable Gherkin for user-visible behaviour
- tests/build   service worker and manifest artifacts per build variant

Replaces the two Playwright specs in client-test/ and the two Vitest files in
test/. Adds a GitHub Actions workflow running the layers as separate jobs, a
mock OAuth provider server so the Drive and Dropbox scenarios never touch real
accounts, and a wrapper that reads the local Supabase keys from
`supabase status` rather than hard-coding them.

Extracts the pure formatting helpers out of PokedexExportService so they can be
unit tested, and makes the provider endpoints configurable so the mock server
can stand in for Google and Dropbox.
2026-09-13 17:38:41 +01:00
Josh Creek 08c5e3271c style: format tracked files and ignore generated data exports
`prettier --check .` failed on 22 files, so gating CI on `npm run lint` was
never going to pass. These changes are whitespace only.

Adds the two remaining generated data exports to .prettierignore so this class
of churn cannot recur, along with machine-local settings files.
2026-09-13 17:38:35 +01:00
Josh Creek 676490b800 style(data): reformat generated Pokédex data files
These two files are generated exports that prettier was not ignoring, so
`prettier --check .` failed on them. Reformatting is isolated here because the
diff is ~124k lines and would otherwise bury real changes.

The only semantic change in this commit is the apostrophe in Farfetch'd and
Sirfetch'd: U+0027 -> U+2019, matching the spelling the rest of the data
already used. Everything else is whitespace.
2026-09-13 17:34:35 +01:00
Josh Creek bfd74a2985 Merge pull request #93 from jcreek/codex/fix-default-form-filtering
Fix default-form filtering and complete dex mappings
2026-09-13 12:56:17 +01:00
Josh Creek 7c32813cf2 fix: preserve default forms and complete dex mappings 2026-09-13 12:50:42 +01:00
Josh Creek c5a47439d9 Merge pull request #92 from jcreek/91-forms-only-work-when-all-games-is-selected
91 forms only work when all games is selected
2026-06-16 15:49:07 +01:00
Josh Creek 19e4d7b727 refactor(#91): Address PR comments 2026-06-16 15:46:12 +01:00
Josh Creek 8255fb4c67 fix(#91): correct form game coverage and fix canonical sort order 2026-06-16 15:28:07 +01:00
Josh Creek 069f7f41fa fix(data): add missing female form entries to pokemon_origin_games
Female Sneasel was absent from all 5 Gen 2 games (Gold, Silver, Crystal,
HeartGold, SoulSilver) and Female Indeedee was absent from Sword, despite
their base forms being present. Both found during QA of the form dex
game-scope feature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 14:00:10 +01:00
Josh Creek 955cba1aaa fix(forms): supplement game-scoped dex entries with alternate forms
When a Pokédex has a game scope set and isFormDex=true, alternate forms
were not appearing because game_pokedex_entries only contains base-form
Pokémon. This adds fetchFormsForGame() to pull supplemental form entries
from pokedex_entries filtered by gamesToCatchIn, then merges and sorts
them using the base form's regional dex number so ordering is preserved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 13:16:29 +01:00
Josh Creek c5a503f5b5 fix(my-pokedexes): preserve original desktop header and stack actions on mobile 2026-02-06 13:15:24 +00:00
Josh Creek 71cfbce7e3 feat(*): Add evolution data and notes 2026-01-25 17:19:51 +00:00
Josh Creek 4f2fe5e333 build(*): Update supabase version 2026-01-25 09:09:49 +00:00
Josh Creek 575aafbc28 build(*): Enable running db migrations in build 2026-01-24 17:59:28 +00:00
Josh Creek 6ecaa0f30f Merge pull request #90 from jcreek/89-add-backup-functionality-for-google-drive-and-dropbox
feat(#89): Add backup functionality for google drive and dropbox
2026-01-24 17:44:00 +00:00
Josh Creek e55d511141 refactor(#89): Address PR comments 2026-01-24 17:40:59 +00:00
Josh Creek 86e8d6f5e6 refactor(#89): Address PR comments 2026-01-24 17:26:55 +00:00
Josh Creek 8141bd624b refactor(#89): Address PR comments 2026-01-24 17:18:57 +00:00
Josh Creek ab82f75dc6 feat(#89): Add backup functionality for google drive and dropbox 2026-01-24 13:32:10 +00:00
Josh Creek 3f5c14a8bc data(*): Add evolution info 2026-01-24 10:09:23 +00:00
Josh Creek 8775e05ba7 Merge pull request #86 from jcreek/84-improve-performance-and-efficiency-of-service-worker
feat(#84): Improve performance and efficiency of service worker
2026-01-22 21:27:51 +00:00
Josh Creek c5c63ab8ef feat(#84): Improve performance and efficiency of service worker 2026-01-22 21:21:57 +00:00
Josh Creek dd9ced17d8 Merge pull request #83 from jcreek/82-improve-data-seeding-performance
82 improve data seeding performance
2026-01-19 12:26:44 +00:00
Josh Creek 606fcbb201 chore(*): Remove commented out code 2026-01-19 12:20:31 +00:00
Josh Creek dfa0569119 feat(*): Make pokemon sprite bigger 2026-01-19 12:18:25 +00:00
Josh Creek e819929898 feat(#84): Improve data seeding performance 2026-01-19 12:17:40 +00:00
Josh Creek decf6ca1fb Merge pull request #81 from jcreek/data/dexes
Improve data seeding and structure
2026-01-18 13:45:24 +00:00
Josh Creek 6d54c93700 fix(*): Address PR comment 2026-01-18 13:38:22 +00:00
Josh Creek 07ce2b3421 fix(*): Address PR comment 2026-01-18 13:25:54 +00:00
Josh Creek 0c25bba236 fix(*): Address PR comment 2026-01-18 13:18:55 +00:00
Josh Creek eba34158fe data(*): Fix remaining sprites 2026-01-18 13:14:18 +00:00
Josh Creek 71df0de3df fix(*): Address PR comments 2026-01-18 10:41:12 +00:00
Josh Creek 46351c9af0 data(*): Add final data changes 2026-01-17 23:30:40 +00:00
Josh Creek 479b3ae7a0 data(*): Add native game dexes 2026-01-17 22:42:12 +00:00
Josh Creek a26f38bca1 data(*): Improve ordering of forms 2026-01-17 21:08:21 +00:00
Josh Creek f302721119 data(*): Add working regenerated data structure 2026-01-17 20:39:55 +00:00
Josh Creek a604fe2526 data(*): Further corrections 2026-01-17 16:42:02 +00:00
Josh Creek 88d8344706 data(*): Remove old spreadsheet 2026-01-17 15:43:47 +00:00
Josh Creek bfef2fd4a7 data(*): Make corrections to csv 2026-01-17 15:42:01 +00:00
Josh Creek ee73c01afe feat(*): Change how data is set up 2026-01-16 21:11:21 +00:00
Josh Creek 3f0003b006 chore(*): Update csv 2026-01-15 19:34:28 +00:00
Josh Creek 874a6bd78e data(*): Add reference data 2026-01-11 21:20:27 +00:00
Josh Creek d40d4aa4e1 data(*): Add sinnoh data 2026-01-11 21:20:06 +00:00
Josh Creek bde3d71e6c data(*): Add hoenn data 2026-01-11 20:50:24 +00:00
Josh Creek a871da5d59 Merge pull request #80 from jcreek/48-add-dark-mode-toggle
48 add dark mode toggle
2026-01-10 21:53:08 +00:00
Josh Creek d437c05770 refactor(#48): Address PR comment 2026-01-10 21:50:56 +00:00
Josh Creek 9d14b2d2f1 refactor(#48): Address PR comments 2026-01-10 21:44:19 +00:00
Josh Creek ad8c8a847d feat(#48): Make box cells square on mobile 2026-01-10 21:35:14 +00:00
Josh Creek 23e8382bd1 chore(*): Remove console log 2026-01-10 21:15:21 +00:00
Josh Creek d50417ffef feat(#48): Add dark mode 2026-01-10 21:12:25 +00:00
Josh Creek ad66b874e9 Merge pull request #79 from jcreek/54-make-it-clear-what-the-profile-search-is-in-the-nav-bar-ie-not-a-pokemon-search
feat(#54): Remove search icon and improve sign in page
2026-01-10 20:37:23 +00:00
Josh Creek a7d878fffd fix(#54): Address PR comments 2026-01-10 20:32:34 +00:00
Josh Creek c10b526b3e feat(#54): Remove search icon and improve sign in page 2026-01-10 20:23:13 +00:00
Josh Creek 1614ff52be Merge pull request #78 from jcreek/64-update-styling-on-the-about-page
feat(#64): Improve the about page
2026-01-10 19:29:49 +00:00
Josh Creek 75f7161b7a fix(#64): Address PR feedback 2026-01-10 19:25:29 +00:00
Josh Creek 5657c2b2ab fix(#64): Address PR comments 2026-01-10 18:45:57 +00:00
Josh Creek f17b350e4e fix(#64): Address PR comments 2026-01-10 18:27:01 +00:00
Josh Creek 68cc2a0712 fix(#64): Address PR comments 2026-01-10 17:06:52 +00:00
Josh Creek 7c68d121ce fix(#64): Address PR comments 2026-01-10 16:27:23 +00:00
Josh Creek adc96baa90 feat(#64): Improve the about page 2026-01-10 15:27:00 +00:00
Josh Creek 463ab88545 Merge pull request #77 from jcreek/fix/migration-issue
fix(*): Fix migration issue
2026-01-10 13:31:05 +00:00
Josh Creek fb8dbdda3e fix(*): Fix migration issue 2026-01-10 13:26:09 +00:00
Josh Creek ee03ffc11f Merge pull request #76 from jcreek/56-improve-responsiveness-of-updates-to-the-dex
refactor(#56): Improve how the dex updating is handled and the error …
2026-01-10 13:02:41 +00:00
Josh Creek 070604fb89 fix(#56): Address PR comments 2026-01-10 12:47:27 +00:00
Josh Creek b30be24fd5 feat(#56): Address PR comments 2026-01-10 12:37:43 +00:00
Josh Creek b1b6e63b6f refactor(#56): Improve how the dex updating is handled and the error messaging around it 2026-01-10 12:07:05 +00:00
Josh Creek 845cc1c739 Merge pull request #75 from jcreek/59-add-outlines-to-cells-in-box-view-even-if-there-is-no-pokemon-to-show-there
feat(#59): Add outlines to empty box cells
2026-01-10 10:32:25 +00:00
Josh Creek 84c6de6b62 feat(#59): Add outlines to empty box cells 2026-01-10 10:23:21 +00:00
Josh Creek fc09b5f2f1 Merge pull request #74 from jcreek/57-replace-many-buttons-with-toggles
feat(#57): Replace 'mark box as' buttons with dropdown for better ux
2026-01-10 10:15:01 +00:00
Josh Creek 789321ce03 feat(#57): Improve accessibility of dropdown 2026-01-10 10:12:22 +00:00
Josh Creek cb0773b03e feat(#57): Replace 'mark box as' buttons with dropdown for better ux 2026-01-09 22:21:01 +00:00
Josh Creek cbece0ec22 Merge pull request #73 from jcreek/60-add-useful-stats-to-the-my-dex-page-that-change-based-on-the-selected-filters
feat(#60): Add stats and filters to pokedex page
2026-01-09 21:55:30 +00:00
Josh Creek 8fa394f102 feat(#60): Add stats and filters to pokedex page 2026-01-09 21:51:21 +00:00
Josh Creek bd3f266a4a Merge pull request #72 from jcreek/63-suggestions-for-box-view-improvements
feat(#63): Improve the box view
2026-01-09 20:55:33 +00:00
Josh Creek 35ee92df0c fix(#63): Enforce mutually exclusive catch states 2026-01-09 20:51:33 +00:00
Josh Creek ca6831d10a feat(#63): Improve the box view 2026-01-09 20:34:57 +00:00
Josh Creek 2c2ab8b99c Merge pull request #71 from jcreek/67-add-support-for-multiple-pokédex-challenge-types-per-user-new
67 add support for multiple pokedex challenge types per user new
2026-01-09 18:50:12 +00:00
Josh Creek 07af29e6e6 chore(#67): Address pr comments 2026-01-09 18:45:47 +00:00
Josh Creek 28bb39d558 feat(*): Add improvements to the UX and the data seeding 2026-01-07 20:13:07 +00:00
Josh Creek b9a49686c1 refactor(*): Implement CSV-based seeding, dynamic box placement, and enforce forms from pokedex configuration 2026-01-05 09:44:15 +00:00
Josh Creek 19a571e315 feat(#67): Add support for multiple pokedexes per user 2026-01-04 22:06:36 +00:00
Josh Creek 578df57a45 Merge pull request #70 from jcreek/69-cant-create-account-clicking-sign-up-does-nothing
69 Set up Docker and Supabase workflow with seeding migrations
2026-01-02 21:18:53 +00:00
Josh Creek 6ec40056e1 feat(#69): Remove redundant env var 2026-01-02 21:11:25 +00:00
Josh Creek d18b231ac6 fix(#69): Downgrade SvelteKit to 2.5.3 and enable generateSW mode to resolve build failures 2026-01-02 20:57:28 +00:00
Josh Creek 0e2d7f7792 fix(#69): Use service role key for seeding 2026-01-02 20:35:38 +00:00
Josh Creek 78c3230b92 fix(#69): Set correct urls for local supabase 2026-01-02 20:17:33 +00:00
Josh Creek 2f5c0d68be feat(#69): Improve seeding process 2026-01-02 20:17:13 +00:00
Josh Creek 073ba77dee docs(#69): Clarify getting started docs 2026-01-02 20:16:42 +00:00
Josh Creek 31eb551c8a Merge pull request #68 from jcreek/chore/migrate-from-mongodb
feat(*): Migrate from MongoDB to unified Supabase PostgreSQL architecture
2025-07-26 23:20:39 +01:00
Josh Creek 5e0e45494f chore(*): Fix remaining PR comments 2025-07-26 23:18:36 +01:00
Josh Creek 852c6c3f34 feat(*): Complete MongoDB to Supabase migration cleanup 2025-07-26 23:13:11 +01:00
Josh Creek c063e9d2cd fix(*): map all updatable fields in PokedexEntryRepository.update method 2025-07-26 22:49:21 +01:00
Josh Creek c2c8fd1fb4 refactor(*): Remove unused userId parameter from countCombinedData method 2025-07-26 22:39:25 +01:00
Josh Creek 5b7fe52dc4 Merge branch 'chore/migrate-from-mongodb' of https://github.com/jcreek/LivingDexTracker into chore/migrate-from-mongodb 2025-07-26 22:35:04 +01:00
Josh Creek 31e8a0d686 build(*): Add netlify support 2025-07-26 22:26:45 +01:00
Josh Creek 120f936eb7 Update src/lib/repositories/CatchRecordRepository.ts 2025-07-26 22:22:03 +01:00
Josh Creek 8459ecf3fe fix(*): Resolve protocol mismatch 2025-07-26 22:13:01 +01:00
Josh Creek dd31a8d040 Update supabase/config.toml 2025-07-26 22:09:35 +01:00
Josh Creek ebfe2413f0 fix(*): Pass userId prop to PokedexEntryCatchRecord component 2025-07-26 22:07:06 +01:00
Josh Creek 389f73d164 chore(*): Clean up migration artifacts and optimize data repository queries 2025-07-26 21:50:54 +01:00
Josh Creek fa38fa69ca refactor(*):Address PR comments 2025-07-26 19:42:04 +01:00
Josh Creek bc9ce84615 feat(*): Migrate from MongoDB to unified Supabase PostgreSQL architecture 2025-07-26 18:50:05 +01:00
Josh Creek 70f7bbdffc Merge pull request #65 from jcreek/55-fix-bug-where-one-users-catch-records-are-used-for-everyone
fix(#55): implement user data isolation to prevent cross-user data access
2025-07-26 16:48:26 +01:00
Josh Creek 3aa716b941 fix(#55): implement user data isolation to prevent cross-user data access
- Add server-side authentication validation for all protected API endpoints
- Create auth utility with requireAuth() function for session validation
- Update CombinedDataRepository to filter data by authenticated user ID
- Add findByUserId() method to CatchRecordRepository for user-specific queries
- Replace client-side userId parameters with server-side session extraction
- Use MongoDB aggregation with $lookup and $expr for secure user filtering
- Return 401 errors for unauthenticated requests
- Fix critical security vulnerability where users could see others' catch records

Fixes: User data isolation bug where one user's catch records were used for everyone
Security: Prevents unauthorized access to other users' Pokemon tracking data
2025-07-26 16:34:19 +01:00
Josh Creek a4269259f9 feat(#46): Move change view button to sidebar 2024-07-17 22:15:43 +01:00
Josh Creek bfde0c49f5 feat(#46): Merge boxes view into my dex page 2024-07-17 22:07:07 +01:00
Josh Creek 02a2160f08 feat(#46): Componentise the list view 2024-07-17 21:24:06 +01:00
Josh Creek 4d9d5e74d7 feat(#46): Componentise the boxes view 2024-07-17 21:11:58 +01:00
Josh Creek e4ca722de7 feat(#46): Add checkmark for pokemon in home 2024-07-17 18:52:09 +01:00
Josh Creek ad13540879 feat(#46): Add buttons to update catch records for entire boxes 2024-07-17 18:01:59 +01:00
Josh Creek 6c9ec0239c feat(#46): Add tooltip to my boxes page 2024-07-17 18:01:10 +01:00
Josh Creek 1c207455fb feat(#46): Add Tooltip component 2024-07-17 17:50:03 +01:00
Josh Creek c071dca26a build(#46): Use .env var for image base path 2024-07-17 17:49:19 +01:00
Josh Creek 8b32bca11c feat(*): Enable sprites on mydex page 2024-07-16 22:00:06 +01:00
Josh Creek 5bdf88b735 feat(#22): Add shiny toggle 2024-07-16 21:47:57 +01:00
Josh Creek f62b18b0ee feat(#22): Add sprites 2024-07-16 21:43:41 +01:00
Josh Creek 5468515d4b feat(#46): Add better box styling 2024-07-16 21:39:22 +01:00
Josh Creek 6f4847f126 feat(#46): Add color to alternate columns 2024-07-15 21:02:44 +01:00
Josh Creek 2ad7e219a2 feat(#46): Add boxes page 2024-07-15 20:49:36 +01:00
Josh Creek d3b7e7f5a9 feat(*): Enable sliding filters bar for smaller viewports 2024-07-15 19:18:37 +01:00
Josh Creek 7b5a948910 feat(*): Add sign in route with redirection to mydex 2024-07-14 21:37:24 +01:00
Josh Creek bc25ab0e38 fix(*): Fix bug returning 0 for document counts when filtering by region and game 2024-07-14 21:03:57 +01:00
Josh Creek 0285725b6d feat(*): Add ability to filter by game and region 2024-07-14 20:51:05 +01:00
Josh Creek 62c03f41eb feat(*): Add region-game mappings 2024-07-14 19:45:06 +01:00
Josh Creek 80fb0d7414 feat(*): Add clarifying copy 2024-07-14 18:42:59 +01:00
Josh Creek 1c9a9bcf8f feat(*): Add prompts for contributing 2024-07-14 18:29:43 +01:00
Josh Creek ed1ea42e50 feat(*): Enable automatic saving 2024-07-14 18:09:47 +01:00
Josh Creek 0edc7f0974 feat(*): Enable filtering to either do a forms dex or a regular dex 2024-07-14 17:47:16 +01:00
Josh Creek 7467a4425f feat(*): Update pokedex entry data structure and re-add error handling 2024-07-14 16:16:18 +01:00
Josh Creek 90f6bd6e75 feat(*): Improve layout 2024-07-14 12:08:29 +01:00
Josh Creek 953524cecf feat(*): Make mydex use combined data 2024-07-14 12:07:15 +01:00
Josh Creek 308753d2e5 feat(*): Add pokedex theming 2024-07-14 11:41:17 +01:00
Josh Creek 2cf3a03f8f feat(*): Add pagination to my dex 2024-07-12 21:33:02 +01:00
Josh Creek 8d86d93bc0 feat(*): Hide notes if there are none 2024-07-12 14:38:30 +01:00
Josh Creek 0e3be214ba feat(*): Add ability to toggle origins and forms 2024-07-12 14:35:25 +01:00
Josh Creek 704e618f84 chore(*): Remove console log 2024-07-12 14:28:21 +01:00
Josh Creek 64c5f375ac fix(*): Add error handling for no pokedex entries 2024-07-12 14:25:22 +01:00
Josh Creek e512c63e0b chore(*): Re-enable service worker 2024-07-12 14:21:04 +01:00
Josh Creek e7f1930eff feat(*): Add support for catch records to My Dex page 2024-07-12 14:19:44 +01:00
Josh Creek 0e8af37309 chore(*): Disable service worker 2024-07-12 14:17:03 +01:00
Josh Creek 6aac4c5985 feat(*): Update seeding logic to handle new fields and record the last modified date 2024-07-12 14:16:30 +01:00
Josh Creek 212f674b44 feat(*): Add tsv parser to enable easily loading pokedex data 2024-07-12 14:14:24 +01:00
Amber Marie 7deb4632bc Merge pull request #40 from jcreek/35-style-the-about-page
Design About Page
2024-05-15 15:12:02 +01:00
Amber M 70f85be9b9 Replace break with paragraph 2024-05-15 15:10:26 +01:00
Amber M 24792331db Add TODO 2024-05-15 15:05:37 +01:00
Amber M d59d970812 Delete duplicate code 2024-05-15 15:04:30 +01:00
Amber M ff43601b1a Design About Page 2024-05-15 14:49:30 +01:00
Josh Creek 425d66a9ce fix(*): Disable some functionality of service worker 2024-05-13 19:32:24 +01:00
Josh Creek 4761bdf31a Merge pull request #37 from jcreek/36-style-the-landing-page
feat(#36): Style the landing page
2024-04-28 16:10:20 +01:00
Josh Creek 6a4c6d81b2 feat(#36): Style the landing page 2024-04-28 16:08:28 +01:00
Josh Creek cdab9b4ab5 Merge pull request #34 from jcreek/29-create-an-about-page
Make about page
2024-04-28 14:07:29 +01:00
Amber M c17dc6090c Remove id 2024-04-28 14:05:31 +01:00
Amber M 3a72225e16 Make about page 2024-04-28 13:59:31 +01:00
Josh Creek 046b956882 Merge pull request #33 from jcreek/32-link-profile-page-to-actual-profile
feat(#32): Link profile page to actual profile
2024-04-28 13:43:23 +01:00
Josh Creek 43c7dab2ee feat(#32): Link profile page to actual profile 2024-04-28 13:39:33 +01:00
Josh Creek 5bbe8b9abe Merge pull request #31 from jcreek/27-create-a-profile-page
Make profile page
2024-04-28 13:25:28 +01:00
Amber M ec6aa1a5cf Remove Join us 2024-04-28 13:22:52 +01:00
Amber M e6b4cc84bc Make profile page 2024-04-28 13:15:48 +01:00
Josh Creek 548e918fd9 Merge pull request #28 from jcreek/feat/workbox
chore(*): Add workbox service worker
2024-04-14 16:06:49 +01:00
Josh Creek 5285d5d84d chore(*): Add workbox service worker 2024-04-14 16:03:01 +01:00
Josh Creek 63de9c82a4 feat(*): Make the user object available and reactive in any component 2024-04-10 22:03:37 +01:00
Josh Creek 6213c773c3 feat(*): Add custom pokeball theme 2024-04-10 21:50:43 +01:00
Josh Creek 99ed144a34 feat(*): Move account functionality into header 2024-04-10 21:50:04 +01:00
Josh Creek 6db13fff6d Merge branch 'master' of https://github.com/jcreek/LivingDexTracker 2024-04-10 20:55:45 +01:00
Josh Creek 499ee75c6a docs(*): Add local development instructions and hosting details 2024-04-10 20:55:43 +01:00
Amber Marie 580dd83c69 Merge pull request #26 from jcreek/2-create-a-header-to-show-on-all-pages
Create a header
2024-04-09 21:27:45 +01:00
Amber M d80da3e415 Create a header 2024-04-09 21:24:47 +01:00
Josh Creek 2a4a4a1414 Merge pull request #24 from jcreek/20-make-this-a-pwa-so-it-can-cache-the-sprites-and-be-used-offline-updating-the-db-when-its-back-online
feat(#20): Make the site a PWA
2024-04-08 21:53:33 +01:00
Josh Creek f6bf7a7a85 feat(#20): Make the site a PWA 2024-04-08 21:47:42 +01:00
Josh Creek 0204870f5a Merge pull request #23 from jcreek/19-add-a-basic-my-dex-page
feat(#19): Add a basic My Dex page
2024-04-08 21:23:23 +01:00
Josh Creek 454259d9e7 feat(#19): Add a basic My Dex page 2024-04-08 21:09:34 +01:00
Josh Creek 23385d2c44 Merge pull request #18 from jcreek/5-set-up-repositories-for-database-access
feat(#5): Add ability to seed pokedex entry data
2024-04-08 20:12:59 +01:00
Josh Creek 44fa581ecd feat(#5): Add ability to seed pokedex entry data 2024-04-08 20:08:53 +01:00
Amber M b15889d6af Merge pull request #17 from jcreek/16-fix-issue-where-daisyui-styles-dont-apply-to-components
fix(#16): Ensure DaisyUI styles apply to components
2024-04-07 19:31:08 +01:00
Josh Creek 16a067cd5d fix(#16): Ensure DaisyUI styles apply to components
It turns out that tailwind excludes styles it hasn't found in use, so it needs to be explicitly told where to find the component files. This also therefore fixes the styles in the SignUp component.
2024-04-07 19:19:08 +01:00
Amber M 335f5c9046 Merge pull request #15 from jcreek/3-create-a-footer-to-show-on-all-pages
Add Footer to layout
2024-04-07 16:05:46 +01:00
Amber M d66ac7ae4b Add Footer to layout 2024-04-07 16:01:57 +01:00
Josh Creek 22b9af0bbe chore(*): Add build steps 2024-04-07 15:44:17 +01:00
Josh Creek db5ae6fdc1 Merge pull request #14 from jcreek/13-add-daisyui
build(#13): Add DaisyUI
2024-04-07 15:29:54 +01:00
Josh Creek 4ff4243125 fix(#13): Add hacky workaround for component styling 2024-04-07 15:28:15 +01:00
Josh Creek 59ff274a44 build(#13): Add DaisyUI 2024-04-07 15:12:59 +01:00
Josh Creek 88b4d92905 docs(*): Add dependencies section to readme 2024-04-07 13:03:00 +01:00
Josh Creek e699298a82 Merge pull request #12 from jcreek/11-add-sprites
11 add sprites
2024-04-07 10:54:47 +01:00
Josh Creek ee191aa7cf feat(#11): Add sprite component 2024-04-07 10:50:59 +01:00
Josh Creek d708de8b2c feat(#11): Add sprites 2024-04-07 10:48:15 +01:00
Josh Creek 93db09d669 Merge pull request #10 from jcreek/9-add-supabase-auth
9 add supabase auth
2024-04-06 21:51:51 +01:00
Josh Creek 1475e06b8e feat(#9): Add sign in and sign out 2024-04-06 21:46:04 +01:00
Josh Creek 496cdb6666 feat(#9): Add sign up 2024-04-06 21:10:37 +01:00
Josh Creek d55dcb066d Merge pull request #8 from jcreek/6-set-up-classes-for-database-access
feat(#6): Add classes for database
2024-04-06 17:58:43 +01:00
Josh Creek 7518579047 feat(#6): Add classes for database 2024-04-06 17:56:56 +01:00
Josh Creek aaf60f9634 Merge pull request #7 from jcreek/4-add-a-database-connection
chore(#4): Add a database connection to mongodb
2024-04-06 17:09:58 +01:00
Josh Creek 4ca2ddb181 build(*): Attempt to get env vars working 2024-04-06 17:06:00 +01:00
Josh Creek 49e39c2742 chore(#4): Add a database connection to mongodb 2024-04-06 15:04:53 +01:00
Josh Creek 26c552e994 build(*): Add netlify support 2024-03-09 21:32:50 +00:00
Josh Creek e3420d6e02 chore(*): Add base sveltekit files 2024-03-09 21:28:07 +00:00
Josh Creek bf087bd77b Initial commit 2024-03-09 21:09:47 +00:00
3524 changed files with 62032 additions and 40409 deletions
+22 -3
View File
@@ -1,3 +1,22 @@
MONGO_URL=""
PUBLIC_SUPABASE_URL=""
PUBLIC_SUPABASE_ANON_KEY=""
PUBLIC_SUPABASE_URL="your-supabase-project-url"
PUBLIC_SUPABASE_ANON_KEY="your-supabase-anon-key"
SUPABASE_SERVICE_ROLE_KEY="your-supabase-service-role-key"
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER="false"
GOOGLE_OAUTH_CLIENT_ID="your-google-client-id"
GOOGLE_OAUTH_CLIENT_SECRET="your-google-client-secret"
DROPBOX_OAUTH_CLIENT_ID="your-dropbox-client-id"
DROPBOX_OAUTH_CLIENT_SECRET="your-dropbox-client-secret"
# Endpoint overrides for deterministic local provider tests. They are ignored unless
# ALLOW_PROVIDER_ENDPOINT_OVERRIDES is exactly "true", the local BDD stack variables are present,
# and every URL is loopback. These endpoints receive OAuth secrets, so never set this in a deployed
# environment. `npm run test:bdd` supplies the complete test context.
ALLOW_PROVIDER_ENDPOINT_OVERRIDES=""
GOOGLE_OAUTH_AUTHORIZE_URL=""
GOOGLE_OAUTH_TOKEN_URL=""
GOOGLE_DRIVE_API_URL=""
GOOGLE_DRIVE_UPLOAD_URL=""
DROPBOX_OAUTH_AUTHORIZE_URL=""
DROPBOX_OAUTH_TOKEN_URL=""
DROPBOX_UPLOAD_URL=""
+2
View File
@@ -11,3 +11,5 @@ node_modules
pnpm-lock.yaml
package-lock.json
yarn.lock
.wrangler/
+187
View File
@@ -0,0 +1,187 @@
name: Tests
on:
pull_request:
push:
branches: [master]
concurrency:
group: tests-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# `$env/static/public` is resolved at build time, so every variable imported from it must be
# present for `vite build` and `svelte-check` to succeed on a clean checkout. These are the
# local-stack defaults already published in .env.local.example - never real credentials.
env:
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER: 'false'
PUBLIC_SUPABASE_URL: http://127.0.0.1:54321
PUBLIC_SUPABASE_ANON_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
jobs:
quality:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
- name: Check committed whitespace
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
git diff --check "${{ github.event.pull_request.base.sha }}...HEAD"
else
git diff --check "HEAD^...HEAD"
fi
- run: npm run check
- run: npm run lint
- run: npm run test:fast
- name: Verify tests leave the checkout clean
run: test -z "$(git status --porcelain --untracked-files=all)"
- uses: actions/upload-artifact@v6
if: always()
with:
name: coverage
path: coverage/
if-no-files-found: ignore
integration:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
# `supabase start` applies migrations and seeds; no separate reset is needed.
- run: npx supabase start
- run: npm run test:integration
- if: always()
run: npx supabase stop
build:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run test:build
lighthouse:
runs-on: ubuntu-latest
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
form-factor: [mobile, desktop]
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
# The homepage streams public stats from the database, so audit against a real stack.
- run: npx supabase start
- run: npm run test:lighthouse
# Not LHCI_*: lhci reads any LHCI_ variable as a CLI flag (LHCI_PRESET became `--preset`).
env:
LIGHTHOUSE_FORM_FACTOR: ${{ matrix.form-factor }}
- uses: actions/upload-artifact@v6
if: always()
with:
name: lighthouse-${{ matrix.form-factor }}
path: .lighthouseci/
# upload-artifact v4+ skips dot-directories unless told otherwise.
include-hidden-files: true
if-no-files-found: ignore
- if: always()
run: npx supabase stop
bdd:
runs-on: ubuntu-latest
timeout-minutes: 30
# Serve the committed sprites so offline sync doesn't download every Living Dex sprite from
# GitHub on each run.
env:
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER: 'true'
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
- uses: actions/cache@v5
with:
path: ~/.cache/ms-playwright
key: playwright-chromium-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
playwright-chromium-${{ runner.os }}-
- run: npx playwright install --with-deps chromium
- run: npx supabase start
- run: npm run test:bdd
- uses: actions/upload-artifact@v6
if: failure()
with:
name: playwright-failures
path: |
test-results/
playwright-report/
if-no-files-found: ignore
- if: always()
run: npx supabase stop
pokedex-performance:
runs-on: ubuntu-latest
timeout-minutes: 20
env:
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER: 'true'
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx supabase start
- run: npm run test:performance
- uses: actions/upload-artifact@v6
if: always()
with:
name: pokedex-performance
path: test-results/performance/
if-no-files-found: ignore
- if: always()
run: npx supabase stop
cloudflare-preview-build:
runs-on: ubuntu-latest
timeout-minutes: 15
env:
WRANGLER_SEND_METRICS: 'false'
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run build:cloudflare
- run: npm run check:cloudflare
# This is compilation/package coverage, not a production compatibility gate.
# Native sharp still blocks the share-preview route in the Worker runtime.
+8
View File
@@ -9,4 +9,12 @@ node_modules
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
/static/output.css
.lighthouseci
.netlify
.features-gen
coverage
playwright-report
test-results
/static/sprites-grid/
.wrangler/
+15
View File
@@ -2,3 +2,18 @@
pnpm-lock.yaml
package-lock.json
yarn.lock
# Generated data exports. Nobody hand-edits these, and reformatting them buries real data
# changes under tens of thousands of lines of churn.
src/lib/helpers/pokeapi-pokemon.json
static/sprites/pokemon.json
src/lib/helpers/pokedex.json
src/lib/helpers/sprites.json
static/sprites-small/manifest.json
# Machine-local editor and tool settings.
**/*.local.json
# Generated grid artwork and local Worker runtime output.
static/sprites-grid/
.wrangler/
+110 -10
View File
@@ -4,18 +4,24 @@ A web app to track completion of a living Pokédex.
## Developing
Cloned the repository you can install the dependencies with `npm install`, and start a development server:
1. Clone the repository
2. Install the dependencies with `npm install`
3. Ensure that Docker is running
4. An example `.env` file is provided in the repository. You will need to copy `.env.example` to `.env` and fill in the values with your own credentials. For local development with Supabase running in Docker, you can use the following values:
```bash
npm run dev
- The `PUBLIC_SUPABASE_URL` will be `"http://127.0.0.1:54321"`
- The `PUBLIC_SUPABASE_ANON_KEY` will be the 'Publishable' authentication key displayed when you run Supabase in the terminal
- The `SUPABASE_SERVICE_ROLE_KEY` will be the 'Secret' authentication key displayed when you run Supabase in the terminal
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
5. Start local Supabase and a development server with `npm run dev:supabase`
6. The Pokédex data is automatically seeded via database migrations when Supabase starts
7. Create an account using the sign-up form and access the email it sends in [MailPit](http://127.0.0.1:54324/) to verify your email address.
N.B. All local emails are captured by MailPit when running Supabase in Docker.
8. You can now use [the app](http://localhost:5173/).
An example `.env` file is provided in the repository. You will need to copy `.env.example` to `.env` and fill in the values with your own credentials.
## Reference Data Updates
Once you have done this, you can seed the Pokédex data using the /api/seed endpoint. You will need to comment out the `return;` at the beginning of the `GET` function in `/src/routes/api/seed.ts` to do this. Make sure you remember to uncomment it afterwards.
The seed data lives in `supabase/migrations/20260118001000_seed_reference_data.sql`. Update that migration directly when new data is added. You can access a local copy of [Supabase](http://localhost:54323/) to check it.
## Building
@@ -25,16 +31,110 @@ To create a production version:
npm run build
```
## Testing
The test suite is split by responsibility so a failure points to the correct layer:
- `tests/unit` contains fast, isolated tests for utilities, repositories, and services.
- `tests/data` validates the tracked Pokémon, game, region, dex, and sprite reference files.
- `tests/integration` checks the migrated Supabase schema, views, constraints, RLS, and repositories.
- `tests/bdd/features` is the executable Gherkin specification for user-visible behaviour. Step
definitions and browser fixtures live beside it under `tests/bdd`.
- `tests/build` verifies generated service-worker and manifest artifacts after each supported build,
and fails if the gzipped JS or CSS every page loads grows past its budget.
- `lighthouserc.cjs` audits the public pages with Lighthouse CI (`npm run test:lighthouse`, which
builds and serves the Node output). PRs fail if Performance, Accessibility, Best Practices or SEO
drops below 90, or if LCP, TBT, CLS, script, stylesheet or total transfer size exceeds its budget.
CI runs it with both the mobile and desktop profiles (`LIGHTHOUSE_FORM_FACTOR=desktop`).
- `tests/bdd/features/performance.feature` holds time budgets for signed-in pages Lighthouse can't
reach: opening a Pokédex and switching between it and the Pokédex list.
The budgets sit just above current measurements so regressions fail the PR. If a change genuinely
needs more, raise the budget in the same PR so the cost is reviewed.
Run the offline suites while developing. `test:fast` includes the coverage run, so there is no need
to run both:
```bash
npm run test:fast
```
Coverage is measured across all of `src/lib` (excluding type-only models and the browser-only
store/action modules) with global thresholds set to the current baseline, so new untested code lowers
the number instead of being invisible to the gate. Ratchet the thresholds in `vitest.config.mts` up as
coverage grows, never down.
Database and BDD tests require Docker and the local Supabase stack. The wrappers read the local keys
from `supabase status` at run time, so no keys are hard-coded in the test files; the local stack's
well-known demo keys do appear in `.env.local.example`, and no real credentials are committed:
```bash
npm run supabase:start
npm run supabase:reset
npm run test:integration
npm run test:bdd
```
`npm test` runs the complete CI-equivalent sequence and fails with setup instructions when Supabase is
not available. Individual layers are available as `test:unit`, `test:data`, `test:integration`,
`test:build`, and `test:bdd`.
Gherkin describes outcomes in domain language. Keep selectors, API calls, test-user provisioning, and
provider mocks in step definitions or support fixtures. `@product-review` marks a rule that should be
reviewed with product stakeholders, but does not skip it. Missing or ambiguous steps fail generation.
Google Drive and Dropbox scenarios use a local provider server (`scripts/mock-provider-server.mjs`)
and never contact real provider accounts. The endpoint overrides that point at it are refused unless
`ALLOW_PROVIDER_ENDPOINT_OVERRIDES=true`, the local test-stack/service-role variables are present,
and the override is a loopback URL. These endpoints receive the OAuth client secret and refresh
token, so they must not be redirectable in a deployed environment. `npm run test:bdd` supplies the
complete test context.
The mock's recorded requests, refresh counter and fail-uploads switch are reset before every scenario
by an auto fixture in `tests/bdd/fixtures.ts`. That reset is also why the suite runs with a single
worker: the mock is one shared process, so parallel scenarios would reset each other's state. A global
teardown deletes the users each run creates, so repeated local runs do not need a database reset.
Chromium is the only configured browser project. Playwright traces and screenshots are retained on
failure under `test-results`.
Password-reset scenarios follow recovery links generated by the local Supabase stack and verify both
the rejected old password and accepted replacement password. The application waits for Supabase to
confirm the recovery session before enabling the replacement form.
After sign-in, the application automatically stores a versioned, per-user read-only copy of every
Pokédex and its referenced artwork. Offline navigation opens a static viewer; all mutation and
authentication controls remain unavailable until connectivity returns. A successful sign-out removes
the user-specific snapshot and artwork caches from the device.
The current National Dex maximum is deliberately asserted as 1025. When adding a new generation,
update that expectation together with Pokémon data, the corresponding game/dex files, database seed,
and sprites. Data tests print the exact conflicting identities or broken references.
You can preview the production build with `npm run preview`.
## Sprites
The app uses WebP sprites from `static/sprites-small`. During builds we generate this folder from the
full-resolution PNGs in `static/sprites`:
```bash
npm run sprites:build
```
If you want to serve sprites locally, set `PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER="true"` in `.env`.
Otherwise the app defaults to GitHub raw for `static/sprites-small`.
## Hosting
The app is hosted on [Netlify](https://www.netlify.com/) at [pokedex.jcreek.co.uk](https://pokedex.jcreek.co.uk/).
The Pokédex data is stored in a [MongoDB](https://www.mongodb.com/) database hosted on [MongoDB Cloud](https://cloud.mongodb.com/).
The Pokédex data is stored in a [Supabase](https://supabase.com/) database.
User authentication is handled by [Supabase Auth](https://supabase.com/auth).
## Dependencies
The living dex tracker's sprite collection is taken from [PokéAPI Sprites](https://github.com/PokeAPI/sprites), which is licensed under [the Creative Commons CC0 1.0 Universal license](https://github.com/PokeAPI/sprites/blob/master/LICENCE.txt).
The living dex tracker's sprite collection is derived from [PokéAPI Sprites](https://github.com/PokeAPI/sprites)
and converted to smaller WebP files in `static/sprites-small`. PokéAPI sprites are licensed under
[the Creative Commons CC0 1.0 Universal license](https://github.com/PokeAPI/sprites/blob/master/LICENCE.txt).
+3
View File
@@ -0,0 +1,3 @@
/sprites-grid/v1/*
Cache-Control: public, max-age=31536000, immutable
+10 -5
View File
@@ -1,7 +1,12 @@
import process from 'node:process'
import process from 'node:process';
import AdapterNode from '@sveltejs/adapter-node';
import AdpaterStatic from '@sveltejs/adapter-static';
import AdapterNetlify from '@sveltejs/adapter-netlify';
export const nodeAdapter = process.env.NODE_ADAPTER === 'true'
export const adapter = nodeAdapter ? AdapterNode() : AdpaterStatic()
export const nodeAdapter =
process.env.NODE_ADAPTER === 'true' || process.env.DEPLOY_TARGET === 'node';
export const cloudflareAdapter = process.env.DEPLOY_TARGET === 'cloudflare';
export const adapter = nodeAdapter
? AdapterNode({ precompress: true })
: cloudflareAdapter
? (await import('@sveltejs/adapter-cloudflare')).default()
: AdapterNetlify({ edge: false, split: false });
-39
View File
@@ -1,39 +0,0 @@
import { test, expect } from '@playwright/test';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
test('Test offline and trailing slashes', async ({ browser }) => {
// test offline + trailing slashes routes
const context = await browser.newContext();
const offlinePage = await context.newPage();
await offlinePage.goto('/');
const offlineSwURL = await offlinePage.evaluate(async () => {
const registration = await Promise.race([
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
navigator.serviceWorker.ready,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Service worker registration failed: time out')), 10000)
)
]);
// @ts-expect-error registration is of type unknown
return registration.active?.scriptURL;
});
const offlineSwName = 'sw.js';
expect(offlineSwURL).toBe(`http://localhost:4173/${offlineSwName}`);
await context.setOffline(true);
const aboutAnchor = offlinePage.getByRole('link', { name: 'About' });
expect(await aboutAnchor.getAttribute('href')).toBe('/about');
await aboutAnchor.click({ noWaitAfter: false });
const url = await offlinePage.evaluate(async () => {
await new Promise((resolve) => setTimeout(resolve, 3000));
return location.href;
});
expect(url).toBe('http://localhost:4173/about');
expect(offlinePage.locator('li[aria-current="page"] a').getByText('About')).toBeTruthy();
await offlinePage.reload({ waitUntil: 'load' });
expect(offlinePage.url()).toBe('http://localhost:4173/about');
expect(offlinePage.locator('li[aria-current="page"] a').getByText('About')).toBeTruthy();
// Dispose context once it's no longer needed.
await context.close();
});
-56
View File
@@ -1,56 +0,0 @@
import { test, expect } from '@playwright/test';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
test('The service worker is registered and cache storage is present', async ({ page }) => {
await page.goto('/');
const swURL = await page.evaluate(async () => {
const registration = await Promise.race([
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
navigator.serviceWorker.ready,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Service worker registration failed: time out')), 10000)
)
]);
// @ts-expect-error registration is of type unknown
return registration.active?.scriptURL;
});
const swName = 'sw.js';
expect(swURL).toBe(`http://localhost:4173/${swName}`);
const cacheContents = await page.evaluate(async () => {
const cacheState: Record<string, Array<string>> = {};
for (const cacheName of await caches.keys()) {
const cache = await caches.open(cacheName);
cacheState[cacheName] = (await cache.keys()).map((req) => req.url);
}
return cacheState;
});
expect(Object.keys(cacheContents).length).toEqual(1);
const key = 'workbox-precache-v2-http://localhost:4173/';
expect(Object.keys(cacheContents)[0]).toEqual(key);
const urls = cacheContents[key].map((url) => url.slice('http://localhost:4173/'.length));
/*
'http://localhost:4173/about?__WB_REVISION__=38251751d310c9b683a1426c22c135a2',
'http://localhost:4173/?__WB_REVISION__=073370aa3804305a787b01180cd6b8aa',
'http://localhost:4173/manifest.webmanifest?__WB_REVISION__=27df2fa4f35d014b42361148a2207da3'
*/
expect(urls.some((url) => url.startsWith('manifest.webmanifest?__WB_REVISION__='))).toEqual(true);
expect(urls.some((url) => url.startsWith('?__WB_REVISION__='))).toEqual(true);
expect(urls.some((url) => url.startsWith('about?__WB_REVISION__='))).toEqual(true);
// dontCacheBustURLsMatching: any asset in _app/immutable folder shouldn't have a revision (?__WB_REVISION__=)
expect(urls.some((url) => url.startsWith('_app/immutable/') && url.endsWith('.css'))).toEqual(
true
);
expect(urls.some((url) => url.startsWith('_app/immutable/') && url.endsWith('.js'))).toEqual(
true
);
expect(urls.some((url) => url.includes('_app/version.json?__WB_REVISION__='))).toEqual(true);
});
+52
View File
@@ -0,0 +1,52 @@
dexId,gameDisplayName,dexDisplayName,sortOrder,isDlc,parentDexId,file
red-kanto,Red,Kanto,1,false,,native-game-dexes/red-blue-yellow.csv
blue-kanto,Blue,Kanto,1,false,,native-game-dexes/red-blue-yellow.csv
yellow-kanto,Yellow,Kanto,1,false,,native-game-dexes/red-blue-yellow.csv
gold-johto,Gold,Johto,1,false,,native-game-dexes/gold-silver-crystal.csv
silver-johto,Silver,Johto,1,false,,native-game-dexes/gold-silver-crystal.csv
crystal-johto,Crystal,Johto,1,false,,native-game-dexes/gold-silver-crystal.csv
ruby-hoenn,Ruby,Hoenn,1,false,,native-game-dexes/ruby-sapphire-emerald.csv
sapphire-hoenn,Sapphire,Hoenn,1,false,,native-game-dexes/ruby-sapphire-emerald.csv
emerald-hoenn,Emerald,Hoenn,1,false,,native-game-dexes/ruby-sapphire-emerald.csv
firered-kanto,FireRed,Kanto,1,false,,native-game-dexes/fire-red-leaf-green.csv
leafgreen-kanto,LeafGreen,Kanto,1,false,,native-game-dexes/fire-red-leaf-green.csv
diamond-sinnoh,Diamond,Sinnoh,1,false,,native-game-dexes/diamond-pearl.csv
pearl-sinnoh,Pearl,Sinnoh,1,false,,native-game-dexes/diamond-pearl.csv
platinum-sinnoh,Platinum,Sinnoh,1,false,,native-game-dexes/platinum.csv
heart-gold-johto,Heart Gold,Johto,1,false,,native-game-dexes/heart-gold-soul-silver.csv
soul-silver-johto,Soul Silver,Johto,1,false,,native-game-dexes/heart-gold-soul-silver.csv
black-unova,Black,Unova,1,false,,native-game-dexes/black-white.csv
white-unova,White,Unova,1,false,,native-game-dexes/black-white.csv
black-2-unova,Black 2,Unova,1,false,,native-game-dexes/black-2-white-2.csv
white-2-unova,White 2,Unova,1,false,,native-game-dexes/black-2-white-2.csv
x-central-kalos,X,Central Kalos,1,false,,native-game-dexes/x-y-central-kalos.csv
x-coastal-kalos,X,Coastal Kalos,2,false,,native-game-dexes/x-y-coastal-kalos.csv
x-mountain-kalos,X,Mountain Kalos,3,false,,native-game-dexes/x-y-mountain-kalos.csv
y-central-kalos,Y,Central Kalos,1,false,,native-game-dexes/x-y-central-kalos.csv
y-coastal-kalos,Y,Coastal Kalos,2,false,,native-game-dexes/x-y-coastal-kalos.csv
y-mountain-kalos,Y,Mountain Kalos,3,false,,native-game-dexes/x-y-mountain-kalos.csv
omega-ruby-hoenn,Omega Ruby,Hoenn,1,false,,native-game-dexes/omega-ruby-alpha-sapphire.csv
alpha-sapphire-hoenn,Alpha Sapphire,Hoenn,1,false,,native-game-dexes/omega-ruby-alpha-sapphire.csv
sun-alola,Sun,Alola,1,false,,native-game-dexes/sun-moon-alola.csv
moon-alola,Moon,Alola,1,false,,native-game-dexes/sun-moon-alola.csv
ultra-sun-alola,Ultra Sun,Alola,1,false,,native-game-dexes/ultra-sun-ultra-moon-alola.csv
ultra-moon-alola,Ultra Moon,Alola,1,false,,native-game-dexes/ultra-sun-ultra-moon-alola.csv
lg-pikachu-kanto,LG: Pikachu,Kanto,1,false,,native-game-dexes/lets-go-pikachu-eevee.csv
lg-eevee-kanto,LG: Eevee,Kanto,1,false,,native-game-dexes/lets-go-pikachu-eevee.csv
sword-galar,Sword,Galar,1,false,,native-game-dexes/sword-shield.csv
sword-isle-armor,Sword,Isle of Armor,2,true,sword-galar,native-game-dexes/sword-shield-isle-armor.csv
sword-crown-tundra,Sword,Crown Tundra,3,true,sword-galar,native-game-dexes/sword-shield-crown-tundra.csv
shield-galar,Shield,Galar,1,false,,native-game-dexes/sword-shield.csv
shield-isle-armor,Shield,Isle of Armor,2,true,shield-galar,native-game-dexes/sword-shield-isle-armor.csv
shield-crown-tundra,Shield,Crown Tundra,3,true,shield-galar,native-game-dexes/sword-shield-crown-tundra.csv
brilliant-diamond-sinnoh,Brilliant Diamond,Sinnoh,1,false,,native-game-dexes/brilliant-diamond-shining-pearl.csv
shining-pearl-sinnoh,Shining Pearl,Sinnoh,1,false,,native-game-dexes/brilliant-diamond-shining-pearl.csv
legends-arceus-hisui,Legends: Arceus,Hisui,1,false,,native-game-dexes/legends-arceus.csv
scarlet-paldea,Scarlet,Paldea,1,false,,native-game-dexes/scarlet-violet.csv
scarlet-kitakami,Scarlet,Kitakami,2,true,scarlet-paldea,native-game-dexes/scarlet-violet-kitakami.csv
scarlet-blueberry,Scarlet,Blueberry,3,true,scarlet-paldea,native-game-dexes/scarlet-violet-blueberry.csv
violet-paldea,Violet,Paldea,1,false,,native-game-dexes/scarlet-violet.csv
violet-kitakami,Violet,Kitakami,2,true,violet-paldea,native-game-dexes/scarlet-violet-kitakami.csv
violet-blueberry,Violet,Blueberry,3,true,violet-paldea,native-game-dexes/scarlet-violet-blueberry.csv
legends-z-a-kalos,Legends: Z-A,Kalos,1,false,,native-game-dexes/legends-z-a.csv
legends-z-a-mega-dimension,Legends: Z-A,Mega Dimension,2,true,legends-z-a-kalos,native-game-dexes/legends-z-a-mega-dimension.csv
1 dexId gameDisplayName dexDisplayName sortOrder isDlc parentDexId file
2 red-kanto Red Kanto 1 false native-game-dexes/red-blue-yellow.csv
3 blue-kanto Blue Kanto 1 false native-game-dexes/red-blue-yellow.csv
4 yellow-kanto Yellow Kanto 1 false native-game-dexes/red-blue-yellow.csv
5 gold-johto Gold Johto 1 false native-game-dexes/gold-silver-crystal.csv
6 silver-johto Silver Johto 1 false native-game-dexes/gold-silver-crystal.csv
7 crystal-johto Crystal Johto 1 false native-game-dexes/gold-silver-crystal.csv
8 ruby-hoenn Ruby Hoenn 1 false native-game-dexes/ruby-sapphire-emerald.csv
9 sapphire-hoenn Sapphire Hoenn 1 false native-game-dexes/ruby-sapphire-emerald.csv
10 emerald-hoenn Emerald Hoenn 1 false native-game-dexes/ruby-sapphire-emerald.csv
11 firered-kanto FireRed Kanto 1 false native-game-dexes/fire-red-leaf-green.csv
12 leafgreen-kanto LeafGreen Kanto 1 false native-game-dexes/fire-red-leaf-green.csv
13 diamond-sinnoh Diamond Sinnoh 1 false native-game-dexes/diamond-pearl.csv
14 pearl-sinnoh Pearl Sinnoh 1 false native-game-dexes/diamond-pearl.csv
15 platinum-sinnoh Platinum Sinnoh 1 false native-game-dexes/platinum.csv
16 heart-gold-johto Heart Gold Johto 1 false native-game-dexes/heart-gold-soul-silver.csv
17 soul-silver-johto Soul Silver Johto 1 false native-game-dexes/heart-gold-soul-silver.csv
18 black-unova Black Unova 1 false native-game-dexes/black-white.csv
19 white-unova White Unova 1 false native-game-dexes/black-white.csv
20 black-2-unova Black 2 Unova 1 false native-game-dexes/black-2-white-2.csv
21 white-2-unova White 2 Unova 1 false native-game-dexes/black-2-white-2.csv
22 x-central-kalos X Central Kalos 1 false native-game-dexes/x-y-central-kalos.csv
23 x-coastal-kalos X Coastal Kalos 2 false native-game-dexes/x-y-coastal-kalos.csv
24 x-mountain-kalos X Mountain Kalos 3 false native-game-dexes/x-y-mountain-kalos.csv
25 y-central-kalos Y Central Kalos 1 false native-game-dexes/x-y-central-kalos.csv
26 y-coastal-kalos Y Coastal Kalos 2 false native-game-dexes/x-y-coastal-kalos.csv
27 y-mountain-kalos Y Mountain Kalos 3 false native-game-dexes/x-y-mountain-kalos.csv
28 omega-ruby-hoenn Omega Ruby Hoenn 1 false native-game-dexes/omega-ruby-alpha-sapphire.csv
29 alpha-sapphire-hoenn Alpha Sapphire Hoenn 1 false native-game-dexes/omega-ruby-alpha-sapphire.csv
30 sun-alola Sun Alola 1 false native-game-dexes/sun-moon-alola.csv
31 moon-alola Moon Alola 1 false native-game-dexes/sun-moon-alola.csv
32 ultra-sun-alola Ultra Sun Alola 1 false native-game-dexes/ultra-sun-ultra-moon-alola.csv
33 ultra-moon-alola Ultra Moon Alola 1 false native-game-dexes/ultra-sun-ultra-moon-alola.csv
34 lg-pikachu-kanto LG: Pikachu Kanto 1 false native-game-dexes/lets-go-pikachu-eevee.csv
35 lg-eevee-kanto LG: Eevee Kanto 1 false native-game-dexes/lets-go-pikachu-eevee.csv
36 sword-galar Sword Galar 1 false native-game-dexes/sword-shield.csv
37 sword-isle-armor Sword Isle of Armor 2 true sword-galar native-game-dexes/sword-shield-isle-armor.csv
38 sword-crown-tundra Sword Crown Tundra 3 true sword-galar native-game-dexes/sword-shield-crown-tundra.csv
39 shield-galar Shield Galar 1 false native-game-dexes/sword-shield.csv
40 shield-isle-armor Shield Isle of Armor 2 true shield-galar native-game-dexes/sword-shield-isle-armor.csv
41 shield-crown-tundra Shield Crown Tundra 3 true shield-galar native-game-dexes/sword-shield-crown-tundra.csv
42 brilliant-diamond-sinnoh Brilliant Diamond Sinnoh 1 false native-game-dexes/brilliant-diamond-shining-pearl.csv
43 shining-pearl-sinnoh Shining Pearl Sinnoh 1 false native-game-dexes/brilliant-diamond-shining-pearl.csv
44 legends-arceus-hisui Legends: Arceus Hisui 1 false native-game-dexes/legends-arceus.csv
45 scarlet-paldea Scarlet Paldea 1 false native-game-dexes/scarlet-violet.csv
46 scarlet-kitakami Scarlet Kitakami 2 true scarlet-paldea native-game-dexes/scarlet-violet-kitakami.csv
47 scarlet-blueberry Scarlet Blueberry 3 true scarlet-paldea native-game-dexes/scarlet-violet-blueberry.csv
48 violet-paldea Violet Paldea 1 false native-game-dexes/scarlet-violet.csv
49 violet-kitakami Violet Kitakami 2 true violet-paldea native-game-dexes/scarlet-violet-kitakami.csv
50 violet-blueberry Violet Blueberry 3 true violet-paldea native-game-dexes/scarlet-violet-blueberry.csv
51 legends-z-a-kalos Legends: Z-A Kalos 1 false native-game-dexes/legends-z-a.csv
52 legends-z-a-mega-dimension Legends: Z-A Mega Dimension 2 true legends-z-a-kalos native-game-dexes/legends-z-a-mega-dimension.csv
+46
View File
@@ -0,0 +1,46 @@
game,region,releaseYear
Red,Kanto,1996
Blue,Kanto,1996
Yellow,Kanto,1998
Gold,Johto,1999
Silver,Johto,1999
Crystal,Johto,2000
Ruby,Hoenn,2002
Sapphire,Hoenn,2002
Colosseum,Orre,2003
Emerald,Hoenn,2004
FireRed,Kanto,2004
LeafGreen,Kanto,2004
XD: Gale of Darkness,Orre,2005
Diamond,Sinnoh,2006
Pearl,Sinnoh,2006
Platinum,Sinnoh,2008
Ranch,Ranch,2008
Heart Gold,Johto,2009
Soul Silver,Johto,2009
Black,Unova,2010
White,Unova,2010
Black 2,Unova,2012
White 2,Unova,2012
Dream Radar,Unova,2012
X,Kalos,2013
Y,Kalos,2013
Omega Ruby,Hoenn,2014
Alpha Sapphire,Hoenn,2014
Sun,Alola,2016
Moon,Alola,2016
Moon (demo),Alola,2016
Go,Go,2016
Ultra Sun,Alola,2017
Ultra Moon,Alola,2017
LG: Pikachu,Kanto,2018
LG: Eevee,Kanto,2018
Sword,Galar,2019
Shield,Galar,2019
Home,Home,2020
Brilliant Diamond,Sinnoh,2021
Shining Pearl,Sinnoh,2021
Legends: Arceus,Hisui,2022
Scarlet,Paldea,2022
Violet,Paldea,2022
Legends: Z-A,Kalos,2025
1 game region releaseYear
2 Red Kanto 1996
3 Blue Kanto 1996
4 Yellow Kanto 1998
5 Gold Johto 1999
6 Silver Johto 1999
7 Crystal Johto 2000
8 Ruby Hoenn 2002
9 Sapphire Hoenn 2002
10 Colosseum Orre 2003
11 Emerald Hoenn 2004
12 FireRed Kanto 2004
13 LeafGreen Kanto 2004
14 XD: Gale of Darkness Orre 2005
15 Diamond Sinnoh 2006
16 Pearl Sinnoh 2006
17 Platinum Sinnoh 2008
18 Ranch Ranch 2008
19 Heart Gold Johto 2009
20 Soul Silver Johto 2009
21 Black Unova 2010
22 White Unova 2010
23 Black 2 Unova 2012
24 White 2 Unova 2012
25 Dream Radar Unova 2012
26 X Kalos 2013
27 Y Kalos 2013
28 Omega Ruby Hoenn 2014
29 Alpha Sapphire Hoenn 2014
30 Sun Alola 2016
31 Moon Alola 2016
32 Moon (demo) Alola 2016
33 Go Go 2016
34 Ultra Sun Alola 2017
35 Ultra Moon Alola 2017
36 LG: Pikachu Kanto 2018
37 LG: Eevee Kanto 2018
38 Sword Galar 2019
39 Shield Galar 2019
40 Home Home 2020
41 Brilliant Diamond Sinnoh 2021
42 Shining Pearl Sinnoh 2021
43 Legends: Arceus Hisui 2022
44 Scarlet Paldea 2022
45 Violet Paldea 2022
46 Legends: Z-A Kalos 2025
@@ -0,0 +1,302 @@
dexNumber,pokemon,form,notes
0,Victini,,
1,Snivy,,
2,Servine,,
3,Serperior,,
4,Tepig,,
5,Pignite,,
6,Emboar,,
7,Oshawott,,
8,Dewott,,
9,Samurott,,
10,Patrat,,
11,Watchog,,
12,Purrloin,,
13,Liepard,,
14,Pidove,,
15,Tranquill,,
16,Unfezant,,
17,Sewaddle,,
18,Swadloon,,
19,Leavanny,,
20,Sunkern,,
21,Sunflora,,
22,Lillipup,,
23,Herdier,,
24,Stoutland,,
25,Mareep,,
26,Flaaffy,,
27,Ampharos,,
28,Psyduck,,
29,Golduck,,
30,Azurill,,
31,Marill,,
32,Azumarill,,
33,Riolu,,
34,Lucario,,
35,Dunsparce,,
36,Audino,,
37,Pansage,,
38,Simisage,,
39,Pansear,,
40,Simisear,,
41,Panpour,,
42,Simipour,,
43,Venipede,,
44,Whirlipede,,
45,Scolipede,,
46,Koffing,,
47,Weezing,,
48,Magnemite,,
49,Magneton,,
50,Magnezone,,
51,Growlithe,,
52,Arcanine,,
53,Magby,,
54,Magmar,,
55,Magmortar,,
56,Elekid,,
57,Electabuzz,,
58,Electivire,,
59,Rattata,,
60,Raticate,,
61,Zubat,,
62,Golbat,,
63,Crobat,,
64,Grimer,,
65,Muk,,
66,Woobat,,
67,Swoobat,,
68,Roggenrola,,
69,Boldore,,
70,Gigalith,,
71,Onix,,
72,Steelix,,
73,Timburr,,
74,Gurdurr,,
75,Conkeldurr,,
76,Drilbur,,
77,Excadrill,,
78,Skitty,,
79,Delcatty,,
80,Buneary,,
81,Lopunny,,
82,Cottonee,,
83,Whimsicott,,
84,Petilil,,
85,Lilligant,,
86,Munna,,
87,Musharna,,
88,Cleffa,,
89,Clefairy,,
90,Clefable,,
91,Eevee,,
92,Vaporeon,,
93,Jolteon,,
94,Flareon,,
95,Espeon,,
96,Umbreon,,
97,Leafeon,,
98,Glaceon,,
99,Sandile,,
100,Krokorok,,
101,Krookodile,,
102,Darumaka,,
103,Darmanitan,,
104,Basculin,,
105,Trubbish,,
106,Garbodor,,
107,Minccino,,
108,Cinccino,,
109,Rufflet,,
110,Braviary,,
111,Vullaby,,
112,Mandibuzz,,
113,Sandshrew,,
114,Sandslash,,
115,Dwebble,,
116,Crustle,,
117,Scraggy,,
118,Scrafty,,
119,Maractus,,
120,Sigilyph,,
121,Trapinch,,
122,Vibrava,,
123,Flygon,,
124,Yamask,,
125,Cofagrigus,,
126,Tirtouga,,
127,Carracosta,,
128,Archen,,
129,Archeops,,
130,Klink,,
131,Klang,,
132,Klinklang,,
133,Budew,,
134,Roselia,,
135,Roserade,,
136,Gothita,,
137,Gothorita,,
138,Gothitelle,,
139,Solosis,,
140,Duosion,,
141,Reuniclus,,
142,Combee,,
143,Vespiquen,,
144,Emolga,,
145,Heracross,,
146,Pinsir,,
147,Blitzle,,
148,Zebstrika,,
149,Buizel,,
150,Floatzel,,
151,Zorua,,
152,Zoroark,,
153,Ducklett,,
154,Swanna,,
155,Karrablast,,
156,Escavalier,,
157,Shelmet,,
158,Accelgor,,
159,Deerling,,
160,Sawsbuck,,
161,Foongus,,
162,Amoonguss,,
163,Castform,,
164,Nosepass,,
165,Probopass,,
166,Aron,,
167,Lairon,,
168,Aggron,,
169,Baltoy,,
170,Claydol,,
171,Larvesta,,
172,Volcarona,,
173,Joltik,,
174,Galvantula,,
175,Ferroseed,,
176,Ferrothorn,,
177,Tynamo,,
178,Eelektrik,,
179,Eelektross,,
180,Frillish,,
181,Jellicent,,
182,Alomomola,,
183,Axew,,
184,Fraxure,,
185,Haxorus,,
186,Zangoose,,
187,Seviper,,
188,Elgyem,,
189,Beheeyem,,
190,Litwick,,
191,Lampent,,
192,Chandelure,,
193,Heatmor,,
194,Durant,,
195,Cubchoo,,
196,Beartic,,
197,Cryogonal,,
198,Tornadus,,
199,Thundurus,,
200,Landorus,,
201,Skorupi,,
202,Drapion,,
203,Skarmory,,
204,Numel,,
205,Camerupt,,
206,Spoink,,
207,Grumpig,,
208,Drifloon,,
209,Drifblim,,
210,Shuppet,,
211,Banette,,
212,Wingull,,
213,Pelipper,,
214,Lunatone,,
215,Solrock,,
216,Absol,,
217,Tangela,,
218,Tangrowth,,
219,Mienfoo,,
220,Mienshao,,
221,Gligar,,
222,Gliscor,,
223,Pawniard,,
224,Bisharp,,
225,Cobalion,,
226,Terrakion,,
227,Virizion,,
228,Tympole,,
229,Palpitoad,,
230,Seismitoad,,
231,Stunfisk,,
232,Shuckle,,
233,Mantyke,,
234,Mantine,,
235,Remoraid,,
236,Octillery,,
237,Corsola,,
238,Staryu,,
239,Starmie,,
240,Wailmer,,
241,Wailord,,
242,Lapras,,
243,Spheal,,
244,Sealeo,,
245,Walrein,,
246,Swablu,,
247,Altaria,,
248,Vulpix,,
249,Ninetales,,
250,Bronzor,,
251,Bronzong,,
252,Sneasel,,
253,Weavile,,
254,Delibird,,
255,Vanillite,,
256,Vanillish,,
257,Vanilluxe,,
258,Swinub,,
259,Piloswine,,
260,Mamoswine,,
261,Ditto,,
262,Beldum,,
263,Metang,,
264,Metagross,,
265,Seel,,
266,Dewgong,,
267,Throh,,
268,Sawk,,
269,Bouffalant,,
270,Druddigon,,
271,Golett,,
272,Golurk,,
273,Deino,,
274,Zweilous,,
275,Hydreigon,,
276,Slakoth,,
277,Vigoroth,,
278,Slaking,,
279,Corphish,,
280,Crawdaunt,,
281,Igglybuff,,
282,Jigglypuff,,
283,Wigglytuff,,
284,Lickitung,,
285,Lickilicky,,
286,Yanma,,
287,Yanmega,,
288,Tropius,,
289,Carnivine,,
290,Croagunk,,
291,Toxicroak,,
292,Larvitar,,
293,Pupitar,,
294,Tyranitar,,
295,Reshiram,,
296,Zekrom,,
297,Kyurem,,
298,Keldeo,,
299,Meloetta,,
300,Genesect,,
1 dexNumber pokemon form notes
2 0 Victini
3 1 Snivy
4 2 Servine
5 3 Serperior
6 4 Tepig
7 5 Pignite
8 6 Emboar
9 7 Oshawott
10 8 Dewott
11 9 Samurott
12 10 Patrat
13 11 Watchog
14 12 Purrloin
15 13 Liepard
16 14 Pidove
17 15 Tranquill
18 16 Unfezant
19 17 Sewaddle
20 18 Swadloon
21 19 Leavanny
22 20 Sunkern
23 21 Sunflora
24 22 Lillipup
25 23 Herdier
26 24 Stoutland
27 25 Mareep
28 26 Flaaffy
29 27 Ampharos
30 28 Psyduck
31 29 Golduck
32 30 Azurill
33 31 Marill
34 32 Azumarill
35 33 Riolu
36 34 Lucario
37 35 Dunsparce
38 36 Audino
39 37 Pansage
40 38 Simisage
41 39 Pansear
42 40 Simisear
43 41 Panpour
44 42 Simipour
45 43 Venipede
46 44 Whirlipede
47 45 Scolipede
48 46 Koffing
49 47 Weezing
50 48 Magnemite
51 49 Magneton
52 50 Magnezone
53 51 Growlithe
54 52 Arcanine
55 53 Magby
56 54 Magmar
57 55 Magmortar
58 56 Elekid
59 57 Electabuzz
60 58 Electivire
61 59 Rattata
62 60 Raticate
63 61 Zubat
64 62 Golbat
65 63 Crobat
66 64 Grimer
67 65 Muk
68 66 Woobat
69 67 Swoobat
70 68 Roggenrola
71 69 Boldore
72 70 Gigalith
73 71 Onix
74 72 Steelix
75 73 Timburr
76 74 Gurdurr
77 75 Conkeldurr
78 76 Drilbur
79 77 Excadrill
80 78 Skitty
81 79 Delcatty
82 80 Buneary
83 81 Lopunny
84 82 Cottonee
85 83 Whimsicott
86 84 Petilil
87 85 Lilligant
88 86 Munna
89 87 Musharna
90 88 Cleffa
91 89 Clefairy
92 90 Clefable
93 91 Eevee
94 92 Vaporeon
95 93 Jolteon
96 94 Flareon
97 95 Espeon
98 96 Umbreon
99 97 Leafeon
100 98 Glaceon
101 99 Sandile
102 100 Krokorok
103 101 Krookodile
104 102 Darumaka
105 103 Darmanitan
106 104 Basculin
107 105 Trubbish
108 106 Garbodor
109 107 Minccino
110 108 Cinccino
111 109 Rufflet
112 110 Braviary
113 111 Vullaby
114 112 Mandibuzz
115 113 Sandshrew
116 114 Sandslash
117 115 Dwebble
118 116 Crustle
119 117 Scraggy
120 118 Scrafty
121 119 Maractus
122 120 Sigilyph
123 121 Trapinch
124 122 Vibrava
125 123 Flygon
126 124 Yamask
127 125 Cofagrigus
128 126 Tirtouga
129 127 Carracosta
130 128 Archen
131 129 Archeops
132 130 Klink
133 131 Klang
134 132 Klinklang
135 133 Budew
136 134 Roselia
137 135 Roserade
138 136 Gothita
139 137 Gothorita
140 138 Gothitelle
141 139 Solosis
142 140 Duosion
143 141 Reuniclus
144 142 Combee
145 143 Vespiquen
146 144 Emolga
147 145 Heracross
148 146 Pinsir
149 147 Blitzle
150 148 Zebstrika
151 149 Buizel
152 150 Floatzel
153 151 Zorua
154 152 Zoroark
155 153 Ducklett
156 154 Swanna
157 155 Karrablast
158 156 Escavalier
159 157 Shelmet
160 158 Accelgor
161 159 Deerling
162 160 Sawsbuck
163 161 Foongus
164 162 Amoonguss
165 163 Castform
166 164 Nosepass
167 165 Probopass
168 166 Aron
169 167 Lairon
170 168 Aggron
171 169 Baltoy
172 170 Claydol
173 171 Larvesta
174 172 Volcarona
175 173 Joltik
176 174 Galvantula
177 175 Ferroseed
178 176 Ferrothorn
179 177 Tynamo
180 178 Eelektrik
181 179 Eelektross
182 180 Frillish
183 181 Jellicent
184 182 Alomomola
185 183 Axew
186 184 Fraxure
187 185 Haxorus
188 186 Zangoose
189 187 Seviper
190 188 Elgyem
191 189 Beheeyem
192 190 Litwick
193 191 Lampent
194 192 Chandelure
195 193 Heatmor
196 194 Durant
197 195 Cubchoo
198 196 Beartic
199 197 Cryogonal
200 198 Tornadus
201 199 Thundurus
202 200 Landorus
203 201 Skorupi
204 202 Drapion
205 203 Skarmory
206 204 Numel
207 205 Camerupt
208 206 Spoink
209 207 Grumpig
210 208 Drifloon
211 209 Drifblim
212 210 Shuppet
213 211 Banette
214 212 Wingull
215 213 Pelipper
216 214 Lunatone
217 215 Solrock
218 216 Absol
219 217 Tangela
220 218 Tangrowth
221 219 Mienfoo
222 220 Mienshao
223 221 Gligar
224 222 Gliscor
225 223 Pawniard
226 224 Bisharp
227 225 Cobalion
228 226 Terrakion
229 227 Virizion
230 228 Tympole
231 229 Palpitoad
232 230 Seismitoad
233 231 Stunfisk
234 232 Shuckle
235 233 Mantyke
236 234 Mantine
237 235 Remoraid
238 236 Octillery
239 237 Corsola
240 238 Staryu
241 239 Starmie
242 240 Wailmer
243 241 Wailord
244 242 Lapras
245 243 Spheal
246 244 Sealeo
247 245 Walrein
248 246 Swablu
249 247 Altaria
250 248 Vulpix
251 249 Ninetales
252 250 Bronzor
253 251 Bronzong
254 252 Sneasel
255 253 Weavile
256 254 Delibird
257 255 Vanillite
258 256 Vanillish
259 257 Vanilluxe
260 258 Swinub
261 259 Piloswine
262 260 Mamoswine
263 261 Ditto
264 262 Beldum
265 263 Metang
266 264 Metagross
267 265 Seel
268 266 Dewgong
269 267 Throh
270 268 Sawk
271 269 Bouffalant
272 270 Druddigon
273 271 Golett
274 272 Golurk
275 273 Deino
276 274 Zweilous
277 275 Hydreigon
278 276 Slakoth
279 277 Vigoroth
280 278 Slaking
281 279 Corphish
282 280 Crawdaunt
283 281 Igglybuff
284 282 Jigglypuff
285 283 Wigglytuff
286 284 Lickitung
287 285 Lickilicky
288 286 Yanma
289 287 Yanmega
290 288 Tropius
291 289 Carnivine
292 290 Croagunk
293 291 Toxicroak
294 292 Larvitar
295 293 Pupitar
296 294 Tyranitar
297 295 Reshiram
298 296 Zekrom
299 297 Kyurem
300 298 Keldeo
301 299 Meloetta
302 300 Genesect
+157
View File
@@ -0,0 +1,157 @@
dexNumber,pokemon,form,notes
0,Victini,,
1,Snivy,,
2,Servine,,
3,Serperior,,
4,Tepig,,
5,Pignite,,
6,Emboar,,
7,Oshawott,,
8,Dewott,,
9,Samurott,,
10,Patrat,,
11,Watchog,,
12,Lillipup,,
13,Herdier,,
14,Stoutland,,
15,Purrloin,,
16,Liepard,,
17,Pansage,,
18,Simisage,,
19,Pansear,,
20,Simisear,,
21,Panpour,,
22,Simipour,,
23,Munna,,
24,Musharna,,
25,Pidove,,
26,Tranquill,,
27,Unfezant,,
28,Blitzle,,
29,Zebstrika,,
30,Roggenrola,,
31,Boldore,,
32,Gigalith,,
33,Woobat,,
34,Swoobat,,
35,Drilbur,,
36,Excadrill,,
37,Audino,,
38,Timburr,,
39,Gurdurr,,
40,Conkeldurr,,
41,Tympole,,
42,Palpitoad,,
43,Seismitoad,,
44,Throh,,
45,Sawk,,
46,Sewaddle,,
47,Swadloon,,
48,Leavanny,,
49,Venipede,,
50,Whirlipede,,
51,Scolipede,,
52,Cottonee,,
53,Whimsicott,,
54,Petilil,,
55,Lilligant,,
56,Basculin,,
57,Sandile,,
58,Krokorok,,
59,Krookodile,,
60,Darumaka,,
61,Darmanitan,,
62,Maractus,,
63,Dwebble,,
64,Crustle,,
65,Scraggy,,
66,Scrafty,,
67,Sigilyph,,
68,Yamask,,
69,Cofagrigus,,
70,Tirtouga,,
71,Carracosta,,
72,Archen,,
73,Archeops,,
74,Trubbish,,
75,Garbodor,,
76,Zorua,,
77,Zoroark,,
78,Minccino,,
79,Cinccino,,
80,Gothita,,
81,Gothorita,,
82,Gothitelle,,
83,Solosis,,
84,Duosion,,
85,Reuniclus,,
86,Ducklett,,
87,Swanna,,
88,Vanillite,,
89,Vanillish,,
90,Vanilluxe,,
91,Deerling,,
92,Sawsbuck,,
93,Emolga,,
94,Karrablast,,
95,Escavalier,,
96,Foongus,,
97,Amoonguss,,
98,Frillish,,
99,Jellicent,,
100,Alomomola,,
101,Joltik,,
102,Galvantula,,
103,Ferroseed,,
104,Ferrothorn,,
105,Klink,,
106,Klang,,
107,Klinklang,,
108,Tynamo,,
109,Eelektrik,,
110,Eelektross,,
111,Elgyem,,
112,Beheeyem,,
113,Litwick,,
114,Lampent,,
115,Chandelure,,
116,Axew,,
117,Fraxure,,
118,Haxorus,,
119,Cubchoo,,
120,Beartic,,
121,Cryogonal,,
122,Shelmet,,
123,Accelgor,,
124,Stunfisk,,
125,Mienfoo,,
126,Mienshao,,
127,Druddigon,,
128,Golett,,
129,Golurk,,
130,Pawniard,,
131,Bisharp,,
132,Bouffalant,,
133,Rufflet,,
134,Braviary,,
135,Vullaby,,
136,Mandibuzz,,
137,Heatmor,,
138,Durant,,
139,Deino,,
140,Zweilous,,
141,Hydreigon,,
142,Larvesta,,
143,Volcarona,,
144,Cobalion,,
145,Terrakion,,
146,Virizion,,
147,Tornadus,,
148,Thundurus,,
149,Reshiram,,
150,Zekrom,,
151,Landorus,,
152,Kyurem,,
153,Keldeo,,
154,Meloetta,,
155,Genesect,,
1 dexNumber pokemon form notes
2 0 Victini
3 1 Snivy
4 2 Servine
5 3 Serperior
6 4 Tepig
7 5 Pignite
8 6 Emboar
9 7 Oshawott
10 8 Dewott
11 9 Samurott
12 10 Patrat
13 11 Watchog
14 12 Lillipup
15 13 Herdier
16 14 Stoutland
17 15 Purrloin
18 16 Liepard
19 17 Pansage
20 18 Simisage
21 19 Pansear
22 20 Simisear
23 21 Panpour
24 22 Simipour
25 23 Munna
26 24 Musharna
27 25 Pidove
28 26 Tranquill
29 27 Unfezant
30 28 Blitzle
31 29 Zebstrika
32 30 Roggenrola
33 31 Boldore
34 32 Gigalith
35 33 Woobat
36 34 Swoobat
37 35 Drilbur
38 36 Excadrill
39 37 Audino
40 38 Timburr
41 39 Gurdurr
42 40 Conkeldurr
43 41 Tympole
44 42 Palpitoad
45 43 Seismitoad
46 44 Throh
47 45 Sawk
48 46 Sewaddle
49 47 Swadloon
50 48 Leavanny
51 49 Venipede
52 50 Whirlipede
53 51 Scolipede
54 52 Cottonee
55 53 Whimsicott
56 54 Petilil
57 55 Lilligant
58 56 Basculin
59 57 Sandile
60 58 Krokorok
61 59 Krookodile
62 60 Darumaka
63 61 Darmanitan
64 62 Maractus
65 63 Dwebble
66 64 Crustle
67 65 Scraggy
68 66 Scrafty
69 67 Sigilyph
70 68 Yamask
71 69 Cofagrigus
72 70 Tirtouga
73 71 Carracosta
74 72 Archen
75 73 Archeops
76 74 Trubbish
77 75 Garbodor
78 76 Zorua
79 77 Zoroark
80 78 Minccino
81 79 Cinccino
82 80 Gothita
83 81 Gothorita
84 82 Gothitelle
85 83 Solosis
86 84 Duosion
87 85 Reuniclus
88 86 Ducklett
89 87 Swanna
90 88 Vanillite
91 89 Vanillish
92 90 Vanilluxe
93 91 Deerling
94 92 Sawsbuck
95 93 Emolga
96 94 Karrablast
97 95 Escavalier
98 96 Foongus
99 97 Amoonguss
100 98 Frillish
101 99 Jellicent
102 100 Alomomola
103 101 Joltik
104 102 Galvantula
105 103 Ferroseed
106 104 Ferrothorn
107 105 Klink
108 106 Klang
109 107 Klinklang
110 108 Tynamo
111 109 Eelektrik
112 110 Eelektross
113 111 Elgyem
114 112 Beheeyem
115 113 Litwick
116 114 Lampent
117 115 Chandelure
118 116 Axew
119 117 Fraxure
120 118 Haxorus
121 119 Cubchoo
122 120 Beartic
123 121 Cryogonal
124 122 Shelmet
125 123 Accelgor
126 124 Stunfisk
127 125 Mienfoo
128 126 Mienshao
129 127 Druddigon
130 128 Golett
131 129 Golurk
132 130 Pawniard
133 131 Bisharp
134 132 Bouffalant
135 133 Rufflet
136 134 Braviary
137 135 Vullaby
138 136 Mandibuzz
139 137 Heatmor
140 138 Durant
141 139 Deino
142 140 Zweilous
143 141 Hydreigon
144 142 Larvesta
145 143 Volcarona
146 144 Cobalion
147 145 Terrakion
148 146 Virizion
149 147 Tornadus
150 148 Thundurus
151 149 Reshiram
152 150 Zekrom
153 151 Landorus
154 152 Kyurem
155 153 Keldeo
156 154 Meloetta
157 155 Genesect
@@ -0,0 +1,152 @@
dexNumber,pokemon,form,notes
1,Turtwig,,
2,Grotle,,
3,Torterra,,
4,Chimchar,,
5,Monferno,,
6,Infernape,,
7,Piplup,,
8,Prinplup,,
9,Empoleon,,
10,Starly,,
11,Staravia,,
12,Staraptor,,
13,Bidoof,,
14,Bibarel,,
15,Kricketot,,
16,Kricketune,,
17,Shinx,,
18,Luxio,,
19,Luxray,,
20,Abra,,
21,Kadabra,,
22,Alakazam,,
23,Magikarp,,
24,Gyarados,,
25,Budew,,
26,Roselia,,
27,Roserade,,
28,Zubat,,
29,Golbat,,
30,Crobat,,
31,Geodude,,
32,Graveler,,
33,Golem,,
34,Onix,,
35,Steelix,,
36,Cranidos,,
37,Rampardos,,
38,Shieldon,,
39,Bastiodon,,
40,Machop,,
41,Machoke,,
42,Machamp,,
43,Psyduck,,
44,Golduck,,
45,Burmy,,
46,Wormadam,,
47,Mothim,,
48,Wurmple,,
49,Silcoon,,
50,Beautifly,,
51,Cascoon,,
52,Dustox,,
53,Combee,,
54,Vespiquen,,
55,Pachirisu,,
56,Buizel,,
57,Floatzel,,
58,Cherubi,,
59,Cherrim,,
60,Shellos,,
61,Gastrodon,,
62,Heracross,,
63,Aipom,,
64,Ambipom,,
65,Drifloon,,
66,Drifblim,,
67,Buneary,,
68,Lopunny,,
69,Gastly,,
70,Haunter,,
71,Gengar,,
72,Misdreavus,,
73,Mismagius,,
74,Murkrow,,
75,Honchkrow,,
76,Glameow,,
77,Purugly,,
78,Goldeen,,
79,Seaking,,
80,Barboach,,
81,Whiscash,,
82,Chingling,,
83,Chimecho,,
84,Stunky,,
85,Skuntank,,
86,Meditite,,
87,Medicham,,
88,Bronzor,,
89,Bronzong,,
90,Ponyta,,
91,Rapidash,,
92,Bonsly,,
93,Sudowoodo,,
94,Mime Jr.,,
95,Mr. Mime,,
96,Happiny,,
97,Chansey,,
98,Blissey,,
99,Cleffa,,
100,Clefairy,,
101,Clefable,,
102,Chatot,,
103,Pichu,,
104,Pikachu,,
105,Raichu,,
106,Hoothoot,,
107,Noctowl,,
108,Spiritomb,,
109,Gible,,
110,Gabite,,
111,Garchomp,,
112,Munchlax,,
113,Snorlax,,
114,Unown,,
115,Riolu,,
116,Lucario,,
117,Wooper,,
118,Quagsire,,
119,Wingull,,
120,Pelipper,,
121,Girafarig,,
122,Hippopotas,,
123,Hippowdon,,
124,Azurill,,
125,Marill,,
126,Azumarill,,
127,Skorupi,,
128,Drapion,,
129,Croagunk,,
130,Toxicroak,,
131,Carnivine,,
132,Remoraid,,
133,Octillery,,
134,Finneon,,
135,Lumineon,,
136,Tentacool,,
137,Tentacruel,,
138,Feebas,,
139,Milotic,,
140,Mantyke,,
141,Mantine,,
142,Snover,,
143,Abomasnow,,
144,Sneasel,,
145,Weavile,,
146,Uxie,,
147,Mesprit,,
148,Azelf,,
149,Dialga,,
150,Palkia,,
151,Manaphy,,
1 dexNumber pokemon form notes
2 1 Turtwig
3 2 Grotle
4 3 Torterra
5 4 Chimchar
6 5 Monferno
7 6 Infernape
8 7 Piplup
9 8 Prinplup
10 9 Empoleon
11 10 Starly
12 11 Staravia
13 12 Staraptor
14 13 Bidoof
15 14 Bibarel
16 15 Kricketot
17 16 Kricketune
18 17 Shinx
19 18 Luxio
20 19 Luxray
21 20 Abra
22 21 Kadabra
23 22 Alakazam
24 23 Magikarp
25 24 Gyarados
26 25 Budew
27 26 Roselia
28 27 Roserade
29 28 Zubat
30 29 Golbat
31 30 Crobat
32 31 Geodude
33 32 Graveler
34 33 Golem
35 34 Onix
36 35 Steelix
37 36 Cranidos
38 37 Rampardos
39 38 Shieldon
40 39 Bastiodon
41 40 Machop
42 41 Machoke
43 42 Machamp
44 43 Psyduck
45 44 Golduck
46 45 Burmy
47 46 Wormadam
48 47 Mothim
49 48 Wurmple
50 49 Silcoon
51 50 Beautifly
52 51 Cascoon
53 52 Dustox
54 53 Combee
55 54 Vespiquen
56 55 Pachirisu
57 56 Buizel
58 57 Floatzel
59 58 Cherubi
60 59 Cherrim
61 60 Shellos
62 61 Gastrodon
63 62 Heracross
64 63 Aipom
65 64 Ambipom
66 65 Drifloon
67 66 Drifblim
68 67 Buneary
69 68 Lopunny
70 69 Gastly
71 70 Haunter
72 71 Gengar
73 72 Misdreavus
74 73 Mismagius
75 74 Murkrow
76 75 Honchkrow
77 76 Glameow
78 77 Purugly
79 78 Goldeen
80 79 Seaking
81 80 Barboach
82 81 Whiscash
83 82 Chingling
84 83 Chimecho
85 84 Stunky
86 85 Skuntank
87 86 Meditite
88 87 Medicham
89 88 Bronzor
90 89 Bronzong
91 90 Ponyta
92 91 Rapidash
93 92 Bonsly
94 93 Sudowoodo
95 94 Mime Jr.
96 95 Mr. Mime
97 96 Happiny
98 97 Chansey
99 98 Blissey
100 99 Cleffa
101 100 Clefairy
102 101 Clefable
103 102 Chatot
104 103 Pichu
105 104 Pikachu
106 105 Raichu
107 106 Hoothoot
108 107 Noctowl
109 108 Spiritomb
110 109 Gible
111 110 Gabite
112 111 Garchomp
113 112 Munchlax
114 113 Snorlax
115 114 Unown
116 115 Riolu
117 116 Lucario
118 117 Wooper
119 118 Quagsire
120 119 Wingull
121 120 Pelipper
122 121 Girafarig
123 122 Hippopotas
124 123 Hippowdon
125 124 Azurill
126 125 Marill
127 126 Azumarill
128 127 Skorupi
129 128 Drapion
130 129 Croagunk
131 130 Toxicroak
132 131 Carnivine
133 132 Remoraid
134 133 Octillery
135 134 Finneon
136 135 Lumineon
137 136 Tentacool
138 137 Tentacruel
139 138 Feebas
140 139 Milotic
141 140 Mantyke
142 141 Mantine
143 142 Snover
144 143 Abomasnow
145 144 Sneasel
146 145 Weavile
147 146 Uxie
148 147 Mesprit
149 148 Azelf
150 149 Dialga
151 150 Palkia
152 151 Manaphy
@@ -0,0 +1,152 @@
dexNumber,pokemon,form,notes
1,Turtwig,,
2,Grotle,,
3,Torterra,,
4,Chimchar,,
5,Monferno,,
6,Infernape,,
7,Piplup,,
8,Prinplup,,
9,Empoleon,,
10,Starly,,
11,Staravia,,
12,Staraptor,,
13,Bidoof,,
14,Bibarel,,
15,Kricketot,,
16,Kricketune,,
17,Shinx,,
18,Luxio,,
19,Luxray,,
20,Abra,,
21,Kadabra,,
22,Alakazam,,
23,Magikarp,,
24,Gyarados,,
25,Budew,,
26,Roselia,,
27,Roserade,,
28,Zubat,,
29,Golbat,,
30,Crobat,,
31,Geodude,,
32,Graveler,,
33,Golem,,
34,Onix,,
35,Steelix,,
36,Cranidos,,
37,Rampardos,,
38,Shieldon,,
39,Bastiodon,,
40,Machop,,
41,Machoke,,
42,Machamp,,
43,Psyduck,,
44,Golduck,,
45,Burmy,,
46,Wormadam,,
47,Mothim,,
48,Wurmple,,
49,Silcoon,,
50,Beautifly,,
51,Cascoon,,
52,Dustox,,
53,Combee,,
54,Vespiquen,,
55,Pachirisu,,
56,Buizel,,
57,Floatzel,,
58,Cherubi,,
59,Cherrim,,
60,Shellos,,
61,Gastrodon,,
62,Heracross,,
63,Aipom,,
64,Ambipom,,
65,Drifloon,,
66,Drifblim,,
67,Buneary,,
68,Lopunny,,
69,Gastly,,
70,Haunter,,
71,Gengar,,
72,Misdreavus,,
73,Mismagius,,
74,Murkrow,,
75,Honchkrow,,
76,Glameow,,
77,Purugly,,
78,Goldeen,,
79,Seaking,,
80,Barboach,,
81,Whiscash,,
82,Chingling,,
83,Chimecho,,
84,Stunky,,
85,Skuntank,,
86,Meditite,,
87,Medicham,,
88,Bronzor,,
89,Bronzong,,
90,Ponyta,,
91,Rapidash,,
92,Bonsly,,
93,Sudowoodo,,
94,Mime Jr.,,
95,Mr. Mime,,
96,Happiny,,
97,Chansey,,
98,Blissey,,
99,Cleffa,,
100,Clefairy,,
101,Clefable,,
102,Chatot,,
103,Pichu,,
104,Pikachu,,
105,Raichu,,
106,Hoothoot,,
107,Noctowl,,
108,Spiritomb,,
109,Gible,,
110,Gabite,,
111,Garchomp,,
112,Munchlax,,
113,Snorlax,,
114,Unown,,
115,Riolu,,
116,Lucario,,
117,Wooper,,
118,Quagsire,,
119,Wingull,,
120,Pelipper,,
121,Girafarig,,
122,Hippopotas,,
123,Hippowdon,,
124,Azurill,,
125,Marill,,
126,Azumarill,,
127,Skorupi,,
128,Drapion,,
129,Croagunk,,
130,Toxicroak,,
131,Carnivine,,
132,Remoraid,,
133,Octillery,,
134,Finneon,,
135,Lumineon,,
136,Tentacool,,
137,Tentacruel,,
138,Feebas,,
139,Milotic,,
140,Mantyke,,
141,Mantine,,
142,Snover,,
143,Abomasnow,,
144,Sneasel,,
145,Weavile,,
146,Uxie,,
147,Mesprit,,
148,Azelf,,
149,Dialga,,
150,Palkia,,
151,Manaphy,,
1 dexNumber pokemon form notes
2 1 Turtwig
3 2 Grotle
4 3 Torterra
5 4 Chimchar
6 5 Monferno
7 6 Infernape
8 7 Piplup
9 8 Prinplup
10 9 Empoleon
11 10 Starly
12 11 Staravia
13 12 Staraptor
14 13 Bidoof
15 14 Bibarel
16 15 Kricketot
17 16 Kricketune
18 17 Shinx
19 18 Luxio
20 19 Luxray
21 20 Abra
22 21 Kadabra
23 22 Alakazam
24 23 Magikarp
25 24 Gyarados
26 25 Budew
27 26 Roselia
28 27 Roserade
29 28 Zubat
30 29 Golbat
31 30 Crobat
32 31 Geodude
33 32 Graveler
34 33 Golem
35 34 Onix
36 35 Steelix
37 36 Cranidos
38 37 Rampardos
39 38 Shieldon
40 39 Bastiodon
41 40 Machop
42 41 Machoke
43 42 Machamp
44 43 Psyduck
45 44 Golduck
46 45 Burmy
47 46 Wormadam
48 47 Mothim
49 48 Wurmple
50 49 Silcoon
51 50 Beautifly
52 51 Cascoon
53 52 Dustox
54 53 Combee
55 54 Vespiquen
56 55 Pachirisu
57 56 Buizel
58 57 Floatzel
59 58 Cherubi
60 59 Cherrim
61 60 Shellos
62 61 Gastrodon
63 62 Heracross
64 63 Aipom
65 64 Ambipom
66 65 Drifloon
67 66 Drifblim
68 67 Buneary
69 68 Lopunny
70 69 Gastly
71 70 Haunter
72 71 Gengar
73 72 Misdreavus
74 73 Mismagius
75 74 Murkrow
76 75 Honchkrow
77 76 Glameow
78 77 Purugly
79 78 Goldeen
80 79 Seaking
81 80 Barboach
82 81 Whiscash
83 82 Chingling
84 83 Chimecho
85 84 Stunky
86 85 Skuntank
87 86 Meditite
88 87 Medicham
89 88 Bronzor
90 89 Bronzong
91 90 Ponyta
92 91 Rapidash
93 92 Bonsly
94 93 Sudowoodo
95 94 Mime Jr.
96 95 Mr. Mime
97 96 Happiny
98 97 Chansey
99 98 Blissey
100 99 Cleffa
101 100 Clefairy
102 101 Clefable
103 102 Chatot
104 103 Pichu
105 104 Pikachu
106 105 Raichu
107 106 Hoothoot
108 107 Noctowl
109 108 Spiritomb
110 109 Gible
111 110 Gabite
112 111 Garchomp
113 112 Munchlax
114 113 Snorlax
115 114 Unown
116 115 Riolu
117 116 Lucario
118 117 Wooper
119 118 Quagsire
120 119 Wingull
121 120 Pelipper
122 121 Girafarig
123 122 Hippopotas
124 123 Hippowdon
125 124 Azurill
126 125 Marill
127 126 Azumarill
128 127 Skorupi
129 128 Drapion
130 129 Croagunk
131 130 Toxicroak
132 131 Carnivine
133 132 Remoraid
134 133 Octillery
135 134 Finneon
136 135 Lumineon
137 136 Tentacool
138 137 Tentacruel
139 138 Feebas
140 139 Milotic
141 140 Mantyke
142 141 Mantine
143 142 Snover
144 143 Abomasnow
145 144 Sneasel
146 145 Weavile
147 146 Uxie
148 147 Mesprit
149 148 Azelf
150 149 Dialga
151 150 Palkia
152 151 Manaphy
@@ -0,0 +1,152 @@
dexNumber,pokemon,form,notes
1,Bulbasaur,,
2,Ivysaur,,
3,Venusaur,,
4,Charmander,,
5,Charmeleon,,
6,Charizard,,
7,Squirtle,,
8,Wartortle,,
9,Blastoise,,
10,Caterpie,,
11,Metapod,,
12,Butterfree,,
13,Weedle,,
14,Kakuna,,
15,Beedrill,,
16,Pidgey,,
17,Pidgeotto,,
18,Pidgeot,,
19,Rattata,,
20,Raticate,,
21,Spearow,,
22,Fearow,,
23,Ekans,,
24,Arbok,,
25,Pikachu,,
26,Raichu,,
27,Sandshrew,,
28,Sandslash,,
29,Nidoran♀,,
30,Nidorina,,
31,Nidoqueen,,
32,Nidoran♂,,
33,Nidorino,,
34,Nidoking,,
35,Clefairy,,
36,Clefable,,
37,Vulpix,,
38,Ninetales,,
39,Jigglypuff,,
40,Wigglytuff,,
41,Zubat,,
42,Golbat,,
43,Oddish,,
44,Gloom,,
45,Vileplume,,
46,Paras,,
47,Parasect,,
48,Venonat,,
49,Venomoth,,
50,Diglett,,
51,Dugtrio,,
52,Meowth,,
53,Persian,,
54,Psyduck,,
55,Golduck,,
56,Mankey,,
57,Primeape,,
58,Growlithe,,
59,Arcanine,,
60,Poliwag,,
61,Poliwhirl,,
62,Poliwrath,,
63,Abra,,
64,Kadabra,,
65,Alakazam,,
66,Machop,,
67,Machoke,,
68,Machamp,,
69,Bellsprout,,
70,Weepinbell,,
71,Victreebel,,
72,Tentacool,,
73,Tentacruel,,
74,Geodude,,
75,Graveler,,
76,Golem,,
77,Ponyta,,
78,Rapidash,,
79,Slowpoke,,
80,Slowbro,,
81,Magnemite,,
82,Magneton,,
83,Farfetchd,,
84,Doduo,,
85,Dodrio,,
86,Seel,,
87,Dewgong,,
88,Grimer,,
89,Muk,,
90,Shellder,,
91,Cloyster,,
92,Gastly,,
93,Haunter,,
94,Gengar,,
95,Onix,,
96,Drowzee,,
97,Hypno,,
98,Krabby,,
99,Kingler,,
100,Voltorb,,
101,Electrode,,
102,Exeggcute,,
103,Exeggutor,,
104,Cubone,,
105,Marowak,,
106,Hitmonlee,,
107,Hitmonchan,,
108,Lickitung,,
109,Koffing,,
110,Weezing,,
111,Rhyhorn,,
112,Rhydon,,
113,Chansey,,
114,Tangela,,
115,Kangaskhan,,
116,Horsea,,
117,Seadra,,
118,Goldeen,,
119,Seaking,,
120,Staryu,,
121,Starmie,,
122,Mr. Mime,,
123,Scyther,,
124,Jynx,,
125,Electabuzz,,
126,Magmar,,
127,Pinsir,,
128,Tauros,,
129,Magikarp,,
130,Gyarados,,
131,Lapras,,
132,Ditto,,
133,Eevee,,
134,Vaporeon,,
135,Jolteon,,
136,Flareon,,
137,Porygon,,
138,Omanyte,,
139,Omastar,,
140,Kabuto,,
141,Kabutops,,
142,Aerodactyl,,
143,Snorlax,,
144,Articuno,,
145,Zapdos,,
146,Moltres,,
147,Dratini,,
148,Dragonair,,
149,Dragonite,,
150,Mewtwo,,
151,Mew,,
1 dexNumber pokemon form notes
2 1 Bulbasaur
3 2 Ivysaur
4 3 Venusaur
5 4 Charmander
6 5 Charmeleon
7 6 Charizard
8 7 Squirtle
9 8 Wartortle
10 9 Blastoise
11 10 Caterpie
12 11 Metapod
13 12 Butterfree
14 13 Weedle
15 14 Kakuna
16 15 Beedrill
17 16 Pidgey
18 17 Pidgeotto
19 18 Pidgeot
20 19 Rattata
21 20 Raticate
22 21 Spearow
23 22 Fearow
24 23 Ekans
25 24 Arbok
26 25 Pikachu
27 26 Raichu
28 27 Sandshrew
29 28 Sandslash
30 29 Nidoran♀
31 30 Nidorina
32 31 Nidoqueen
33 32 Nidoran♂
34 33 Nidorino
35 34 Nidoking
36 35 Clefairy
37 36 Clefable
38 37 Vulpix
39 38 Ninetales
40 39 Jigglypuff
41 40 Wigglytuff
42 41 Zubat
43 42 Golbat
44 43 Oddish
45 44 Gloom
46 45 Vileplume
47 46 Paras
48 47 Parasect
49 48 Venonat
50 49 Venomoth
51 50 Diglett
52 51 Dugtrio
53 52 Meowth
54 53 Persian
55 54 Psyduck
56 55 Golduck
57 56 Mankey
58 57 Primeape
59 58 Growlithe
60 59 Arcanine
61 60 Poliwag
62 61 Poliwhirl
63 62 Poliwrath
64 63 Abra
65 64 Kadabra
66 65 Alakazam
67 66 Machop
68 67 Machoke
69 68 Machamp
70 69 Bellsprout
71 70 Weepinbell
72 71 Victreebel
73 72 Tentacool
74 73 Tentacruel
75 74 Geodude
76 75 Graveler
77 76 Golem
78 77 Ponyta
79 78 Rapidash
80 79 Slowpoke
81 80 Slowbro
82 81 Magnemite
83 82 Magneton
84 83 Farfetch’d
85 84 Doduo
86 85 Dodrio
87 86 Seel
88 87 Dewgong
89 88 Grimer
90 89 Muk
91 90 Shellder
92 91 Cloyster
93 92 Gastly
94 93 Haunter
95 94 Gengar
96 95 Onix
97 96 Drowzee
98 97 Hypno
99 98 Krabby
100 99 Kingler
101 100 Voltorb
102 101 Electrode
103 102 Exeggcute
104 103 Exeggutor
105 104 Cubone
106 105 Marowak
107 106 Hitmonlee
108 107 Hitmonchan
109 108 Lickitung
110 109 Koffing
111 110 Weezing
112 111 Rhyhorn
113 112 Rhydon
114 113 Chansey
115 114 Tangela
116 115 Kangaskhan
117 116 Horsea
118 117 Seadra
119 118 Goldeen
120 119 Seaking
121 120 Staryu
122 121 Starmie
123 122 Mr. Mime
124 123 Scyther
125 124 Jynx
126 125 Electabuzz
127 126 Magmar
128 127 Pinsir
129 128 Tauros
130 129 Magikarp
131 130 Gyarados
132 131 Lapras
133 132 Ditto
134 133 Eevee
135 134 Vaporeon
136 135 Jolteon
137 136 Flareon
138 137 Porygon
139 138 Omanyte
140 139 Omastar
141 140 Kabuto
142 141 Kabutops
143 142 Aerodactyl
144 143 Snorlax
145 144 Articuno
146 145 Zapdos
147 146 Moltres
148 147 Dratini
149 148 Dragonair
150 149 Dragonite
151 150 Mewtwo
152 151 Mew
@@ -0,0 +1,252 @@
dexNumber,pokemon,form,notes
1,Chikorita,,
2,Bayleef,,
3,Meganium,,
4,Cyndaquil,,
5,Quilava,,
6,Typhlosion,,
7,Totodile,,
8,Croconaw,,
9,Feraligatr,,
10,Pidgey,,
11,Pidgeotto,,
12,Pidgeot,,
13,Spearow,,
14,Fearow,,
15,Hoothoot,,
16,Noctowl,,
17,Rattata,,
18,Raticate,,
19,Sentret,,
20,Furret,,
21,Pichu,,
22,Pikachu,,
23,Raichu,,
24,Caterpie,,
25,Metapod,,
26,Butterfree,,
27,Weedle,,
28,Kakuna,,
29,Beedrill,,
30,Ledyba,,
31,Ledian,,
32,Spinarak,,
33,Ariados,,
34,Geodude,,
35,Graveler,,
36,Golem,,
37,Zubat,,
38,Golbat,,
39,Crobat,,
40,Cleffa,,
41,Clefairy,,
42,Clefable,,
43,Igglybuff,,
44,Jigglypuff,,
45,Wigglytuff,,
46,Togepi,,
47,Togetic,,
48,Sandshrew,,
49,Sandslash,,
50,Ekans,,
51,Arbok,,
52,Dunsparce,,
53,Mareep,,
54,Flaaffy,,
55,Ampharos,,
56,Wooper,,
57,Quagsire,,
58,Gastly,,
59,Haunter,,
60,Gengar,,
61,Unown,,
62,Onix,,
63,Steelix,,
64,Bellsprout,,
65,Weepinbell,,
66,Victreebel,,
67,Hoppip,,
68,Skiploom,,
69,Jumpluff,,
70,Paras,,
71,Parasect,,
72,Poliwag,,
73,Poliwhirl,,
74,Poliwrath,,
75,Politoed,,
76,Magikarp,,
77,Gyarados,,
78,Goldeen,,
79,Seaking,,
80,Slowpoke,,
81,Slowbro,,
82,Slowking,,
83,Oddish,,
84,Gloom,,
85,Vileplume,,
86,Bellossom,,
87,Drowzee,,
88,Hypno,,
89,Abra,,
90,Kadabra,,
91,Alakazam,,
92,Ditto,,
93,Pineco,,
94,Forretress,,
95,Nidoran♀,,
96,Nidorina,,
97,Nidoqueen,,
98,Nidoran♂,,
99,Nidorino,,
100,Nidoking,,
101,Yanma,,
102,Sunkern,,
103,Sunflora,,
104,Exeggcute,,
105,Exeggutor,,
106,Sudowoodo,,
107,Wobbuffet,,
108,Venonat,,
109,Venomoth,,
110,Scyther,,
111,Scizor,,
112,Pinsir,,
113,Heracross,,
114,Koffing,,
115,Weezing,,
116,Grimer,,
117,Muk,,
118,Magnemite,,
119,Magneton,,
120,Voltorb,,
121,Electrode,,
122,Aipom,,
123,Snubbull,,
124,Granbull,,
125,Vulpix,,
126,Ninetales,,
127,Growlithe,,
128,Arcanine,,
129,Stantler,,
130,Marill,,
131,Azumarill,,
132,Diglett,,
133,Dugtrio,,
134,Mankey,,
135,Primeape,,
136,Meowth,,
137,Persian,,
138,Psyduck,,
139,Golduck,,
140,Machop,,
141,Machoke,,
142,Machamp,,
143,Tyrogue,,
144,Hitmonlee,,
145,Hitmonchan,,
146,Hitmontop,,
147,Girafarig,,
148,Tauros,,
149,Miltank,,
150,Magby,,
151,Magmar,,
152,Smoochum,,
153,Jynx,,
154,Elekid,,
155,Electabuzz,,
156,Mr. Mime,,
157,Smeargle,,
158,Farfetchd,,
159,Natu,,
160,Xatu,,
161,Qwilfish,,
162,Tentacool,,
163,Tentacruel,,
164,Krabby,,
165,Kingler,,
166,Shuckle,,
167,Staryu,,
168,Starmie,,
169,Shellder,,
170,Cloyster,,
171,Corsola,,
172,Remoraid,,
173,Octillery,,
174,Chinchou,,
175,Lanturn,,
176,Seel,,
177,Dewgong,,
178,Lickitung,,
179,Tangela,,
180,Eevee,,
181,Vaporeon,,
182,Jolteon,,
183,Flareon,,
184,Espeon,,
185,Umbreon,,
186,Horsea,,
187,Seadra,,
188,Kingdra,,
189,Gligar,,
190,Delibird,,
191,Swinub,,
192,Piloswine,,
193,Teddiursa,,
194,Ursaring,,
195,Phanpy,,
196,Donphan,,
197,Mantine,,
198,Skarmory,,
199,Doduo,,
200,Dodrio,,
201,Ponyta,,
202,Rapidash,,
203,Cubone,,
204,Marowak,,
205,Kangaskhan,,
206,Rhyhorn,,
207,Rhydon,,
208,Murkrow,,
209,Houndour,,
210,Houndoom,,
211,Slugma,,
212,Magcargo,,
213,Sneasel,,
214,Misdreavus,,
215,Porygon,,
216,Porygon2,,
217,Chansey,,
218,Blissey,,
219,Lapras,,
220,Omanyte,,
221,Omastar,,
222,Kabuto,,
223,Kabutops,,
224,Aerodactyl,,
225,Snorlax,,
226,Bulbasaur,,
227,Ivysaur,,
228,Venusaur,,
229,Charmander,,
230,Charmeleon,,
231,Charizard,,
232,Squirtle,,
233,Wartortle,,
234,Blastoise,,
235,Articuno,,
236,Zapdos,,
237,Moltres,,
238,Raikou,,
239,Entei,,
240,Suicune,,
241,Dratini,,
242,Dragonair,,
243,Dragonite,,
244,Larvitar,,
245,Pupitar,,
246,Tyranitar,,
247,Lugia,,
248,Ho-Oh,,
249,Mewtwo,,
250,Mew,,
251,Celebi,,
1 dexNumber pokemon form notes
2 1 Chikorita
3 2 Bayleef
4 3 Meganium
5 4 Cyndaquil
6 5 Quilava
7 6 Typhlosion
8 7 Totodile
9 8 Croconaw
10 9 Feraligatr
11 10 Pidgey
12 11 Pidgeotto
13 12 Pidgeot
14 13 Spearow
15 14 Fearow
16 15 Hoothoot
17 16 Noctowl
18 17 Rattata
19 18 Raticate
20 19 Sentret
21 20 Furret
22 21 Pichu
23 22 Pikachu
24 23 Raichu
25 24 Caterpie
26 25 Metapod
27 26 Butterfree
28 27 Weedle
29 28 Kakuna
30 29 Beedrill
31 30 Ledyba
32 31 Ledian
33 32 Spinarak
34 33 Ariados
35 34 Geodude
36 35 Graveler
37 36 Golem
38 37 Zubat
39 38 Golbat
40 39 Crobat
41 40 Cleffa
42 41 Clefairy
43 42 Clefable
44 43 Igglybuff
45 44 Jigglypuff
46 45 Wigglytuff
47 46 Togepi
48 47 Togetic
49 48 Sandshrew
50 49 Sandslash
51 50 Ekans
52 51 Arbok
53 52 Dunsparce
54 53 Mareep
55 54 Flaaffy
56 55 Ampharos
57 56 Wooper
58 57 Quagsire
59 58 Gastly
60 59 Haunter
61 60 Gengar
62 61 Unown
63 62 Onix
64 63 Steelix
65 64 Bellsprout
66 65 Weepinbell
67 66 Victreebel
68 67 Hoppip
69 68 Skiploom
70 69 Jumpluff
71 70 Paras
72 71 Parasect
73 72 Poliwag
74 73 Poliwhirl
75 74 Poliwrath
76 75 Politoed
77 76 Magikarp
78 77 Gyarados
79 78 Goldeen
80 79 Seaking
81 80 Slowpoke
82 81 Slowbro
83 82 Slowking
84 83 Oddish
85 84 Gloom
86 85 Vileplume
87 86 Bellossom
88 87 Drowzee
89 88 Hypno
90 89 Abra
91 90 Kadabra
92 91 Alakazam
93 92 Ditto
94 93 Pineco
95 94 Forretress
96 95 Nidoran♀
97 96 Nidorina
98 97 Nidoqueen
99 98 Nidoran♂
100 99 Nidorino
101 100 Nidoking
102 101 Yanma
103 102 Sunkern
104 103 Sunflora
105 104 Exeggcute
106 105 Exeggutor
107 106 Sudowoodo
108 107 Wobbuffet
109 108 Venonat
110 109 Venomoth
111 110 Scyther
112 111 Scizor
113 112 Pinsir
114 113 Heracross
115 114 Koffing
116 115 Weezing
117 116 Grimer
118 117 Muk
119 118 Magnemite
120 119 Magneton
121 120 Voltorb
122 121 Electrode
123 122 Aipom
124 123 Snubbull
125 124 Granbull
126 125 Vulpix
127 126 Ninetales
128 127 Growlithe
129 128 Arcanine
130 129 Stantler
131 130 Marill
132 131 Azumarill
133 132 Diglett
134 133 Dugtrio
135 134 Mankey
136 135 Primeape
137 136 Meowth
138 137 Persian
139 138 Psyduck
140 139 Golduck
141 140 Machop
142 141 Machoke
143 142 Machamp
144 143 Tyrogue
145 144 Hitmonlee
146 145 Hitmonchan
147 146 Hitmontop
148 147 Girafarig
149 148 Tauros
150 149 Miltank
151 150 Magby
152 151 Magmar
153 152 Smoochum
154 153 Jynx
155 154 Elekid
156 155 Electabuzz
157 156 Mr. Mime
158 157 Smeargle
159 158 Farfetch’d
160 159 Natu
161 160 Xatu
162 161 Qwilfish
163 162 Tentacool
164 163 Tentacruel
165 164 Krabby
166 165 Kingler
167 166 Shuckle
168 167 Staryu
169 168 Starmie
170 169 Shellder
171 170 Cloyster
172 171 Corsola
173 172 Remoraid
174 173 Octillery
175 174 Chinchou
176 175 Lanturn
177 176 Seel
178 177 Dewgong
179 178 Lickitung
180 179 Tangela
181 180 Eevee
182 181 Vaporeon
183 182 Jolteon
184 183 Flareon
185 184 Espeon
186 185 Umbreon
187 186 Horsea
188 187 Seadra
189 188 Kingdra
190 189 Gligar
191 190 Delibird
192 191 Swinub
193 192 Piloswine
194 193 Teddiursa
195 194 Ursaring
196 195 Phanpy
197 196 Donphan
198 197 Mantine
199 198 Skarmory
200 199 Doduo
201 200 Dodrio
202 201 Ponyta
203 202 Rapidash
204 203 Cubone
205 204 Marowak
206 205 Kangaskhan
207 206 Rhyhorn
208 207 Rhydon
209 208 Murkrow
210 209 Houndour
211 210 Houndoom
212 211 Slugma
213 212 Magcargo
214 213 Sneasel
215 214 Misdreavus
216 215 Porygon
217 216 Porygon2
218 217 Chansey
219 218 Blissey
220 219 Lapras
221 220 Omanyte
222 221 Omastar
223 222 Kabuto
224 223 Kabutops
225 224 Aerodactyl
226 225 Snorlax
227 226 Bulbasaur
228 227 Ivysaur
229 228 Venusaur
230 229 Charmander
231 230 Charmeleon
232 231 Charizard
233 232 Squirtle
234 233 Wartortle
235 234 Blastoise
236 235 Articuno
237 236 Zapdos
238 237 Moltres
239 238 Raikou
240 239 Entei
241 240 Suicune
242 241 Dratini
243 242 Dragonair
244 243 Dragonite
245 244 Larvitar
246 245 Pupitar
247 246 Tyranitar
248 247 Lugia
249 248 Ho-Oh
250 249 Mewtwo
251 250 Mew
252 251 Celebi
@@ -0,0 +1,257 @@
dexNumber,pokemon,form,notes
1,Chikorita,,
2,Bayleef,,
3,Meganium,,
4,Cyndaquil,,
5,Quilava,,
6,Typhlosion,,
7,Totodile,,
8,Croconaw,,
9,Feraligatr,,
10,Pidgey,,
11,Pidgeotto,,
12,Pidgeot,,
13,Spearow,,
14,Fearow,,
15,Hoothoot,,
16,Noctowl,,
17,Rattata,,
18,Raticate,,
19,Sentret,,
20,Furret,,
21,Pichu,,
22,Pikachu,,
23,Raichu,,
24,Caterpie,,
25,Metapod,,
26,Butterfree,,
27,Weedle,,
28,Kakuna,,
29,Beedrill,,
30,Ledyba,,
31,Ledian,,
32,Spinarak,,
33,Ariados,,
34,Geodude,,
35,Graveler,,
36,Golem,,
37,Zubat,,
38,Golbat,,
39,Crobat,,
40,Cleffa,,
41,Clefairy,,
42,Clefable,,
43,Igglybuff,,
44,Jigglypuff,,
45,Wigglytuff,,
46,Togepi,,
47,Togetic,,
48,Sandshrew,,
49,Sandslash,,
50,Ekans,,
51,Arbok,,
52,Dunsparce,,
53,Mareep,,
54,Flaaffy,,
55,Ampharos,,
56,Wooper,,
57,Quagsire,,
58,Gastly,,
59,Haunter,,
60,Gengar,,
61,Unown,,
62,Onix,,
63,Steelix,,
64,Bellsprout,,
65,Weepinbell,,
66,Victreebel,,
67,Hoppip,,
68,Skiploom,,
69,Jumpluff,,
70,Paras,,
71,Parasect,,
72,Poliwag,,
73,Poliwhirl,,
74,Poliwrath,,
75,Politoed,,
76,Magikarp,,
77,Gyarados,,
78,Goldeen,,
79,Seaking,,
80,Slowpoke,,
81,Slowbro,,
82,Slowking,,
83,Oddish,,
84,Gloom,,
85,Vileplume,,
86,Bellossom,,
87,Drowzee,,
88,Hypno,,
89,Abra,,
90,Kadabra,,
91,Alakazam,,
92,Ditto,,
93,Pineco,,
94,Forretress,,
95,Nidoran♀,,
96,Nidorina,,
97,Nidoqueen,,
98,Nidoran♂,,
99,Nidorino,,
100,Nidoking,,
101,Yanma,,
102,Yanmega,,
103,Sunkern,,
104,Sunflora,,
105,Exeggcute,,
106,Exeggutor,,
107,Sudowoodo,,
108,Wobbuffet,,
109,Venonat,,
110,Venomoth,,
111,Scyther,,
112,Scizor,,
113,Pinsir,,
114,Heracross,,
115,Koffing,,
116,Weezing,,
117,Grimer,,
118,Muk,,
119,Magnemite,,
120,Magneton,,
121,Voltorb,,
122,Electrode,,
123,Aipom,,
124,Ambipom,,
125,Snubbull,,
126,Granbull,,
127,Vulpix,,
128,Ninetales,,
129,Growlithe,,
130,Arcanine,,
131,Stantler,,
132,Marill,,
133,Azumarill,,
134,Diglett,,
135,Dugtrio,,
136,Mankey,,
137,Primeape,,
138,Meowth,,
139,Persian,,
140,Psyduck,,
141,Golduck,,
142,Machop,,
143,Machoke,,
144,Machamp,,
145,Tyrogue,,
146,Hitmonlee,,
147,Hitmonchan,,
148,Hitmontop,,
149,Girafarig,,
150,Tauros,,
151,Miltank,,
152,Magby,,
153,Magmar,,
154,Smoochum,,
155,Jynx,,
156,Elekid,,
157,Electabuzz,,
158,Mr. Mime,,
159,Smeargle,,
160,Farfetchd,,
161,Natu,,
162,Xatu,,
163,Qwilfish,,
164,Tentacool,,
165,Tentacruel,,
166,Krabby,,
167,Kingler,,
168,Shuckle,,
169,Staryu,,
170,Starmie,,
171,Shellder,,
172,Cloyster,,
173,Corsola,,
174,Remoraid,,
175,Octillery,,
176,Chinchou,,
177,Lanturn,,
178,Seel,,
179,Dewgong,,
180,Lickitung,,
181,Lickilicky,,
182,Tangela,,
183,Tangrowth,,
184,Eevee,,
185,Vaporeon,,
186,Jolteon,,
187,Flareon,,
188,Espeon,,
189,Umbreon,,
190,Horsea,,
191,Seadra,,
192,Kingdra,,
193,Gligar,,
194,Delibird,,
195,Swinub,,
196,Piloswine,,
197,Mamoswine,,
198,Teddiursa,,
199,Ursaring,,
200,Phanpy,,
201,Donphan,,
202,Mantine,,
203,Skarmory,,
204,Doduo,,
205,Dodrio,,
206,Ponyta,,
207,Rapidash,,
208,Cubone,,
209,Marowak,,
210,Kangaskhan,,
211,Rhyhorn,,
212,Rhydon,,
213,Murkrow,,
214,Houndour,,
215,Houndoom,,
216,Slugma,,
217,Magcargo,,
218,Sneasel,,
219,Misdreavus,,
220,Porygon,,
221,Porygon2,,
222,Chansey,,
223,Blissey,,
224,Lapras,,
225,Omanyte,,
226,Omastar,,
227,Kabuto,,
228,Kabutops,,
229,Aerodactyl,,
230,Snorlax,,
231,Bulbasaur,,
232,Ivysaur,,
233,Venusaur,,
234,Charmander,,
235,Charmeleon,,
236,Charizard,,
237,Squirtle,,
238,Wartortle,,
239,Blastoise,,
240,Articuno,,
241,Zapdos,,
242,Moltres,,
243,Raikou,,
244,Entei,,
245,Suicune,,
246,Dratini,,
247,Dragonair,,
248,Dragonite,,
249,Larvitar,,
250,Pupitar,,
251,Tyranitar,,
252,Lugia,,
253,Ho-Oh,,
254,Mewtwo,,
255,Mew,,
256,Celebi,,
1 dexNumber pokemon form notes
2 1 Chikorita
3 2 Bayleef
4 3 Meganium
5 4 Cyndaquil
6 5 Quilava
7 6 Typhlosion
8 7 Totodile
9 8 Croconaw
10 9 Feraligatr
11 10 Pidgey
12 11 Pidgeotto
13 12 Pidgeot
14 13 Spearow
15 14 Fearow
16 15 Hoothoot
17 16 Noctowl
18 17 Rattata
19 18 Raticate
20 19 Sentret
21 20 Furret
22 21 Pichu
23 22 Pikachu
24 23 Raichu
25 24 Caterpie
26 25 Metapod
27 26 Butterfree
28 27 Weedle
29 28 Kakuna
30 29 Beedrill
31 30 Ledyba
32 31 Ledian
33 32 Spinarak
34 33 Ariados
35 34 Geodude
36 35 Graveler
37 36 Golem
38 37 Zubat
39 38 Golbat
40 39 Crobat
41 40 Cleffa
42 41 Clefairy
43 42 Clefable
44 43 Igglybuff
45 44 Jigglypuff
46 45 Wigglytuff
47 46 Togepi
48 47 Togetic
49 48 Sandshrew
50 49 Sandslash
51 50 Ekans
52 51 Arbok
53 52 Dunsparce
54 53 Mareep
55 54 Flaaffy
56 55 Ampharos
57 56 Wooper
58 57 Quagsire
59 58 Gastly
60 59 Haunter
61 60 Gengar
62 61 Unown
63 62 Onix
64 63 Steelix
65 64 Bellsprout
66 65 Weepinbell
67 66 Victreebel
68 67 Hoppip
69 68 Skiploom
70 69 Jumpluff
71 70 Paras
72 71 Parasect
73 72 Poliwag
74 73 Poliwhirl
75 74 Poliwrath
76 75 Politoed
77 76 Magikarp
78 77 Gyarados
79 78 Goldeen
80 79 Seaking
81 80 Slowpoke
82 81 Slowbro
83 82 Slowking
84 83 Oddish
85 84 Gloom
86 85 Vileplume
87 86 Bellossom
88 87 Drowzee
89 88 Hypno
90 89 Abra
91 90 Kadabra
92 91 Alakazam
93 92 Ditto
94 93 Pineco
95 94 Forretress
96 95 Nidoran♀
97 96 Nidorina
98 97 Nidoqueen
99 98 Nidoran♂
100 99 Nidorino
101 100 Nidoking
102 101 Yanma
103 102 Yanmega
104 103 Sunkern
105 104 Sunflora
106 105 Exeggcute
107 106 Exeggutor
108 107 Sudowoodo
109 108 Wobbuffet
110 109 Venonat
111 110 Venomoth
112 111 Scyther
113 112 Scizor
114 113 Pinsir
115 114 Heracross
116 115 Koffing
117 116 Weezing
118 117 Grimer
119 118 Muk
120 119 Magnemite
121 120 Magneton
122 121 Voltorb
123 122 Electrode
124 123 Aipom
125 124 Ambipom
126 125 Snubbull
127 126 Granbull
128 127 Vulpix
129 128 Ninetales
130 129 Growlithe
131 130 Arcanine
132 131 Stantler
133 132 Marill
134 133 Azumarill
135 134 Diglett
136 135 Dugtrio
137 136 Mankey
138 137 Primeape
139 138 Meowth
140 139 Persian
141 140 Psyduck
142 141 Golduck
143 142 Machop
144 143 Machoke
145 144 Machamp
146 145 Tyrogue
147 146 Hitmonlee
148 147 Hitmonchan
149 148 Hitmontop
150 149 Girafarig
151 150 Tauros
152 151 Miltank
153 152 Magby
154 153 Magmar
155 154 Smoochum
156 155 Jynx
157 156 Elekid
158 157 Electabuzz
159 158 Mr. Mime
160 159 Smeargle
161 160 Farfetch’d
162 161 Natu
163 162 Xatu
164 163 Qwilfish
165 164 Tentacool
166 165 Tentacruel
167 166 Krabby
168 167 Kingler
169 168 Shuckle
170 169 Staryu
171 170 Starmie
172 171 Shellder
173 172 Cloyster
174 173 Corsola
175 174 Remoraid
176 175 Octillery
177 176 Chinchou
178 177 Lanturn
179 178 Seel
180 179 Dewgong
181 180 Lickitung
182 181 Lickilicky
183 182 Tangela
184 183 Tangrowth
185 184 Eevee
186 185 Vaporeon
187 186 Jolteon
188 187 Flareon
189 188 Espeon
190 189 Umbreon
191 190 Horsea
192 191 Seadra
193 192 Kingdra
194 193 Gligar
195 194 Delibird
196 195 Swinub
197 196 Piloswine
198 197 Mamoswine
199 198 Teddiursa
200 199 Ursaring
201 200 Phanpy
202 201 Donphan
203 202 Mantine
204 203 Skarmory
205 204 Doduo
206 205 Dodrio
207 206 Ponyta
208 207 Rapidash
209 208 Cubone
210 209 Marowak
211 210 Kangaskhan
212 211 Rhyhorn
213 212 Rhydon
214 213 Murkrow
215 214 Houndour
216 215 Houndoom
217 216 Slugma
218 217 Magcargo
219 218 Sneasel
220 219 Misdreavus
221 220 Porygon
222 221 Porygon2
223 222 Chansey
224 223 Blissey
225 224 Lapras
226 225 Omanyte
227 226 Omastar
228 227 Kabuto
229 228 Kabutops
230 229 Aerodactyl
231 230 Snorlax
232 231 Bulbasaur
233 232 Ivysaur
234 233 Venusaur
235 234 Charmander
236 235 Charmeleon
237 236 Charizard
238 237 Squirtle
239 238 Wartortle
240 239 Blastoise
241 240 Articuno
242 241 Zapdos
243 242 Moltres
244 243 Raikou
245 244 Entei
246 245 Suicune
247 246 Dratini
248 247 Dragonair
249 248 Dragonite
250 249 Larvitar
251 250 Pupitar
252 251 Tyranitar
253 252 Lugia
254 253 Ho-Oh
255 254 Mewtwo
256 255 Mew
257 256 Celebi
@@ -0,0 +1,243 @@
dexNumber,pokemon,form,notes
1,Rowlet,,
2,Dartrix,,
3,Decidueye,,
4,Cyndaquil,,
5,Quilava,,
6,Typhlosion,,
7,Oshawott,,
8,Dewott,,
9,Samurott,,
10,Bidoof,,
11,Bibarel,,
12,Starly,,
13,Staravia,,
14,Staraptor,,
15,Shinx,,
16,Luxio,,
17,Luxray,,
18,Wurmple,,
19,Silcoon,,
20,Beautifly,,
21,Cascoon,,
22,Dustox,,
23,Ponyta,,
24,Rapidash,,
25,Eevee,,
26,Vaporeon,,
27,Jolteon,,
28,Flareon,,
29,Espeon,,
30,Umbreon,,
31,Leafeon,,
32,Glaceon,,
33,Sylveon,,
34,Zubat,,
35,Golbat,,
36,Crobat,,
37,Drifloon,,
38,Drifblim,,
39,Kricketot,,
40,Kricketune,,
41,Buizel,,
42,Floatzel,,
43,Burmy,,
44,Wormadam,,
45,Mothim,,
46,Geodude,,
47,Graveler,,
48,Golem,,
49,Stantler,,
50,Wyrdeer,,
51,Munchlax,,
52,Snorlax,,
53,Paras,,
54,Parasect,,
55,Pichu,,
56,Pikachu,,
57,Raichu,,
58,Abra,,
59,Kadabra,,
60,Alakazam,,
61,Chimchar,,
62,Monferno,,
63,Infernape,,
64,Buneary,,
65,Lopunny,,
66,Cherubi,,
67,Cherrim,,
68,Psyduck,,
69,Golduck,,
70,Combee,,
71,Vespiquen,,
72,Scyther,,
73,Kleavor,,
74,Scizor,,
75,Heracross,,
76,Mime Jr.,,
77,Mr. Mime,,
78,Aipom,,
79,Ambipom,,
80,Magikarp,,
81,Gyarados,,
82,Shellos,,
83,Gastrodon,,
84,Qwilfish,,
85,Overqwil,,
86,Happiny,,
87,Chansey,,
88,Blissey,,
89,Budew,,
90,Roselia,,
91,Roserade,,
92,Carnivine,,
93,Petilil,,
94,Lilligant,,
95,Tangela,,
96,Tangrowth,,
97,Barboach,,
98,Whiscash,,
99,Croagunk,,
100,Toxicroak,,
101,Ralts,,
102,Kirlia,,
103,Gardevoir,,
104,Gallade,,
105,Yanma,,
106,Yanmega,,
107,Hippopotas,,
108,Hippowdon,,
109,Pachirisu,,
110,Stunky,,
111,Skuntank,,
112,Teddiursa,,
113,Ursaring,,
114,Ursaluna,,
115,Goomy,,
116,Sliggoo,,
117,Goodra,,
118,Onix,,
119,Steelix,,
120,Rhyhorn,,
121,Rhydon,,
122,Rhyperior,,
123,Bonsly,,
124,Sudowoodo,,
125,Lickitung,,
126,Lickilicky,,
127,Togepi,,
128,Togetic,,
129,Togekiss,,
130,Turtwig,,
131,Grotle,,
132,Torterra,,
133,Porygon,,
134,Porygon2,,
135,Porygon-Z,,
136,Gastly,,
137,Haunter,,
138,Gengar,,
139,Spiritomb,,
140,Murkrow,,
141,Honchkrow,,
142,Unown,,
143,Spheal,,
144,Sealeo,,
145,Walrein,,
146,Remoraid,,
147,Octillery,,
148,Skorupi,,
149,Drapion,,
150,Growlithe,,
151,Arcanine,,
152,Glameow,,
153,Purugly,,
154,Machop,,
155,Machoke,,
156,Machamp,,
157,Chatot,,
158,Duskull,,
159,Dusclops,,
160,Dusknoir,,
161,Piplup,,
162,Prinplup,,
163,Empoleon,,
164,Mantyke,,
165,Mantine,,
166,Basculin,,
167,Basculegion,,
168,Vulpix,,
169,Ninetales,,
170,Tentacool,,
171,Tentacruel,,
172,Finneon,,
173,Lumineon,,
174,Magby,,
175,Magmar,,
176,Magmortar,,
177,Magnemite,,
178,Magneton,,
179,Magnezone,,
180,Bronzor,,
181,Bronzong,,
182,Elekid,,
183,Electabuzz,,
184,Electivire,,
185,Gligar,,
186,Gliscor,,
187,Gible,,
188,Gabite,,
189,Garchomp,,
190,Nosepass,,
191,Probopass,,
192,Voltorb,,
193,Electrode,,
194,Rotom,,
195,Chingling,,
196,Chimecho,,
197,Misdreavus,,
198,Mismagius,,
199,Cleffa,,
200,Clefairy,,
201,Clefable,,
202,Sneasel,,
203,Sneasler,,
204,Weavile,,
205,Snorunt,,
206,Glalie,,
207,Froslass,,
208,Cranidos,,
209,Rampardos,,
210,Shieldon,,
211,Bastiodon,,
212,Swinub,,
213,Piloswine,,
214,Mamoswine,,
215,Bergmite,,
216,Avalugg,,
217,Snover,,
218,Abomasnow,,
219,Zorua,,
220,Zoroark,,
221,Rufflet,,
222,Braviary,,
223,Riolu,,
224,Lucario,,
225,Uxie,,
226,Mesprit,,
227,Azelf,,
228,Heatran,,
229,Regigigas,,
230,Cresselia,,
231,Tornadus,,
232,Thundurus,,
233,Landorus,,
234,Enamorus,,
235,Dialga,,
236,Palkia,,
237,Giratina,,
238,Arceus,,
239,Phione,,
240,Manaphy,,
241,Shaymin,,
242,Darkrai,,
1 dexNumber pokemon form notes
2 1 Rowlet
3 2 Dartrix
4 3 Decidueye
5 4 Cyndaquil
6 5 Quilava
7 6 Typhlosion
8 7 Oshawott
9 8 Dewott
10 9 Samurott
11 10 Bidoof
12 11 Bibarel
13 12 Starly
14 13 Staravia
15 14 Staraptor
16 15 Shinx
17 16 Luxio
18 17 Luxray
19 18 Wurmple
20 19 Silcoon
21 20 Beautifly
22 21 Cascoon
23 22 Dustox
24 23 Ponyta
25 24 Rapidash
26 25 Eevee
27 26 Vaporeon
28 27 Jolteon
29 28 Flareon
30 29 Espeon
31 30 Umbreon
32 31 Leafeon
33 32 Glaceon
34 33 Sylveon
35 34 Zubat
36 35 Golbat
37 36 Crobat
38 37 Drifloon
39 38 Drifblim
40 39 Kricketot
41 40 Kricketune
42 41 Buizel
43 42 Floatzel
44 43 Burmy
45 44 Wormadam
46 45 Mothim
47 46 Geodude
48 47 Graveler
49 48 Golem
50 49 Stantler
51 50 Wyrdeer
52 51 Munchlax
53 52 Snorlax
54 53 Paras
55 54 Parasect
56 55 Pichu
57 56 Pikachu
58 57 Raichu
59 58 Abra
60 59 Kadabra
61 60 Alakazam
62 61 Chimchar
63 62 Monferno
64 63 Infernape
65 64 Buneary
66 65 Lopunny
67 66 Cherubi
68 67 Cherrim
69 68 Psyduck
70 69 Golduck
71 70 Combee
72 71 Vespiquen
73 72 Scyther
74 73 Kleavor
75 74 Scizor
76 75 Heracross
77 76 Mime Jr.
78 77 Mr. Mime
79 78 Aipom
80 79 Ambipom
81 80 Magikarp
82 81 Gyarados
83 82 Shellos
84 83 Gastrodon
85 84 Qwilfish
86 85 Overqwil
87 86 Happiny
88 87 Chansey
89 88 Blissey
90 89 Budew
91 90 Roselia
92 91 Roserade
93 92 Carnivine
94 93 Petilil
95 94 Lilligant
96 95 Tangela
97 96 Tangrowth
98 97 Barboach
99 98 Whiscash
100 99 Croagunk
101 100 Toxicroak
102 101 Ralts
103 102 Kirlia
104 103 Gardevoir
105 104 Gallade
106 105 Yanma
107 106 Yanmega
108 107 Hippopotas
109 108 Hippowdon
110 109 Pachirisu
111 110 Stunky
112 111 Skuntank
113 112 Teddiursa
114 113 Ursaring
115 114 Ursaluna
116 115 Goomy
117 116 Sliggoo
118 117 Goodra
119 118 Onix
120 119 Steelix
121 120 Rhyhorn
122 121 Rhydon
123 122 Rhyperior
124 123 Bonsly
125 124 Sudowoodo
126 125 Lickitung
127 126 Lickilicky
128 127 Togepi
129 128 Togetic
130 129 Togekiss
131 130 Turtwig
132 131 Grotle
133 132 Torterra
134 133 Porygon
135 134 Porygon2
136 135 Porygon-Z
137 136 Gastly
138 137 Haunter
139 138 Gengar
140 139 Spiritomb
141 140 Murkrow
142 141 Honchkrow
143 142 Unown
144 143 Spheal
145 144 Sealeo
146 145 Walrein
147 146 Remoraid
148 147 Octillery
149 148 Skorupi
150 149 Drapion
151 150 Growlithe
152 151 Arcanine
153 152 Glameow
154 153 Purugly
155 154 Machop
156 155 Machoke
157 156 Machamp
158 157 Chatot
159 158 Duskull
160 159 Dusclops
161 160 Dusknoir
162 161 Piplup
163 162 Prinplup
164 163 Empoleon
165 164 Mantyke
166 165 Mantine
167 166 Basculin
168 167 Basculegion
169 168 Vulpix
170 169 Ninetales
171 170 Tentacool
172 171 Tentacruel
173 172 Finneon
174 173 Lumineon
175 174 Magby
176 175 Magmar
177 176 Magmortar
178 177 Magnemite
179 178 Magneton
180 179 Magnezone
181 180 Bronzor
182 181 Bronzong
183 182 Elekid
184 183 Electabuzz
185 184 Electivire
186 185 Gligar
187 186 Gliscor
188 187 Gible
189 188 Gabite
190 189 Garchomp
191 190 Nosepass
192 191 Probopass
193 192 Voltorb
194 193 Electrode
195 194 Rotom
196 195 Chingling
197 196 Chimecho
198 197 Misdreavus
199 198 Mismagius
200 199 Cleffa
201 200 Clefairy
202 201 Clefable
203 202 Sneasel
204 203 Sneasler
205 204 Weavile
206 205 Snorunt
207 206 Glalie
208 207 Froslass
209 208 Cranidos
210 209 Rampardos
211 210 Shieldon
212 211 Bastiodon
213 212 Swinub
214 213 Piloswine
215 214 Mamoswine
216 215 Bergmite
217 216 Avalugg
218 217 Snover
219 218 Abomasnow
220 219 Zorua
221 220 Zoroark
222 221 Rufflet
223 222 Braviary
224 223 Riolu
225 224 Lucario
226 225 Uxie
227 226 Mesprit
228 227 Azelf
229 228 Heatran
230 229 Regigigas
231 230 Cresselia
232 231 Tornadus
233 232 Thundurus
234 233 Landorus
235 234 Enamorus
236 235 Dialga
237 236 Palkia
238 237 Giratina
239 238 Arceus
240 239 Phione
241 240 Manaphy
242 241 Shaymin
243 242 Darkrai
@@ -0,0 +1,133 @@
dexNumber,pokemon,form,notes
1,Mankey,,
2,Primeape,,
3,Annihilape,,
4,Meowth,,
5,Persian,,
6,Perrserker,,
7,Farfetchd,,
8,Sirfetchd,,
9,Cubone,,
10,Marowak,,
11,Porygon,,
12,Porygon2,,
13,Porygon-Z,,
14,Capsakid,,
15,Scovillain,,
16,Tinkatink,,
17,Tinkatuff,,
18,Tinkaton,,
19,Cyclizar,,
20,Glimmet,,
21,Glimmora,,
22,Rotom,,
23,Greavard,,
24,Houndstone,,
25,Sandygast,,
26,Palossand,,
27,Kecleon,,
28,Flamigo,,
29,Cryogonal,,
30,Dondozo,,
31,Tatsugiri,,
32,Frigibax,,
33,Arctibax,,
34,Baxcalibur,,
35,Gimmighoul,,
36,Gholdengo,,
37,Qwilfish,,
38,Overqwil,,
39,Treecko,,
40,Grovyle,,
41,Sceptile,,
42,Torchic,,
43,Combusken,,
44,Blaziken,,
45,Mudkip,,
46,Marshtomp,,
47,Swampert,,
48,Feebas,,
49,Milotic,,
50,Chingling,,
51,Chimecho,,
52,Indeedee,,
53,Purrloin,,
54,Liepard,,
55,Munna,,
56,Musharna,,
57,Throh,,
58,Sawk,,
59,Yamask,,
60,Cofagrigus,,
61,Runerigus,,
62,Wimpod,,
63,Golisopod,,
64,Nickit,,
65,Thievul,,
66,Clobbopus,,
67,Grapploct,,
68,Mimikyu,,
69,Kleavor,,
70,Morpeko,,
71,Golett,,
72,Golurk,,
73,Rookidee,,
74,Corvisquire,,
75,Corviknight,,
76,Igglybuff,,
77,Jigglypuff,,
78,Wigglytuff,,
79,Fidough,,
80,Dachsbun,,
81,Starly,,
82,Staravia,,
83,Staraptor,,
84,Spoink,,
85,Grumpig,,
86,Squawkabilly,,
87,Crabrawler,,
88,Crabominable,,
89,Nacli,,
90,Naclstack,,
91,Garganacl,,
92,Gulpin,,
93,Swalot,,
94,Zubat,,
95,Golbat,,
96,Crobat,,
97,Charcadet,,
98,Armarouge,,
99,Ceruledge,,
100,Maschiff,,
101,Mabosstiff,,
102,Toxel,,
103,Toxtricity,,
104,Shroodle,,
105,Grafaiai,,
106,Zangoose,,
107,Seviper,,
108,Mime Jr.,,
109,Mr. Mime,,
110,Mr. Rime,,
111,Foongus,,
112,Amoonguss,,
113,Heatran,,
114,Volcanion,,
115,Cobalion,,
116,Terrakion,,
117,Virizion,,
118,Keldeo,,
119,Meloetta,,
120,Genesect,,
121,Hoopa,,
122,Marshadow,,
123,Meltan,,
124,Melmetal,,
125,Darkrai,,
126,Latias,,
127,Latios,,
128,Kyogre,,
129,Groudon,,
130,Rayquaza,,
131,Magearna,,
132,Zeraora,,
1 dexNumber pokemon form notes
2 1 Mankey
3 2 Primeape
4 3 Annihilape
5 4 Meowth
6 5 Persian
7 6 Perrserker
8 7 Farfetch’d
9 8 Sirfetch’d
10 9 Cubone
11 10 Marowak
12 11 Porygon
13 12 Porygon2
14 13 Porygon-Z
15 14 Capsakid
16 15 Scovillain
17 16 Tinkatink
18 17 Tinkatuff
19 18 Tinkaton
20 19 Cyclizar
21 20 Glimmet
22 21 Glimmora
23 22 Rotom
24 23 Greavard
25 24 Houndstone
26 25 Sandygast
27 26 Palossand
28 27 Kecleon
29 28 Flamigo
30 29 Cryogonal
31 30 Dondozo
32 31 Tatsugiri
33 32 Frigibax
34 33 Arctibax
35 34 Baxcalibur
36 35 Gimmighoul
37 36 Gholdengo
38 37 Qwilfish
39 38 Overqwil
40 39 Treecko
41 40 Grovyle
42 41 Sceptile
43 42 Torchic
44 43 Combusken
45 44 Blaziken
46 45 Mudkip
47 46 Marshtomp
48 47 Swampert
49 48 Feebas
50 49 Milotic
51 50 Chingling
52 51 Chimecho
53 52 Indeedee
54 53 Purrloin
55 54 Liepard
56 55 Munna
57 56 Musharna
58 57 Throh
59 58 Sawk
60 59 Yamask
61 60 Cofagrigus
62 61 Runerigus
63 62 Wimpod
64 63 Golisopod
65 64 Nickit
66 65 Thievul
67 66 Clobbopus
68 67 Grapploct
69 68 Mimikyu
70 69 Kleavor
71 70 Morpeko
72 71 Golett
73 72 Golurk
74 73 Rookidee
75 74 Corvisquire
76 75 Corviknight
77 76 Igglybuff
78 77 Jigglypuff
79 78 Wigglytuff
80 79 Fidough
81 80 Dachsbun
82 81 Starly
83 82 Staravia
84 83 Staraptor
85 84 Spoink
86 85 Grumpig
87 86 Squawkabilly
88 87 Crabrawler
89 88 Crabominable
90 89 Nacli
91 90 Naclstack
92 91 Garganacl
93 92 Gulpin
94 93 Swalot
95 94 Zubat
96 95 Golbat
97 96 Crobat
98 97 Charcadet
99 98 Armarouge
100 99 Ceruledge
101 100 Maschiff
102 101 Mabosstiff
103 102 Toxel
104 103 Toxtricity
105 104 Shroodle
106 105 Grafaiai
107 106 Zangoose
108 107 Seviper
109 108 Mime Jr.
110 109 Mr. Mime
111 110 Mr. Rime
112 111 Foongus
113 112 Amoonguss
114 113 Heatran
115 114 Volcanion
116 115 Cobalion
117 116 Terrakion
118 117 Virizion
119 118 Keldeo
120 119 Meloetta
121 120 Genesect
122 121 Hoopa
123 122 Marshadow
124 123 Meltan
125 124 Melmetal
126 125 Darkrai
127 126 Latias
128 127 Latios
129 128 Kyogre
130 129 Groudon
131 130 Rayquaza
132 131 Magearna
133 132 Zeraora
+233
View File
@@ -0,0 +1,233 @@
dexNumber,pokemon,form,notes
1,Chikorita,,
2,Bayleef,,
3,Meganium,,
4,Tepig,,
5,Pignite,,
6,Emboar,,
7,Totodile,,
8,Croconaw,,
9,Feraligatr,,
10,Fletchling,,
11,Fletchinder,,
12,Talonflame,,
13,Bunnelby,,
14,Diggersby,,
15,Scatterbug,,
16,Spewpa,,
17,Vivillon,,
18,Weedle,,
19,Kakuna,,
20,Beedrill,,
21,Pidgey,,
22,Pidgeotto,,
23,Pidgeot,,
24,Mareep,,
25,Flaaffy,,
26,Ampharos,,
27,Patrat,,
28,Watchog,,
29,Budew,,
30,Roselia,,
31,Roserade,,
32,Magikarp,,
33,Gyarados,,
34,Binacle,,
35,Barbaracle,,
36,Staryu,,
37,Starmie,,
38,Flabébé,,
39,Floette,,
40,Florges,,
41,Skiddo,,
42,Gogoat,,
43,Espurr,,
44,Meowstic,,
45,Litleo,,
46,Pyroar,,
47,Pancham,,
48,Pangoro,,
49,Trubbish,,
50,Garbodor,,
51,Dedenne,,
52,Pichu,,
53,Pikachu,,
54,Raichu,,
55,Cleffa,,
56,Clefairy,,
57,Clefable,,
58,Spinarak,,
59,Ariados,,
60,Ekans,,
61,Arbok,,
62,Abra,,
63,Kadabra,,
64,Alakazam,,
65,Gastly,,
66,Haunter,,
67,Gengar,,
68,Venipede,,
69,Whirlipede,,
70,Scolipede,,
71,Honedge,,
72,Doublade,,
73,Aegislash,,
74,Bellsprout,,
75,Weepinbell,,
76,Victreebel,,
77,Pansage,,
78,Simisage,,
79,Pansear,,
80,Simisear,,
81,Panpour,,
82,Simipour,,
83,Meditite,,
84,Medicham,,
85,Electrike,,
86,Manectric,,
87,Ralts,,
88,Kirlia,,
89,Gardevoir,,
90,Gallade,,
91,Houndour,,
92,Houndoom,,
93,Swablu,,
94,Altaria,,
95,Audino,,
96,Spritzee,,
97,Aromatisse,,
98,Swirlix,,
99,Slurpuff,,
100,Eevee,,
101,Vaporeon,,
102,Jolteon,,
103,Flareon,,
104,Espeon,,
105,Umbreon,,
106,Leafeon,,
107,Glaceon,,
108,Sylveon,,
109,Buneary,,
110,Lopunny,,
111,Shuppet,,
112,Banette,,
113,Vanillite,,
114,Vanillish,,
115,Vanilluxe,,
116,Numel,,
117,Camerupt,,
118,Hippopotas,,
119,Hippowdon,,
120,Drilbur,,
121,Excadrill,,
122,Sandile,,
123,Krokorok,,
124,Krookodile,,
125,Machop,,
126,Machoke,,
127,Machamp,,
128,Gible,,
129,Gabite,,
130,Garchomp,,
131,Carbink,,
132,Sableye,,
133,Mawile,,
134,Absol,,
135,Riolu,,
136,Lucario,,
137,Slowpoke,,
138,Slowbro,,
139,Slowking,,
140,Carvanha,,
141,Sharpedo,,
142,Tynamo,,
143,Eelektrik,,
144,Eelektross,,
145,Dratini,,
146,Dragonair,,
147,Dragonite,,
148,Bulbasaur,,
149,Ivysaur,,
150,Venusaur,,
151,Charmander,,
152,Charmeleon,,
153,Charizard,,
154,Squirtle,,
155,Wartortle,,
156,Blastoise,,
157,Stunfisk,,
158,Furfrou,,
159,Inkay,,
160,Malamar,,
161,Skrelp,,
162,Dragalge,,
163,Clauncher,,
164,Clawitzer,,
165,Goomy,,
166,Sliggoo,,
167,Goodra,,
168,Delibird,,
169,Snorunt,,
170,Glalie,,
171,Froslass,,
172,Snover,,
173,Abomasnow,,
174,Bergmite,,
175,Avalugg,,
176,Scyther,,
177,Scizor,,
178,Pinsir,,
179,Heracross,,
180,Emolga,,
181,Hawlucha,,
182,Phantump,,
183,Trevenant,,
184,Scraggy,,
185,Scrafty,,
186,Noibat,,
187,Noivern,,
188,Klefki,,
189,Litwick,,
190,Lampent,,
191,Chandelure,,
192,Aerodactyl,,
193,Tyrunt,,
194,Tyrantrum,,
195,Amaura,,
196,Aurorus,,
197,Onix,,
198,Steelix,,
199,Aron,,
200,Lairon,,
201,Aggron,,
202,Helioptile,,
203,Heliolisk,,
204,Pumpkaboo,,
205,Gourgeist,,
206,Larvitar,,
207,Pupitar,,
208,Tyranitar,,
209,Froakie,,
210,Frogadier,,
211,Greninja,,
212,Falinks,,
213,Chespin,,
214,Quilladin,,
215,Chesnaught,,
216,Skarmory,,
217,Fennekin,,
218,Braixen,,
219,Delphox,,
220,Bagon,,
221,Shelgon,,
222,Salamence,,
223,Kangaskhan,,
224,Drampa,,
225,Beldum,,
226,Metang,,
227,Metagross,,
228,Xerneas,,
229,Yveltal,,
230,Zygarde,,
231,Diancie,,
232,Mewtwo,,
1 dexNumber pokemon form notes
2 1 Chikorita
3 2 Bayleef
4 3 Meganium
5 4 Tepig
6 5 Pignite
7 6 Emboar
8 7 Totodile
9 8 Croconaw
10 9 Feraligatr
11 10 Fletchling
12 11 Fletchinder
13 12 Talonflame
14 13 Bunnelby
15 14 Diggersby
16 15 Scatterbug
17 16 Spewpa
18 17 Vivillon
19 18 Weedle
20 19 Kakuna
21 20 Beedrill
22 21 Pidgey
23 22 Pidgeotto
24 23 Pidgeot
25 24 Mareep
26 25 Flaaffy
27 26 Ampharos
28 27 Patrat
29 28 Watchog
30 29 Budew
31 30 Roselia
32 31 Roserade
33 32 Magikarp
34 33 Gyarados
35 34 Binacle
36 35 Barbaracle
37 36 Staryu
38 37 Starmie
39 38 Flabébé
40 39 Floette
41 40 Florges
42 41 Skiddo
43 42 Gogoat
44 43 Espurr
45 44 Meowstic
46 45 Litleo
47 46 Pyroar
48 47 Pancham
49 48 Pangoro
50 49 Trubbish
51 50 Garbodor
52 51 Dedenne
53 52 Pichu
54 53 Pikachu
55 54 Raichu
56 55 Cleffa
57 56 Clefairy
58 57 Clefable
59 58 Spinarak
60 59 Ariados
61 60 Ekans
62 61 Arbok
63 62 Abra
64 63 Kadabra
65 64 Alakazam
66 65 Gastly
67 66 Haunter
68 67 Gengar
69 68 Venipede
70 69 Whirlipede
71 70 Scolipede
72 71 Honedge
73 72 Doublade
74 73 Aegislash
75 74 Bellsprout
76 75 Weepinbell
77 76 Victreebel
78 77 Pansage
79 78 Simisage
80 79 Pansear
81 80 Simisear
82 81 Panpour
83 82 Simipour
84 83 Meditite
85 84 Medicham
86 85 Electrike
87 86 Manectric
88 87 Ralts
89 88 Kirlia
90 89 Gardevoir
91 90 Gallade
92 91 Houndour
93 92 Houndoom
94 93 Swablu
95 94 Altaria
96 95 Audino
97 96 Spritzee
98 97 Aromatisse
99 98 Swirlix
100 99 Slurpuff
101 100 Eevee
102 101 Vaporeon
103 102 Jolteon
104 103 Flareon
105 104 Espeon
106 105 Umbreon
107 106 Leafeon
108 107 Glaceon
109 108 Sylveon
110 109 Buneary
111 110 Lopunny
112 111 Shuppet
113 112 Banette
114 113 Vanillite
115 114 Vanillish
116 115 Vanilluxe
117 116 Numel
118 117 Camerupt
119 118 Hippopotas
120 119 Hippowdon
121 120 Drilbur
122 121 Excadrill
123 122 Sandile
124 123 Krokorok
125 124 Krookodile
126 125 Machop
127 126 Machoke
128 127 Machamp
129 128 Gible
130 129 Gabite
131 130 Garchomp
132 131 Carbink
133 132 Sableye
134 133 Mawile
135 134 Absol
136 135 Riolu
137 136 Lucario
138 137 Slowpoke
139 138 Slowbro
140 139 Slowking
141 140 Carvanha
142 141 Sharpedo
143 142 Tynamo
144 143 Eelektrik
145 144 Eelektross
146 145 Dratini
147 146 Dragonair
148 147 Dragonite
149 148 Bulbasaur
150 149 Ivysaur
151 150 Venusaur
152 151 Charmander
153 152 Charmeleon
154 153 Charizard
155 154 Squirtle
156 155 Wartortle
157 156 Blastoise
158 157 Stunfisk
159 158 Furfrou
160 159 Inkay
161 160 Malamar
162 161 Skrelp
163 162 Dragalge
164 163 Clauncher
165 164 Clawitzer
166 165 Goomy
167 166 Sliggoo
168 167 Goodra
169 168 Delibird
170 169 Snorunt
171 170 Glalie
172 171 Froslass
173 172 Snover
174 173 Abomasnow
175 174 Bergmite
176 175 Avalugg
177 176 Scyther
178 177 Scizor
179 178 Pinsir
180 179 Heracross
181 180 Emolga
182 181 Hawlucha
183 182 Phantump
184 183 Trevenant
185 184 Scraggy
186 185 Scrafty
187 186 Noibat
188 187 Noivern
189 188 Klefki
190 189 Litwick
191 190 Lampent
192 191 Chandelure
193 192 Aerodactyl
194 193 Tyrunt
195 194 Tyrantrum
196 195 Amaura
197 196 Aurorus
198 197 Onix
199 198 Steelix
200 199 Aron
201 200 Lairon
202 201 Aggron
203 202 Helioptile
204 203 Heliolisk
205 204 Pumpkaboo
206 205 Gourgeist
207 206 Larvitar
208 207 Pupitar
209 208 Tyranitar
210 209 Froakie
211 210 Frogadier
212 211 Greninja
213 212 Falinks
214 213 Chespin
215 214 Quilladin
216 215 Chesnaught
217 216 Skarmory
218 217 Fennekin
219 218 Braixen
220 219 Delphox
221 220 Bagon
222 221 Shelgon
223 222 Salamence
224 223 Kangaskhan
225 224 Drampa
226 225 Beldum
227 226 Metang
228 227 Metagross
229 228 Xerneas
230 229 Yveltal
231 230 Zygarde
232 231 Diancie
233 232 Mewtwo
@@ -0,0 +1,154 @@
dexNumber,pokemon,form,notes
1,Bulbasaur,,
2,Ivysaur,,
3,Venusaur,,
4,Charmander,,
5,Charmeleon,,
6,Charizard,,
7,Squirtle,,
8,Wartortle,,
9,Blastoise,,
10,Caterpie,,
11,Metapod,,
12,Butterfree,,
13,Weedle,,
14,Kakuna,,
15,Beedrill,,
16,Pidgey,,
17,Pidgeotto,,
18,Pidgeot,,
19,Rattata,,
20,Raticate,,
21,Spearow,,
22,Fearow,,
23,Ekans,,
24,Arbok,,
25,Pikachu,,
26,Raichu,,
27,Sandshrew,,
28,Sandslash,,
29,Nidoran♀,,
30,Nidorina,,
31,Nidoqueen,,
32,Nidoran♂,,
33,Nidorino,,
34,Nidoking,,
35,Clefairy,,
36,Clefable,,
37,Vulpix,,
38,Ninetales,,
39,Jigglypuff,,
40,Wigglytuff,,
41,Zubat,,
42,Golbat,,
43,Oddish,,
44,Gloom,,
45,Vileplume,,
46,Paras,,
47,Parasect,,
48,Venonat,,
49,Venomoth,,
50,Diglett,,
51,Dugtrio,,
52,Meowth,,
53,Persian,,
54,Psyduck,,
55,Golduck,,
56,Mankey,,
57,Primeape,,
58,Growlithe,,
59,Arcanine,,
60,Poliwag,,
61,Poliwhirl,,
62,Poliwrath,,
63,Abra,,
64,Kadabra,,
65,Alakazam,,
66,Machop,,
67,Machoke,,
68,Machamp,,
69,Bellsprout,,
70,Weepinbell,,
71,Victreebel,,
72,Tentacool,,
73,Tentacruel,,
74,Geodude,,
75,Graveler,,
76,Golem,,
77,Ponyta,,
78,Rapidash,,
79,Slowpoke,,
80,Slowbro,,
81,Magnemite,,
82,Magneton,,
83,Farfetchd,,
84,Doduo,,
85,Dodrio,,
86,Seel,,
87,Dewgong,,
88,Grimer,,
89,Muk,,
90,Shellder,,
91,Cloyster,,
92,Gastly,,
93,Haunter,,
94,Gengar,,
95,Onix,,
96,Drowzee,,
97,Hypno,,
98,Krabby,,
99,Kingler,,
100,Voltorb,,
101,Electrode,,
102,Exeggcute,,
103,Exeggutor,,
104,Cubone,,
105,Marowak,,
106,Hitmonlee,,
107,Hitmonchan,,
108,Lickitung,,
109,Koffing,,
110,Weezing,,
111,Rhyhorn,,
112,Rhydon,,
113,Chansey,,
114,Tangela,,
115,Kangaskhan,,
116,Horsea,,
117,Seadra,,
118,Goldeen,,
119,Seaking,,
120,Staryu,,
121,Starmie,,
122,Mr. Mime,,
123,Scyther,,
124,Jynx,,
125,Electabuzz,,
126,Magmar,,
127,Pinsir,,
128,Tauros,,
129,Magikarp,,
130,Gyarados,,
131,Lapras,,
132,Ditto,,
133,Eevee,,
134,Vaporeon,,
135,Jolteon,,
136,Flareon,,
137,Porygon,,
138,Omanyte,,
139,Omastar,,
140,Kabuto,,
141,Kabutops,,
142,Aerodactyl,,
143,Snorlax,,
144,Articuno,,
145,Zapdos,,
146,Moltres,,
147,Dratini,,
148,Dragonair,,
149,Dragonite,,
150,Mewtwo,,
151,Mew,,
152,Meltan,,
153,Melmetal,,
1 dexNumber pokemon form notes
2 1 Bulbasaur
3 2 Ivysaur
4 3 Venusaur
5 4 Charmander
6 5 Charmeleon
7 6 Charizard
8 7 Squirtle
9 8 Wartortle
10 9 Blastoise
11 10 Caterpie
12 11 Metapod
13 12 Butterfree
14 13 Weedle
15 14 Kakuna
16 15 Beedrill
17 16 Pidgey
18 17 Pidgeotto
19 18 Pidgeot
20 19 Rattata
21 20 Raticate
22 21 Spearow
23 22 Fearow
24 23 Ekans
25 24 Arbok
26 25 Pikachu
27 26 Raichu
28 27 Sandshrew
29 28 Sandslash
30 29 Nidoran♀
31 30 Nidorina
32 31 Nidoqueen
33 32 Nidoran♂
34 33 Nidorino
35 34 Nidoking
36 35 Clefairy
37 36 Clefable
38 37 Vulpix
39 38 Ninetales
40 39 Jigglypuff
41 40 Wigglytuff
42 41 Zubat
43 42 Golbat
44 43 Oddish
45 44 Gloom
46 45 Vileplume
47 46 Paras
48 47 Parasect
49 48 Venonat
50 49 Venomoth
51 50 Diglett
52 51 Dugtrio
53 52 Meowth
54 53 Persian
55 54 Psyduck
56 55 Golduck
57 56 Mankey
58 57 Primeape
59 58 Growlithe
60 59 Arcanine
61 60 Poliwag
62 61 Poliwhirl
63 62 Poliwrath
64 63 Abra
65 64 Kadabra
66 65 Alakazam
67 66 Machop
68 67 Machoke
69 68 Machamp
70 69 Bellsprout
71 70 Weepinbell
72 71 Victreebel
73 72 Tentacool
74 73 Tentacruel
75 74 Geodude
76 75 Graveler
77 76 Golem
78 77 Ponyta
79 78 Rapidash
80 79 Slowpoke
81 80 Slowbro
82 81 Magnemite
83 82 Magneton
84 83 Farfetch’d
85 84 Doduo
86 85 Dodrio
87 86 Seel
88 87 Dewgong
89 88 Grimer
90 89 Muk
91 90 Shellder
92 91 Cloyster
93 92 Gastly
94 93 Haunter
95 94 Gengar
96 95 Onix
97 96 Drowzee
98 97 Hypno
99 98 Krabby
100 99 Kingler
101 100 Voltorb
102 101 Electrode
103 102 Exeggcute
104 103 Exeggutor
105 104 Cubone
106 105 Marowak
107 106 Hitmonlee
108 107 Hitmonchan
109 108 Lickitung
110 109 Koffing
111 110 Weezing
112 111 Rhyhorn
113 112 Rhydon
114 113 Chansey
115 114 Tangela
116 115 Kangaskhan
117 116 Horsea
118 117 Seadra
119 118 Goldeen
120 119 Seaking
121 120 Staryu
122 121 Starmie
123 122 Mr. Mime
124 123 Scyther
125 124 Jynx
126 125 Electabuzz
127 126 Magmar
128 127 Pinsir
129 128 Tauros
130 129 Magikarp
131 130 Gyarados
132 131 Lapras
133 132 Ditto
134 133 Eevee
135 134 Vaporeon
136 135 Jolteon
137 136 Flareon
138 137 Porygon
139 138 Omanyte
140 139 Omastar
141 140 Kabuto
142 141 Kabutops
143 142 Aerodactyl
144 143 Snorlax
145 144 Articuno
146 145 Zapdos
147 146 Moltres
148 147 Dratini
149 148 Dragonair
150 149 Dragonite
151 150 Mewtwo
152 151 Mew
153 152 Meltan
154 153 Melmetal
@@ -0,0 +1,212 @@
dexNumber,pokemon,form,notes
1,Treecko,,
2,Grovyle,,
3,Sceptile,,
4,Torchic,,
5,Combusken,,
6,Blaziken,,
7,Mudkip,,
8,Marshtomp,,
9,Swampert,,
10,Poochyena,,
11,Mightyena,,
12,Zigzagoon,,
13,Linoone,,
14,Wurmple,,
15,Silcoon,,
16,Beautifly,,
17,Cascoon,,
18,Dustox,,
19,Lotad,,
20,Lombre,,
21,Ludicolo,,
22,Seedot,,
23,Nuzleaf,,
24,Shiftry,,
25,Taillow,,
26,Swellow,,
27,Wingull,,
28,Pelipper,,
29,Ralts,,
30,Kirlia,,
31,Gardevoir,,
32,Gallade,,
33,Surskit,,
34,Masquerain,,
35,Shroomish,,
36,Breloom,,
37,Slakoth,,
38,Vigoroth,,
39,Slaking,,
40,Abra,,
41,Kadabra,,
42,Alakazam,,
43,Nincada,,
44,Ninjask,,
45,Shedinja,,
46,Whismur,,
47,Loudred,,
48,Exploud,,
49,Makuhita,,
50,Hariyama,,
51,Goldeen,,
52,Seaking,,
53,Magikarp,,
54,Gyarados,,
55,Azurill,,
56,Marill,,
57,Azumarill,,
58,Geodude,,
59,Graveler,,
60,Golem,,
61,Nosepass,,
62,Probopass,,
63,Skitty,,
64,Delcatty,,
65,Zubat,,
66,Golbat,,
67,Crobat,,
68,Tentacool,,
69,Tentacruel,,
70,Sableye,,
71,Mawile,,
72,Aron,,
73,Lairon,,
74,Aggron,,
75,Machop,,
76,Machoke,,
77,Machamp,,
78,Meditite,,
79,Medicham,,
80,Electrike,,
81,Manectric,,
82,Plusle,,
83,Minun,,
84,Magnemite,,
85,Magneton,,
86,Magnezone,,
87,Voltorb,,
88,Electrode,,
89,Volbeat,,
90,Illumise,,
91,Oddish,,
92,Gloom,,
93,Vileplume,,
94,Bellossom,,
95,Doduo,,
96,Dodrio,,
97,Budew,,
98,Roselia,,
99,Roserade,,
100,Gulpin,,
101,Swalot,,
102,Carvanha,,
103,Sharpedo,,
104,Wailmer,,
105,Wailord,,
106,Numel,,
107,Camerupt,,
108,Slugma,,
109,Magcargo,,
110,Torkoal,,
111,Grimer,,
112,Muk,,
113,Koffing,,
114,Weezing,,
115,Spoink,,
116,Grumpig,,
117,Sandshrew,,
118,Sandslash,,
119,Spinda,,
120,Skarmory,,
121,Trapinch,,
122,Vibrava,,
123,Flygon,,
124,Cacnea,,
125,Cacturne,,
126,Swablu,,
127,Altaria,,
128,Zangoose,,
129,Seviper,,
130,Lunatone,,
131,Solrock,,
132,Barboach,,
133,Whiscash,,
134,Corphish,,
135,Crawdaunt,,
136,Baltoy,,
137,Claydol,,
138,Lileep,,
139,Cradily,,
140,Anorith,,
141,Armaldo,,
142,Igglybuff,,
143,Jigglypuff,,
144,Wigglytuff,,
145,Feebas,,
146,Milotic,,
147,Castform,,
148,Staryu,,
149,Starmie,,
150,Kecleon,,
151,Shuppet,,
152,Banette,,
153,Duskull,,
154,Dusclops,,
155,Dusknoir,,
156,Tropius,,
157,Chingling,,
158,Chimecho,,
159,Absol,,
160,Vulpix,,
161,Ninetales,,
162,Pichu,,
163,Pikachu,,
164,Raichu,,
165,Psyduck,,
166,Golduck,,
167,Wynaut,,
168,Wobbuffet,,
169,Natu,,
170,Xatu,,
171,Girafarig,,
172,Phanpy,,
173,Donphan,,
174,Pinsir,,
175,Heracross,,
176,Rhyhorn,,
177,Rhydon,,
178,Rhyperior,,
179,Snorunt,,
180,Glalie,,
181,Froslass,,
182,Spheal,,
183,Sealeo,,
184,Walrein,,
185,Clamperl,,
186,Huntail,,
187,Gorebyss,,
188,Relicanth,,
189,Corsola,,
190,Chinchou,,
191,Lanturn,,
192,Luvdisc,,
193,Horsea,,
194,Seadra,,
195,Kingdra,,
196,Bagon,,
197,Shelgon,,
198,Salamence,,
199,Beldum,,
200,Metang,,
201,Metagross,,
202,Regirock,,
203,Regice,,
204,Registeel,,
205,Latias,,
206,Latios,,
207,Kyogre,,
208,Groudon,,
209,Rayquaza,,
210,Jirachi,,
211,Deoxys,,
1 dexNumber pokemon form notes
2 1 Treecko
3 2 Grovyle
4 3 Sceptile
5 4 Torchic
6 5 Combusken
7 6 Blaziken
8 7 Mudkip
9 8 Marshtomp
10 9 Swampert
11 10 Poochyena
12 11 Mightyena
13 12 Zigzagoon
14 13 Linoone
15 14 Wurmple
16 15 Silcoon
17 16 Beautifly
18 17 Cascoon
19 18 Dustox
20 19 Lotad
21 20 Lombre
22 21 Ludicolo
23 22 Seedot
24 23 Nuzleaf
25 24 Shiftry
26 25 Taillow
27 26 Swellow
28 27 Wingull
29 28 Pelipper
30 29 Ralts
31 30 Kirlia
32 31 Gardevoir
33 32 Gallade
34 33 Surskit
35 34 Masquerain
36 35 Shroomish
37 36 Breloom
38 37 Slakoth
39 38 Vigoroth
40 39 Slaking
41 40 Abra
42 41 Kadabra
43 42 Alakazam
44 43 Nincada
45 44 Ninjask
46 45 Shedinja
47 46 Whismur
48 47 Loudred
49 48 Exploud
50 49 Makuhita
51 50 Hariyama
52 51 Goldeen
53 52 Seaking
54 53 Magikarp
55 54 Gyarados
56 55 Azurill
57 56 Marill
58 57 Azumarill
59 58 Geodude
60 59 Graveler
61 60 Golem
62 61 Nosepass
63 62 Probopass
64 63 Skitty
65 64 Delcatty
66 65 Zubat
67 66 Golbat
68 67 Crobat
69 68 Tentacool
70 69 Tentacruel
71 70 Sableye
72 71 Mawile
73 72 Aron
74 73 Lairon
75 74 Aggron
76 75 Machop
77 76 Machoke
78 77 Machamp
79 78 Meditite
80 79 Medicham
81 80 Electrike
82 81 Manectric
83 82 Plusle
84 83 Minun
85 84 Magnemite
86 85 Magneton
87 86 Magnezone
88 87 Voltorb
89 88 Electrode
90 89 Volbeat
91 90 Illumise
92 91 Oddish
93 92 Gloom
94 93 Vileplume
95 94 Bellossom
96 95 Doduo
97 96 Dodrio
98 97 Budew
99 98 Roselia
100 99 Roserade
101 100 Gulpin
102 101 Swalot
103 102 Carvanha
104 103 Sharpedo
105 104 Wailmer
106 105 Wailord
107 106 Numel
108 107 Camerupt
109 108 Slugma
110 109 Magcargo
111 110 Torkoal
112 111 Grimer
113 112 Muk
114 113 Koffing
115 114 Weezing
116 115 Spoink
117 116 Grumpig
118 117 Sandshrew
119 118 Sandslash
120 119 Spinda
121 120 Skarmory
122 121 Trapinch
123 122 Vibrava
124 123 Flygon
125 124 Cacnea
126 125 Cacturne
127 126 Swablu
128 127 Altaria
129 128 Zangoose
130 129 Seviper
131 130 Lunatone
132 131 Solrock
133 132 Barboach
134 133 Whiscash
135 134 Corphish
136 135 Crawdaunt
137 136 Baltoy
138 137 Claydol
139 138 Lileep
140 139 Cradily
141 140 Anorith
142 141 Armaldo
143 142 Igglybuff
144 143 Jigglypuff
145 144 Wigglytuff
146 145 Feebas
147 146 Milotic
148 147 Castform
149 148 Staryu
150 149 Starmie
151 150 Kecleon
152 151 Shuppet
153 152 Banette
154 153 Duskull
155 154 Dusclops
156 155 Dusknoir
157 156 Tropius
158 157 Chingling
159 158 Chimecho
160 159 Absol
161 160 Vulpix
162 161 Ninetales
163 162 Pichu
164 163 Pikachu
165 164 Raichu
166 165 Psyduck
167 166 Golduck
168 167 Wynaut
169 168 Wobbuffet
170 169 Natu
171 170 Xatu
172 171 Girafarig
173 172 Phanpy
174 173 Donphan
175 174 Pinsir
176 175 Heracross
177 176 Rhyhorn
178 177 Rhydon
179 178 Rhyperior
180 179 Snorunt
181 180 Glalie
182 181 Froslass
183 182 Spheal
184 183 Sealeo
185 184 Walrein
186 185 Clamperl
187 186 Huntail
188 187 Gorebyss
189 188 Relicanth
190 189 Corsola
191 190 Chinchou
192 191 Lanturn
193 192 Luvdisc
194 193 Horsea
195 194 Seadra
196 195 Kingdra
197 196 Bagon
198 197 Shelgon
199 198 Salamence
200 199 Beldum
201 200 Metang
202 201 Metagross
203 202 Regirock
204 203 Regice
205 204 Registeel
206 205 Latias
207 206 Latios
208 207 Kyogre
209 208 Groudon
210 209 Rayquaza
211 210 Jirachi
212 211 Deoxys
+211
View File
@@ -0,0 +1,211 @@
dexNumber,pokemon,form,notes
1,Turtwig,,
2,Grotle,,
3,Torterra,,
4,Chimchar,,
5,Monferno,,
6,Infernape,,
7,Piplup,,
8,Prinplup,,
9,Empoleon,,
10,Starly,,
11,Staravia,,
12,Staraptor,,
13,Bidoof,,
14,Bibarel,,
15,Kricketot,,
16,Kricketune,,
17,Shinx,,
18,Luxio,,
19,Luxray,,
20,Abra,,
21,Kadabra,,
22,Alakazam,,
23,Magikarp,,
24,Gyarados,,
25,Budew,,
26,Roselia,,
27,Roserade,,
28,Zubat,,
29,Golbat,,
30,Crobat,,
31,Geodude,,
32,Graveler,,
33,Golem,,
34,Onix,,
35,Steelix,,
36,Cranidos,,
37,Rampardos,,
38,Shieldon,,
39,Bastiodon,,
40,Machop,,
41,Machoke,,
42,Machamp,,
43,Psyduck,,
44,Golduck,,
45,Burmy,,
46,Wormadam,,
47,Mothim,,
48,Wurmple,,
49,Silcoon,,
50,Beautifly,,
51,Cascoon,,
52,Dustox,,
53,Combee,,
54,Vespiquen,,
55,Pachirisu,,
56,Buizel,,
57,Floatzel,,
58,Cherubi,,
59,Cherrim,,
60,Shellos,,
61,Gastrodon,,
62,Heracross,,
63,Aipom,,
64,Ambipom,,
65,Drifloon,,
66,Drifblim,,
67,Buneary,,
68,Lopunny,,
69,Gastly,,
70,Haunter,,
71,Gengar,,
72,Misdreavus,,
73,Mismagius,,
74,Murkrow,,
75,Honchkrow,,
76,Glameow,,
77,Purugly,,
78,Goldeen,,
79,Seaking,,
80,Barboach,,
81,Whiscash,,
82,Chingling,,
83,Chimecho,,
84,Stunky,,
85,Skuntank,,
86,Meditite,,
87,Medicham,,
88,Bronzor,,
89,Bronzong,,
90,Ponyta,,
91,Rapidash,,
92,Bonsly,,
93,Sudowoodo,,
94,Mime Jr.,,
95,Mr. Mime,,
96,Happiny,,
97,Chansey,,
98,Blissey,,
99,Cleffa,,
100,Clefairy,,
101,Clefable,,
102,Chatot,,
103,Pichu,,
104,Pikachu,,
105,Raichu,,
106,Hoothoot,,
107,Noctowl,,
108,Spiritomb,,
109,Gible,,
110,Gabite,,
111,Garchomp,,
112,Munchlax,,
113,Snorlax,,
114,Unown,,
115,Riolu,,
116,Lucario,,
117,Wooper,,
118,Quagsire,,
119,Wingull,,
120,Pelipper,,
121,Girafarig,,
122,Hippopotas,,
123,Hippowdon,,
124,Azurill,,
125,Marill,,
126,Azumarill,,
127,Skorupi,,
128,Drapion,,
129,Croagunk,,
130,Toxicroak,,
131,Carnivine,,
132,Remoraid,,
133,Octillery,,
134,Finneon,,
135,Lumineon,,
136,Tentacool,,
137,Tentacruel,,
138,Feebas,,
139,Milotic,,
140,Mantyke,,
141,Mantine,,
142,Snover,,
143,Abomasnow,,
144,Sneasel,,
145,Weavile,,
146,Uxie,,
147,Mesprit,,
148,Azelf,,
149,Dialga,,
150,Palkia,,
151,Manaphy,,
152,Rotom,,
153,Gligar,,
154,Gliscor,,
155,Nosepass,,
156,Probopass,,
157,Ralts,,
158,Kirlia,,
159,Gardevoir,,
160,Gallade,,
161,Lickitung,,
162,Lickilicky,,
163,Eevee,,
164,Vaporeon,,
165,Jolteon,,
166,Flareon,,
167,Espeon,,
168,Umbreon,,
169,Leafeon,,
170,Glaceon,,
171,Swablu,,
172,Altaria,,
173,Togepi,,
174,Togetic,,
175,Togekiss,,
176,Houndour,,
177,Houndoom,,
178,Magnemite,,
179,Magneton,,
180,Magnezone,,
181,Tangela,,
182,Tangrowth,,
183,Yanma,,
184,Yanmega,,
185,Tropius,,
186,Rhyhorn,,
187,Rhydon,,
188,Rhyperior,,
189,Duskull,,
190,Dusclops,,
191,Dusknoir,,
192,Porygon,,
193,Porygon2,,
194,Porygon-Z,,
195,Scyther,,
196,Scizor,,
197,Elekid,,
198,Electabuzz,,
199,Electivire,,
200,Magby,,
201,Magmar,,
202,Magmortar,,
203,Swinub,,
204,Piloswine,,
205,Mamoswine,,
206,Snorunt,,
207,Glalie,,
208,Froslass,,
209,Absol,,
210,Giratina,,
1 dexNumber pokemon form notes
2 1 Turtwig
3 2 Grotle
4 3 Torterra
5 4 Chimchar
6 5 Monferno
7 6 Infernape
8 7 Piplup
9 8 Prinplup
10 9 Empoleon
11 10 Starly
12 11 Staravia
13 12 Staraptor
14 13 Bidoof
15 14 Bibarel
16 15 Kricketot
17 16 Kricketune
18 17 Shinx
19 18 Luxio
20 19 Luxray
21 20 Abra
22 21 Kadabra
23 22 Alakazam
24 23 Magikarp
25 24 Gyarados
26 25 Budew
27 26 Roselia
28 27 Roserade
29 28 Zubat
30 29 Golbat
31 30 Crobat
32 31 Geodude
33 32 Graveler
34 33 Golem
35 34 Onix
36 35 Steelix
37 36 Cranidos
38 37 Rampardos
39 38 Shieldon
40 39 Bastiodon
41 40 Machop
42 41 Machoke
43 42 Machamp
44 43 Psyduck
45 44 Golduck
46 45 Burmy
47 46 Wormadam
48 47 Mothim
49 48 Wurmple
50 49 Silcoon
51 50 Beautifly
52 51 Cascoon
53 52 Dustox
54 53 Combee
55 54 Vespiquen
56 55 Pachirisu
57 56 Buizel
58 57 Floatzel
59 58 Cherubi
60 59 Cherrim
61 60 Shellos
62 61 Gastrodon
63 62 Heracross
64 63 Aipom
65 64 Ambipom
66 65 Drifloon
67 66 Drifblim
68 67 Buneary
69 68 Lopunny
70 69 Gastly
71 70 Haunter
72 71 Gengar
73 72 Misdreavus
74 73 Mismagius
75 74 Murkrow
76 75 Honchkrow
77 76 Glameow
78 77 Purugly
79 78 Goldeen
80 79 Seaking
81 80 Barboach
82 81 Whiscash
83 82 Chingling
84 83 Chimecho
85 84 Stunky
86 85 Skuntank
87 86 Meditite
88 87 Medicham
89 88 Bronzor
90 89 Bronzong
91 90 Ponyta
92 91 Rapidash
93 92 Bonsly
94 93 Sudowoodo
95 94 Mime Jr.
96 95 Mr. Mime
97 96 Happiny
98 97 Chansey
99 98 Blissey
100 99 Cleffa
101 100 Clefairy
102 101 Clefable
103 102 Chatot
104 103 Pichu
105 104 Pikachu
106 105 Raichu
107 106 Hoothoot
108 107 Noctowl
109 108 Spiritomb
110 109 Gible
111 110 Gabite
112 111 Garchomp
113 112 Munchlax
114 113 Snorlax
115 114 Unown
116 115 Riolu
117 116 Lucario
118 117 Wooper
119 118 Quagsire
120 119 Wingull
121 120 Pelipper
122 121 Girafarig
123 122 Hippopotas
124 123 Hippowdon
125 124 Azurill
126 125 Marill
127 126 Azumarill
128 127 Skorupi
129 128 Drapion
130 129 Croagunk
131 130 Toxicroak
132 131 Carnivine
133 132 Remoraid
134 133 Octillery
135 134 Finneon
136 135 Lumineon
137 136 Tentacool
138 137 Tentacruel
139 138 Feebas
140 139 Milotic
141 140 Mantyke
142 141 Mantine
143 142 Snover
144 143 Abomasnow
145 144 Sneasel
146 145 Weavile
147 146 Uxie
148 147 Mesprit
149 148 Azelf
150 149 Dialga
151 150 Palkia
152 151 Manaphy
153 152 Rotom
154 153 Gligar
155 154 Gliscor
156 155 Nosepass
157 156 Probopass
158 157 Ralts
159 158 Kirlia
160 159 Gardevoir
161 160 Gallade
162 161 Lickitung
163 162 Lickilicky
164 163 Eevee
165 164 Vaporeon
166 165 Jolteon
167 166 Flareon
168 167 Espeon
169 168 Umbreon
170 169 Leafeon
171 170 Glaceon
172 171 Swablu
173 172 Altaria
174 173 Togepi
175 174 Togetic
176 175 Togekiss
177 176 Houndour
178 177 Houndoom
179 178 Magnemite
180 179 Magneton
181 180 Magnezone
182 181 Tangela
183 182 Tangrowth
184 183 Yanma
185 184 Yanmega
186 185 Tropius
187 186 Rhyhorn
188 187 Rhydon
189 188 Rhyperior
190 189 Duskull
191 190 Dusclops
192 191 Dusknoir
193 192 Porygon
194 193 Porygon2
195 194 Porygon-Z
196 195 Scyther
197 196 Scizor
198 197 Elekid
199 198 Electabuzz
200 199 Electivire
201 200 Magby
202 201 Magmar
203 202 Magmortar
204 203 Swinub
205 204 Piloswine
206 205 Mamoswine
207 206 Snorunt
208 207 Glalie
209 208 Froslass
210 209 Absol
211 210 Giratina
@@ -0,0 +1,152 @@
dexNumber,pokemon,form,notes
1,Bulbasaur,,
2,Ivysaur,,
3,Venusaur,,
4,Charmander,,
5,Charmeleon,,
6,Charizard,,
7,Squirtle,,
8,Wartortle,,
9,Blastoise,,
10,Caterpie,,
11,Metapod,,
12,Butterfree,,
13,Weedle,,
14,Kakuna,,
15,Beedrill,,
16,Pidgey,,
17,Pidgeotto,,
18,Pidgeot,,
19,Rattata,,
20,Raticate,,
21,Spearow,,
22,Fearow,,
23,Ekans,,
24,Arbok,,
25,Pikachu,,
26,Raichu,,
27,Sandshrew,,
28,Sandslash,,
29,Nidoran♀,,
30,Nidorina,,
31,Nidoqueen,,
32,Nidoran♂,,
33,Nidorino,,
34,Nidoking,,
35,Clefairy,,
36,Clefable,,
37,Vulpix,,
38,Ninetales,,
39,Jigglypuff,,
40,Wigglytuff,,
41,Zubat,,
42,Golbat,,
43,Oddish,,
44,Gloom,,
45,Vileplume,,
46,Paras,,
47,Parasect,,
48,Venonat,,
49,Venomoth,,
50,Diglett,,
51,Dugtrio,,
52,Meowth,,
53,Persian,,
54,Psyduck,,
55,Golduck,,
56,Mankey,,
57,Primeape,,
58,Growlithe,,
59,Arcanine,,
60,Poliwag,,
61,Poliwhirl,,
62,Poliwrath,,
63,Abra,,
64,Kadabra,,
65,Alakazam,,
66,Machop,,
67,Machoke,,
68,Machamp,,
69,Bellsprout,,
70,Weepinbell,,
71,Victreebel,,
72,Tentacool,,
73,Tentacruel,,
74,Geodude,,
75,Graveler,,
76,Golem,,
77,Ponyta,,
78,Rapidash,,
79,Slowpoke,,
80,Slowbro,,
81,Magnemite,,
82,Magneton,,
83,Farfetchd,,
84,Doduo,,
85,Dodrio,,
86,Seel,,
87,Dewgong,,
88,Grimer,,
89,Muk,,
90,Shellder,,
91,Cloyster,,
92,Gastly,,
93,Haunter,,
94,Gengar,,
95,Onix,,
96,Drowzee,,
97,Hypno,,
98,Krabby,,
99,Kingler,,
100,Voltorb,,
101,Electrode,,
102,Exeggcute,,
103,Exeggutor,,
104,Cubone,,
105,Marowak,,
106,Hitmonlee,,
107,Hitmonchan,,
108,Lickitung,,
109,Koffing,,
110,Weezing,,
111,Rhyhorn,,
112,Rhydon,,
113,Chansey,,
114,Tangela,,
115,Kangaskhan,,
116,Horsea,,
117,Seadra,,
118,Goldeen,,
119,Seaking,,
120,Staryu,,
121,Starmie,,
122,Mr. Mime,,
123,Scyther,,
124,Jynx,,
125,Electabuzz,,
126,Magmar,,
127,Pinsir,,
128,Tauros,,
129,Magikarp,,
130,Gyarados,,
131,Lapras,,
132,Ditto,,
133,Eevee,,
134,Vaporeon,,
135,Jolteon,,
136,Flareon,,
137,Porygon,,
138,Omanyte,,
139,Omastar,,
140,Kabuto,,
141,Kabutops,,
142,Aerodactyl,,
143,Snorlax,,
144,Articuno,,
145,Zapdos,,
146,Moltres,,
147,Dratini,,
148,Dragonair,,
149,Dragonite,,
150,Mewtwo,,
151,Mew,,
1 dexNumber pokemon form notes
2 1 Bulbasaur
3 2 Ivysaur
4 3 Venusaur
5 4 Charmander
6 5 Charmeleon
7 6 Charizard
8 7 Squirtle
9 8 Wartortle
10 9 Blastoise
11 10 Caterpie
12 11 Metapod
13 12 Butterfree
14 13 Weedle
15 14 Kakuna
16 15 Beedrill
17 16 Pidgey
18 17 Pidgeotto
19 18 Pidgeot
20 19 Rattata
21 20 Raticate
22 21 Spearow
23 22 Fearow
24 23 Ekans
25 24 Arbok
26 25 Pikachu
27 26 Raichu
28 27 Sandshrew
29 28 Sandslash
30 29 Nidoran♀
31 30 Nidorina
32 31 Nidoqueen
33 32 Nidoran♂
34 33 Nidorino
35 34 Nidoking
36 35 Clefairy
37 36 Clefable
38 37 Vulpix
39 38 Ninetales
40 39 Jigglypuff
41 40 Wigglytuff
42 41 Zubat
43 42 Golbat
44 43 Oddish
45 44 Gloom
46 45 Vileplume
47 46 Paras
48 47 Parasect
49 48 Venonat
50 49 Venomoth
51 50 Diglett
52 51 Dugtrio
53 52 Meowth
54 53 Persian
55 54 Psyduck
56 55 Golduck
57 56 Mankey
58 57 Primeape
59 58 Growlithe
60 59 Arcanine
61 60 Poliwag
62 61 Poliwhirl
63 62 Poliwrath
64 63 Abra
65 64 Kadabra
66 65 Alakazam
67 66 Machop
68 67 Machoke
69 68 Machamp
70 69 Bellsprout
71 70 Weepinbell
72 71 Victreebel
73 72 Tentacool
74 73 Tentacruel
75 74 Geodude
76 75 Graveler
77 76 Golem
78 77 Ponyta
79 78 Rapidash
80 79 Slowpoke
81 80 Slowbro
82 81 Magnemite
83 82 Magneton
84 83 Farfetch’d
85 84 Doduo
86 85 Dodrio
87 86 Seel
88 87 Dewgong
89 88 Grimer
90 89 Muk
91 90 Shellder
92 91 Cloyster
93 92 Gastly
94 93 Haunter
95 94 Gengar
96 95 Onix
97 96 Drowzee
98 97 Hypno
99 98 Krabby
100 99 Kingler
101 100 Voltorb
102 101 Electrode
103 102 Exeggcute
104 103 Exeggutor
105 104 Cubone
106 105 Marowak
107 106 Hitmonlee
108 107 Hitmonchan
109 108 Lickitung
110 109 Koffing
111 110 Weezing
112 111 Rhyhorn
113 112 Rhydon
114 113 Chansey
115 114 Tangela
116 115 Kangaskhan
117 116 Horsea
118 117 Seadra
119 118 Goldeen
120 119 Seaking
121 120 Staryu
122 121 Starmie
123 122 Mr. Mime
124 123 Scyther
125 124 Jynx
126 125 Electabuzz
127 126 Magmar
128 127 Pinsir
129 128 Tauros
130 129 Magikarp
131 130 Gyarados
132 131 Lapras
133 132 Ditto
134 133 Eevee
135 134 Vaporeon
136 135 Jolteon
137 136 Flareon
138 137 Porygon
139 138 Omanyte
140 139 Omastar
141 140 Kabuto
142 141 Kabutops
143 142 Aerodactyl
144 143 Snorlax
145 144 Articuno
146 145 Zapdos
147 146 Moltres
148 147 Dratini
149 148 Dragonair
150 149 Dragonite
151 150 Mewtwo
152 151 Mew
@@ -0,0 +1,203 @@
dexNumber,pokemon,form,notes
1,Treecko,,
2,Grovyle,,
3,Sceptile,,
4,Torchic,,
5,Combusken,,
6,Blaziken,,
7,Mudkip,,
8,Marshtomp,,
9,Swampert,,
10,Poochyena,,
11,Mightyena,,
12,Zigzagoon,,
13,Linoone,,
14,Wurmple,,
15,Silcoon,,
16,Beautifly,,
17,Cascoon,,
18,Dustox,,
19,Lotad,,
20,Lombre,,
21,Ludicolo,,
22,Seedot,,
23,Nuzleaf,,
24,Shiftry,,
25,Taillow,,
26,Swellow,,
27,Wingull,,
28,Pelipper,,
29,Ralts,,
30,Kirlia,,
31,Gardevoir,,
32,Surskit,,
33,Masquerain,,
34,Shroomish,,
35,Breloom,,
36,Slakoth,,
37,Vigoroth,,
38,Slaking,,
39,Abra,,
40,Kadabra,,
41,Alakazam,,
42,Nincada,,
43,Ninjask,,
44,Shedinja,,
45,Whismur,,
46,Loudred,,
47,Exploud,,
48,Makuhita,,
49,Hariyama,,
50,Goldeen,,
51,Seaking,,
52,Magikarp,,
53,Gyarados,,
54,Azurill,,
55,Marill,,
56,Azumarill,,
57,Geodude,,
58,Graveler,,
59,Golem,,
60,Nosepass,,
61,Skitty,,
62,Delcatty,,
63,Zubat,,
64,Golbat,,
65,Crobat,,
66,Tentacool,,
67,Tentacruel,,
68,Sableye,,
69,Mawile,,
70,Aron,,
71,Lairon,,
72,Aggron,,
73,Machop,,
74,Machoke,,
75,Machamp,,
76,Meditite,,
77,Medicham,,
78,Electrike,,
79,Manectric,,
80,Plusle,,
81,Minun,,
82,Magnemite,,
83,Magneton,,
84,Voltorb,,
85,Electrode,,
86,Volbeat,,
87,Illumise,,
88,Oddish,,
89,Gloom,,
90,Vileplume,,
91,Bellossom,,
92,Doduo,,
93,Dodrio,,
94,Roselia,,
95,Gulpin,,
96,Swalot,,
97,Carvanha,,
98,Sharpedo,,
99,Wailmer,,
100,Wailord,,
101,Numel,,
102,Camerupt,,
103,Slugma,,
104,Magcargo,,
105,Torkoal,,
106,Grimer,,
107,Muk,,
108,Koffing,,
109,Weezing,,
110,Spoink,,
111,Grumpig,,
112,Sandshrew,,
113,Sandslash,,
114,Spinda,,
115,Skarmory,,
116,Trapinch,,
117,Vibrava,,
118,Flygon,,
119,Cacnea,,
120,Cacturne,,
121,Swablu,,
122,Altaria,,
123,Zangoose,,
124,Seviper,,
125,Lunatone,,
126,Solrock,,
127,Barboach,,
128,Whiscash,,
129,Corphish,,
130,Crawdaunt,,
131,Baltoy,,
132,Claydol,,
133,Lileep,,
134,Cradily,,
135,Anorith,,
136,Armaldo,,
137,Igglybuff,,
138,Jigglypuff,,
139,Wigglytuff,,
140,Feebas,,
141,Milotic,,
142,Castform,,
143,Staryu,,
144,Starmie,,
145,Kecleon,,
146,Shuppet,,
147,Banette,,
148,Duskull,,
149,Dusclops,,
150,Tropius,,
151,Chimecho,,
152,Absol,,
153,Vulpix,,
154,Ninetales,,
155,Pichu,,
156,Pikachu,,
157,Raichu,,
158,Psyduck,,
159,Golduck,,
160,Wynaut,,
161,Wobbuffet,,
162,Natu,,
163,Xatu,,
164,Girafarig,,
165,Phanpy,,
166,Donphan,,
167,Pinsir,,
168,Heracross,,
169,Rhyhorn,,
170,Rhydon,,
171,Snorunt,,
172,Glalie,,
173,Spheal,,
174,Sealeo,,
175,Walrein,,
176,Clamperl,,
177,Huntail,,
178,Gorebyss,,
179,Relicanth,,
180,Corsola,,
181,Chinchou,,
182,Lanturn,,
183,Luvdisc,,
184,Horsea,,
185,Seadra,,
186,Kingdra,,
187,Bagon,,
188,Shelgon,,
189,Salamence,,
190,Beldum,,
191,Metang,,
192,Metagross,,
193,Regirock,,
194,Regice,,
195,Registeel,,
196,Latias,,
197,Latios,,
198,Kyogre,,
199,Groudon,,
200,Rayquaza,,
201,Jirachi,,
202,Deoxys,,
1 dexNumber pokemon form notes
2 1 Treecko
3 2 Grovyle
4 3 Sceptile
5 4 Torchic
6 5 Combusken
7 6 Blaziken
8 7 Mudkip
9 8 Marshtomp
10 9 Swampert
11 10 Poochyena
12 11 Mightyena
13 12 Zigzagoon
14 13 Linoone
15 14 Wurmple
16 15 Silcoon
17 16 Beautifly
18 17 Cascoon
19 18 Dustox
20 19 Lotad
21 20 Lombre
22 21 Ludicolo
23 22 Seedot
24 23 Nuzleaf
25 24 Shiftry
26 25 Taillow
27 26 Swellow
28 27 Wingull
29 28 Pelipper
30 29 Ralts
31 30 Kirlia
32 31 Gardevoir
33 32 Surskit
34 33 Masquerain
35 34 Shroomish
36 35 Breloom
37 36 Slakoth
38 37 Vigoroth
39 38 Slaking
40 39 Abra
41 40 Kadabra
42 41 Alakazam
43 42 Nincada
44 43 Ninjask
45 44 Shedinja
46 45 Whismur
47 46 Loudred
48 47 Exploud
49 48 Makuhita
50 49 Hariyama
51 50 Goldeen
52 51 Seaking
53 52 Magikarp
54 53 Gyarados
55 54 Azurill
56 55 Marill
57 56 Azumarill
58 57 Geodude
59 58 Graveler
60 59 Golem
61 60 Nosepass
62 61 Skitty
63 62 Delcatty
64 63 Zubat
65 64 Golbat
66 65 Crobat
67 66 Tentacool
68 67 Tentacruel
69 68 Sableye
70 69 Mawile
71 70 Aron
72 71 Lairon
73 72 Aggron
74 73 Machop
75 74 Machoke
76 75 Machamp
77 76 Meditite
78 77 Medicham
79 78 Electrike
80 79 Manectric
81 80 Plusle
82 81 Minun
83 82 Magnemite
84 83 Magneton
85 84 Voltorb
86 85 Electrode
87 86 Volbeat
88 87 Illumise
89 88 Oddish
90 89 Gloom
91 90 Vileplume
92 91 Bellossom
93 92 Doduo
94 93 Dodrio
95 94 Roselia
96 95 Gulpin
97 96 Swalot
98 97 Carvanha
99 98 Sharpedo
100 99 Wailmer
101 100 Wailord
102 101 Numel
103 102 Camerupt
104 103 Slugma
105 104 Magcargo
106 105 Torkoal
107 106 Grimer
108 107 Muk
109 108 Koffing
110 109 Weezing
111 110 Spoink
112 111 Grumpig
113 112 Sandshrew
114 113 Sandslash
115 114 Spinda
116 115 Skarmory
117 116 Trapinch
118 117 Vibrava
119 118 Flygon
120 119 Cacnea
121 120 Cacturne
122 121 Swablu
123 122 Altaria
124 123 Zangoose
125 124 Seviper
126 125 Lunatone
127 126 Solrock
128 127 Barboach
129 128 Whiscash
130 129 Corphish
131 130 Crawdaunt
132 131 Baltoy
133 132 Claydol
134 133 Lileep
135 134 Cradily
136 135 Anorith
137 136 Armaldo
138 137 Igglybuff
139 138 Jigglypuff
140 139 Wigglytuff
141 140 Feebas
142 141 Milotic
143 142 Castform
144 143 Staryu
145 144 Starmie
146 145 Kecleon
147 146 Shuppet
148 147 Banette
149 148 Duskull
150 149 Dusclops
151 150 Tropius
152 151 Chimecho
153 152 Absol
154 153 Vulpix
155 154 Ninetales
156 155 Pichu
157 156 Pikachu
158 157 Raichu
159 158 Psyduck
160 159 Golduck
161 160 Wynaut
162 161 Wobbuffet
163 162 Natu
164 163 Xatu
165 164 Girafarig
166 165 Phanpy
167 166 Donphan
168 167 Pinsir
169 168 Heracross
170 169 Rhyhorn
171 170 Rhydon
172 171 Snorunt
173 172 Glalie
174 173 Spheal
175 174 Sealeo
176 175 Walrein
177 176 Clamperl
178 177 Huntail
179 178 Gorebyss
180 179 Relicanth
181 180 Corsola
182 181 Chinchou
183 182 Lanturn
184 183 Luvdisc
185 184 Horsea
186 185 Seadra
187 186 Kingdra
188 187 Bagon
189 188 Shelgon
190 189 Salamence
191 190 Beldum
192 191 Metang
193 192 Metagross
194 193 Regirock
195 194 Regice
196 195 Registeel
197 196 Latias
198 197 Latios
199 198 Kyogre
200 199 Groudon
201 200 Rayquaza
202 201 Jirachi
203 202 Deoxys
@@ -0,0 +1,244 @@
dexNumber,pokemon,form,notes
1,Doduo,,
2,Dodrio,,
3,Exeggcute,,
4,Exeggutor,,
5,Rhyhorn,,
6,Rhydon,,
7,Rhyperior,,
8,Venonat,,
9,Venomoth,,
10,Elekid,,
11,Electabuzz,,
12,Electivire,,
13,Magby,,
14,Magmar,,
15,Magmortar,,
16,Happiny,,
17,Chansey,,
18,Blissey,,
19,Scyther,,
20,Scizor,,
21,Kleavor,,
22,Tauros,,
23,Blitzle,,
24,Zebstrika,,
25,Girafarig,,
26,Farigiraf,,
27,Sandile,,
28,Krokorok,,
29,Krookodile,,
30,Rellor,,
31,Rabsca,,
32,Rufflet,,
33,Braviary,,
34,Vullaby,,
35,Mandibuzz,,
36,Litleo,,
37,Pyroar,,
38,Deerling,,
39,Sawsbuck,,
40,Smeargle,,
41,Rotom,,
42,Milcery,,
43,Alcremie,,
44,Trapinch,,
45,Vibrava,,
46,Flygon,,
47,Pikipek,,
48,Trumbeak,,
49,Toucannon,,
50,Tentacool,,
51,Tentacruel,,
52,Horsea,,
53,Seadra,,
54,Kingdra,,
55,Bruxish,,
56,Cottonee,,
57,Whimsicott,,
58,Comfey,,
59,Slakoth,,
60,Vigoroth,,
61,Slaking,,
62,Oddish,,
63,Gloom,,
64,Vileplume,,
65,Bellossom,,
66,Diglett,,
67,Dugtrio,,
68,Grimer,,
69,Muk,,
70,Zangoose,,
71,Seviper,,
72,Crabrawler,,
73,Crabominable,,
74,Oricorio,,
75,Slowpoke,,
76,Slowbro,,
77,Slowking,,
78,Chinchou,,
79,Lanturn,,
80,Inkay,,
81,Malamar,,
82,Luvdisc,,
83,Finneon,,
84,Lumineon,,
85,Alomomola,,
86,Torkoal,,
87,Fletchling,,
88,Fletchinder,,
89,Talonflame,,
90,Dewpider,,
91,Araquanid,,
92,Tyrogue,,
93,Hitmonlee,,
94,Hitmonchan,,
95,Hitmontop,,
96,Geodude,,
97,Graveler,,
98,Golem,,
99,Drilbur,,
100,Excadrill,,
101,Gothita,,
102,Gothorita,,
103,Gothitelle,,
104,Espurr,,
105,Meowstic,,
106,Minior,,
107,Cranidos,,
108,Rampardos,,
109,Shieldon,,
110,Bastiodon,,
111,Minccino,,
112,Cinccino,,
113,Skarmory,,
114,Swablu,,
115,Altaria,,
116,Magnemite,,
117,Magneton,,
118,Magnezone,,
119,Plusle,,
120,Minun,,
121,Scraggy,,
122,Scrafty,,
123,Golett,,
124,Golurk,,
125,Numel,,
126,Camerupt,,
127,Sinistea,,
128,Polteageist,,
129,Porygon,,
130,Porygon2,,
131,Porygon-Z,,
132,Joltik,,
133,Galvantula,,
134,Tynamo,,
135,Eelektrik,,
136,Eelektross,,
137,Beldum,,
138,Metang,,
139,Metagross,,
140,Axew,,
141,Fraxure,,
142,Haxorus,,
143,Seel,,
144,Dewgong,,
145,Lapras,,
146,Qwilfish,,
147,Overqwil,,
148,Solosis,,
149,Duosion,,
150,Reuniclus,,
151,Snubbull,,
152,Granbull,,
153,Cubchoo,,
154,Beartic,,
155,Sandshrew,,
156,Sandslash,,
157,Vulpix,,
158,Ninetales,,
159,Snover,,
160,Abomasnow,,
161,Duraludon,,
162,Archaludon,,
163,Hydrapple,,
164,Bulbasaur,,
165,Ivysaur,,
166,Venusaur,,
167,Charmander,,
168,Charmeleon,,
169,Charizard,,
170,Squirtle,,
171,Wartortle,,
172,Blastoise,,
173,Chikorita,,
174,Bayleef,,
175,Meganium,,
176,Cyndaquil,,
177,Quilava,,
178,Typhlosion,,
179,Totodile,,
180,Croconaw,,
181,Feraligatr,,
182,Treecko,,
183,Grovyle,,
184,Sceptile,,
185,Torchic,,
186,Combusken,,
187,Blaziken,,
188,Mudkip,,
189,Marshtomp,,
190,Swampert,,
191,Turtwig,,
192,Grotle,,
193,Torterra,,
194,Chimchar,,
195,Monferno,,
196,Infernape,,
197,Piplup,,
198,Prinplup,,
199,Empoleon,,
200,Snivy,,
201,Servine,,
202,Serperior,,
203,Tepig,,
204,Pignite,,
205,Emboar,,
206,Oshawott,,
207,Dewott,,
208,Samurott,,
209,Chespin,,
210,Quilladin,,
211,Chesnaught,,
212,Fennekin,,
213,Braixen,,
214,Delphox,,
215,Froakie,,
216,Frogadier,,
217,Greninja,,
218,Rowlet,,
219,Dartrix,,
220,Decidueye,,
221,Litten,,
222,Torracat,,
223,Incineroar,,
224,Popplio,,
225,Brionne,,
226,Primarina,,
227,Grookey,,
228,Thwackey,,
229,Rillaboom,,
230,Scorbunny,,
231,Raboot,,
232,Cinderace,,
233,Sobble,,
234,Drizzile,,
235,Inteleon,,
236,Gouging Fire,,
237,Raging Bolt,,
238,Iron Crown,,
239,Iron Boulder,,
240,Terapagos,,
241,Walking Wake,,
242,Iron Leaves,,
243,Pecharunt,,
1 dexNumber pokemon form notes
2 1 Doduo
3 2 Dodrio
4 3 Exeggcute
5 4 Exeggutor
6 5 Rhyhorn
7 6 Rhydon
8 7 Rhyperior
9 8 Venonat
10 9 Venomoth
11 10 Elekid
12 11 Electabuzz
13 12 Electivire
14 13 Magby
15 14 Magmar
16 15 Magmortar
17 16 Happiny
18 17 Chansey
19 18 Blissey
20 19 Scyther
21 20 Scizor
22 21 Kleavor
23 22 Tauros
24 23 Blitzle
25 24 Zebstrika
26 25 Girafarig
27 26 Farigiraf
28 27 Sandile
29 28 Krokorok
30 29 Krookodile
31 30 Rellor
32 31 Rabsca
33 32 Rufflet
34 33 Braviary
35 34 Vullaby
36 35 Mandibuzz
37 36 Litleo
38 37 Pyroar
39 38 Deerling
40 39 Sawsbuck
41 40 Smeargle
42 41 Rotom
43 42 Milcery
44 43 Alcremie
45 44 Trapinch
46 45 Vibrava
47 46 Flygon
48 47 Pikipek
49 48 Trumbeak
50 49 Toucannon
51 50 Tentacool
52 51 Tentacruel
53 52 Horsea
54 53 Seadra
55 54 Kingdra
56 55 Bruxish
57 56 Cottonee
58 57 Whimsicott
59 58 Comfey
60 59 Slakoth
61 60 Vigoroth
62 61 Slaking
63 62 Oddish
64 63 Gloom
65 64 Vileplume
66 65 Bellossom
67 66 Diglett
68 67 Dugtrio
69 68 Grimer
70 69 Muk
71 70 Zangoose
72 71 Seviper
73 72 Crabrawler
74 73 Crabominable
75 74 Oricorio
76 75 Slowpoke
77 76 Slowbro
78 77 Slowking
79 78 Chinchou
80 79 Lanturn
81 80 Inkay
82 81 Malamar
83 82 Luvdisc
84 83 Finneon
85 84 Lumineon
86 85 Alomomola
87 86 Torkoal
88 87 Fletchling
89 88 Fletchinder
90 89 Talonflame
91 90 Dewpider
92 91 Araquanid
93 92 Tyrogue
94 93 Hitmonlee
95 94 Hitmonchan
96 95 Hitmontop
97 96 Geodude
98 97 Graveler
99 98 Golem
100 99 Drilbur
101 100 Excadrill
102 101 Gothita
103 102 Gothorita
104 103 Gothitelle
105 104 Espurr
106 105 Meowstic
107 106 Minior
108 107 Cranidos
109 108 Rampardos
110 109 Shieldon
111 110 Bastiodon
112 111 Minccino
113 112 Cinccino
114 113 Skarmory
115 114 Swablu
116 115 Altaria
117 116 Magnemite
118 117 Magneton
119 118 Magnezone
120 119 Plusle
121 120 Minun
122 121 Scraggy
123 122 Scrafty
124 123 Golett
125 124 Golurk
126 125 Numel
127 126 Camerupt
128 127 Sinistea
129 128 Polteageist
130 129 Porygon
131 130 Porygon2
132 131 Porygon-Z
133 132 Joltik
134 133 Galvantula
135 134 Tynamo
136 135 Eelektrik
137 136 Eelektross
138 137 Beldum
139 138 Metang
140 139 Metagross
141 140 Axew
142 141 Fraxure
143 142 Haxorus
144 143 Seel
145 144 Dewgong
146 145 Lapras
147 146 Qwilfish
148 147 Overqwil
149 148 Solosis
150 149 Duosion
151 150 Reuniclus
152 151 Snubbull
153 152 Granbull
154 153 Cubchoo
155 154 Beartic
156 155 Sandshrew
157 156 Sandslash
158 157 Vulpix
159 158 Ninetales
160 159 Snover
161 160 Abomasnow
162 161 Duraludon
163 162 Archaludon
164 163 Hydrapple
165 164 Bulbasaur
166 165 Ivysaur
167 166 Venusaur
168 167 Charmander
169 168 Charmeleon
170 169 Charizard
171 170 Squirtle
172 171 Wartortle
173 172 Blastoise
174 173 Chikorita
175 174 Bayleef
176 175 Meganium
177 176 Cyndaquil
178 177 Quilava
179 178 Typhlosion
180 179 Totodile
181 180 Croconaw
182 181 Feraligatr
183 182 Treecko
184 183 Grovyle
185 184 Sceptile
186 185 Torchic
187 186 Combusken
188 187 Blaziken
189 188 Mudkip
190 189 Marshtomp
191 190 Swampert
192 191 Turtwig
193 192 Grotle
194 193 Torterra
195 194 Chimchar
196 195 Monferno
197 196 Infernape
198 197 Piplup
199 198 Prinplup
200 199 Empoleon
201 200 Snivy
202 201 Servine
203 202 Serperior
204 203 Tepig
205 204 Pignite
206 205 Emboar
207 206 Oshawott
208 207 Dewott
209 208 Samurott
210 209 Chespin
211 210 Quilladin
212 211 Chesnaught
213 212 Fennekin
214 213 Braixen
215 214 Delphox
216 215 Froakie
217 216 Frogadier
218 217 Greninja
219 218 Rowlet
220 219 Dartrix
221 220 Decidueye
222 221 Litten
223 222 Torracat
224 223 Incineroar
225 224 Popplio
226 225 Brionne
227 226 Primarina
228 227 Grookey
229 228 Thwackey
230 229 Rillaboom
231 230 Scorbunny
232 231 Raboot
233 232 Cinderace
234 233 Sobble
235 234 Drizzile
236 235 Inteleon
237 236 Gouging Fire
238 237 Raging Bolt
239 238 Iron Crown
240 239 Iron Boulder
241 240 Terapagos
242 241 Walking Wake
243 242 Iron Leaves
244 243 Pecharunt
@@ -0,0 +1,201 @@
dexNumber,pokemon,form,notes
1,Spinarak,,
2,Ariados,,
3,Yanma,,
4,Yanmega,,
5,Wooper,,
6,Quagsire,,
7,Poochyena,,
8,Mightyena,,
9,Volbeat,,
10,Illumise,,
11,Corphish,,
12,Crawdaunt,,
13,Sewaddle,,
14,Swadloon,,
15,Leavanny,,
16,Cutiefly,,
17,Ribombee,,
18,Ekans,,
19,Arbok,,
20,Pichu,,
21,Pikachu,,
22,Raichu,,
23,Bellsprout,,
24,Weepinbell,,
25,Victreebel,,
26,Sentret,,
27,Furret,,
28,Starly,,
29,Staravia,,
30,Staraptor,,
31,Fomantis,,
32,Lurantis,,
33,Applin,,
34,Flapple,,
35,Appletun,,
36,Dipplin,,
37,Vulpix,,
38,Ninetales,,
39,Poliwag,,
40,Poliwhirl,,
41,Poliwrath,,
42,Politoed,,
43,Magikarp,,
44,Gyarados,,
45,Hoothoot,,
46,Noctowl,,
47,Aipom,,
48,Ambipom,,
49,Heracross,,
50,Swinub,,
51,Piloswine,,
52,Mamoswine,,
53,Stantler,,
54,Seedot,,
55,Nuzleaf,,
56,Shiftry,,
57,Ralts,,
58,Kirlia,,
59,Gardevoir,,
60,Gallade,,
61,Kricketot,,
62,Kricketune,,
63,Pachirisu,,
64,Riolu,,
65,Lucario,,
66,Petilil,,
67,Lilligant,,
68,Phantump,,
69,Trevenant,,
70,Rockruff,,
71,Lycanroc,,
72,Skwovet,,
73,Greedent,,
74,Toedscool,,
75,Toedscruel,,
76,Poltchageist,,
77,Sinistcha,,
78,Growlithe,,
79,Arcanine,,
80,Geodude,,
81,Graveler,,
82,Golem,,
83,Bonsly,,
84,Sudowoodo,,
85,Timburr,,
86,Gurdurr,,
87,Conkeldurr,,
88,Noibat,,
89,Noivern,,
90,Arrokuda,,
91,Barraskewda,,
92,Hatenna,,
93,Hattrem,,
94,Hatterene,,
95,Morpeko,,
96,Orthworm,,
97,Tandemaus,,
98,Maushold,,
99,Mankey,,
100,Primeape,,
101,Annihilape,,
102,Munchlax,,
103,Snorlax,,
104,Lotad,,
105,Lombre,,
106,Ludicolo,,
107,Nosepass,,
108,Probopass,,
109,Shinx,,
110,Luxio,,
111,Luxray,,
112,Grubbin,,
113,Charjabug,,
114,Vikavolt,,
115,Oricorio,,
116,Sandshrew,,
117,Sandslash,,
118,Gastly,,
119,Haunter,,
120,Gengar,,
121,Gligar,,
122,Gliscor,,
123,Houndour,,
124,Houndoom,,
125,Spoink,,
126,Grumpig,,
127,Vullaby,,
128,Mandibuzz,,
129,Mudbray,,
130,Mudsdale,,
131,Jangmo-o,,
132,Hakamo-o,,
133,Kommo-o,,
134,Bombirdier,,
135,Koffing,,
136,Weezing,,
137,Mienfoo,,
138,Mienshao,,
139,Duskull,,
140,Dusclops,,
141,Dusknoir,,
142,Chingling,,
143,Chimecho,,
144,Slugma,,
145,Magcargo,,
146,Litwick,,
147,Lampent,,
148,Chandelure,,
149,Surskit,,
150,Masquerain,,
151,Cleffa,,
152,Clefairy,,
153,Clefable,,
154,Bronzor,,
155,Bronzong,,
156,Glimmet,,
157,Glimmora,,
158,Feebas,,
159,Milotic,,
160,Dunsparce,,
161,Dudunsparce,,
162,Barboach,,
163,Whiscash,,
164,Gible,,
165,Gabite,,
166,Garchomp,,
167,Carbink,,
168,Salandit,,
169,Salazzle,,
170,Sneasel,,
171,Weavile,,
172,Snorunt,,
173,Glalie,,
174,Froslass,,
175,Tynamo,,
176,Eelektrik,,
177,Eelektross,,
178,Goomy,,
179,Sliggoo,,
180,Goodra,,
181,Ducklett,,
182,Swanna,,
183,Chewtle,,
184,Drednaw,,
185,Cramorant,,
186,Pawniard,,
187,Bisharp,,
188,Kingambit,,
189,Mimikyu,,
190,Impidimp,,
191,Morgrem,,
192,Grimmsnarl,,
193,Indeedee,,
194,Basculin,,
195,Basculegion,,
196,Ursaluna,,
197,Okidogi,,
198,Munkidori,,
199,Fezandipiti,,
200,Ogerpon,,
1 dexNumber pokemon form notes
2 1 Spinarak
3 2 Ariados
4 3 Yanma
5 4 Yanmega
6 5 Wooper
7 6 Quagsire
8 7 Poochyena
9 8 Mightyena
10 9 Volbeat
11 10 Illumise
12 11 Corphish
13 12 Crawdaunt
14 13 Sewaddle
15 14 Swadloon
16 15 Leavanny
17 16 Cutiefly
18 17 Ribombee
19 18 Ekans
20 19 Arbok
21 20 Pichu
22 21 Pikachu
23 22 Raichu
24 23 Bellsprout
25 24 Weepinbell
26 25 Victreebel
27 26 Sentret
28 27 Furret
29 28 Starly
30 29 Staravia
31 30 Staraptor
32 31 Fomantis
33 32 Lurantis
34 33 Applin
35 34 Flapple
36 35 Appletun
37 36 Dipplin
38 37 Vulpix
39 38 Ninetales
40 39 Poliwag
41 40 Poliwhirl
42 41 Poliwrath
43 42 Politoed
44 43 Magikarp
45 44 Gyarados
46 45 Hoothoot
47 46 Noctowl
48 47 Aipom
49 48 Ambipom
50 49 Heracross
51 50 Swinub
52 51 Piloswine
53 52 Mamoswine
54 53 Stantler
55 54 Seedot
56 55 Nuzleaf
57 56 Shiftry
58 57 Ralts
59 58 Kirlia
60 59 Gardevoir
61 60 Gallade
62 61 Kricketot
63 62 Kricketune
64 63 Pachirisu
65 64 Riolu
66 65 Lucario
67 66 Petilil
68 67 Lilligant
69 68 Phantump
70 69 Trevenant
71 70 Rockruff
72 71 Lycanroc
73 72 Skwovet
74 73 Greedent
75 74 Toedscool
76 75 Toedscruel
77 76 Poltchageist
78 77 Sinistcha
79 78 Growlithe
80 79 Arcanine
81 80 Geodude
82 81 Graveler
83 82 Golem
84 83 Bonsly
85 84 Sudowoodo
86 85 Timburr
87 86 Gurdurr
88 87 Conkeldurr
89 88 Noibat
90 89 Noivern
91 90 Arrokuda
92 91 Barraskewda
93 92 Hatenna
94 93 Hattrem
95 94 Hatterene
96 95 Morpeko
97 96 Orthworm
98 97 Tandemaus
99 98 Maushold
100 99 Mankey
101 100 Primeape
102 101 Annihilape
103 102 Munchlax
104 103 Snorlax
105 104 Lotad
106 105 Lombre
107 106 Ludicolo
108 107 Nosepass
109 108 Probopass
110 109 Shinx
111 110 Luxio
112 111 Luxray
113 112 Grubbin
114 113 Charjabug
115 114 Vikavolt
116 115 Oricorio
117 116 Sandshrew
118 117 Sandslash
119 118 Gastly
120 119 Haunter
121 120 Gengar
122 121 Gligar
123 122 Gliscor
124 123 Houndour
125 124 Houndoom
126 125 Spoink
127 126 Grumpig
128 127 Vullaby
129 128 Mandibuzz
130 129 Mudbray
131 130 Mudsdale
132 131 Jangmo-o
133 132 Hakamo-o
134 133 Kommo-o
135 134 Bombirdier
136 135 Koffing
137 136 Weezing
138 137 Mienfoo
139 138 Mienshao
140 139 Duskull
141 140 Dusclops
142 141 Dusknoir
143 142 Chingling
144 143 Chimecho
145 144 Slugma
146 145 Magcargo
147 146 Litwick
148 147 Lampent
149 148 Chandelure
150 149 Surskit
151 150 Masquerain
152 151 Cleffa
153 152 Clefairy
154 153 Clefable
155 154 Bronzor
156 155 Bronzong
157 156 Glimmet
158 157 Glimmora
159 158 Feebas
160 159 Milotic
161 160 Dunsparce
162 161 Dudunsparce
163 162 Barboach
164 163 Whiscash
165 164 Gible
166 165 Gabite
167 166 Garchomp
168 167 Carbink
169 168 Salandit
170 169 Salazzle
171 170 Sneasel
172 171 Weavile
173 172 Snorunt
174 173 Glalie
175 174 Froslass
176 175 Tynamo
177 176 Eelektrik
178 177 Eelektross
179 178 Goomy
180 179 Sliggoo
181 180 Goodra
182 181 Ducklett
183 182 Swanna
184 183 Chewtle
185 184 Drednaw
186 185 Cramorant
187 186 Pawniard
188 187 Bisharp
189 188 Kingambit
190 189 Mimikyu
191 190 Impidimp
192 191 Morgrem
193 192 Grimmsnarl
194 193 Indeedee
195 194 Basculin
196 195 Basculegion
197 196 Ursaluna
198 197 Okidogi
199 198 Munkidori
200 199 Fezandipiti
201 200 Ogerpon
@@ -0,0 +1,401 @@
dexNumber,pokemon,form,notes
1,Sprigatito,,
2,Floragato,,
3,Meowscarada,,
4,Fuecoco,,
5,Crocalor,,
6,Skeledirge,,
7,Quaxly,,
8,Quaxwell,,
9,Quaquaval,,
10,Lechonk,,
11,Oinkologne,,
12,Tarountula,,
13,Spidops,,
14,Nymble,,
15,Lokix,,
16,Hoppip,,
17,Skiploom,,
18,Jumpluff,,
19,Fletchling,,
20,Fletchinder,,
21,Talonflame,,
22,Pawmi,,
23,Pawmo,,
24,Pawmot,,
25,Houndour,,
26,Houndoom,,
27,Yungoos,,
28,Gumshoos,,
29,Skwovet,,
30,Greedent,,
31,Sunkern,,
32,Sunflora,,
33,Kricketot,,
34,Kricketune,,
35,Scatterbug,,
36,Spewpa,,
37,Vivillon,,
38,Combee,,
39,Vespiquen,,
40,Rookidee,,
41,Corvisquire,,
42,Corviknight,,
43,Happiny,,
44,Chansey,,
45,Blissey,,
46,Azurill,,
47,Marill,,
48,Azumarill,,
49,Surskit,,
50,Masquerain,,
51,Buizel,,
52,Floatzel,,
53,Wooper,,
54,Clodsire,,
55,Psyduck,,
56,Golduck,,
57,Chewtle,,
58,Drednaw,,
59,Igglybuff,,
60,Jigglypuff,,
61,Wigglytuff,,
62,Ralts,,
63,Kirlia,,
64,Gardevoir,,
65,Gallade,,
66,Drowzee,,
67,Hypno,,
68,Gastly,,
69,Haunter,,
70,Gengar,,
71,Tandemaus,,
72,Maushold,,
73,Pichu,,
74,Pikachu,,
75,Raichu,,
76,Fidough,,
77,Dachsbun,,
78,Slakoth,,
79,Vigoroth,,
80,Slaking,,
81,Bounsweet,,
82,Steenee,,
83,Tsareena,,
84,Smoliv,,
85,Dolliv,,
86,Arboliva,,
87,Bonsly,,
88,Sudowoodo,,
89,Rockruff,,
90,Lycanroc,,
91,Rolycoly,,
92,Carkol,,
93,Coalossal,,
94,Shinx,,
95,Luxio,,
96,Luxray,,
97,Starly,,
98,Staravia,,
99,Staraptor,,
100,Oricorio,,
101,Mareep,,
102,Flaaffy,,
103,Ampharos,,
104,Petilil,,
105,Lilligant,,
106,Shroomish,,
107,Breloom,,
108,Applin,,
109,Flapple,,
110,Appletun,,
111,Spoink,,
112,Grumpig,,
113,Squawkabilly,,
114,Misdreavus,,
115,Mismagius,,
116,Makuhita,,
117,Hariyama,,
118,Crabrawler,,
119,Crabominable,,
120,Salandit,,
121,Salazzle,,
122,Phanpy,,
123,Donphan,,
124,Cufant,,
125,Copperajah,,
126,Gible,,
127,Gabite,,
128,Garchomp,,
129,Nacli,,
130,Naclstack,,
131,Garganacl,,
132,Wingull,,
133,Pelipper,,
134,Magikarp,,
135,Gyarados,,
136,Arrokuda,,
137,Barraskewda,,
138,Basculin,,
139,Gulpin,,
140,Swalot,,
141,Meowth,,
142,Persian,,
143,Drifloon,,
144,Drifblim,,
145,Flabébé,,
146,Floette,,
147,Florges,,
148,Diglett,,
149,Dugtrio,,
150,Torkoal,,
151,Numel,,
152,Camerupt,,
153,Bronzor,,
154,Bronzong,,
155,Axew,,
156,Fraxure,,
157,Haxorus,,
158,Mankey,,
159,Primeape,,
160,Annihilape,,
161,Meditite,,
162,Medicham,,
163,Riolu,,
164,Lucario,,
165,Charcadet,,
166,Armarouge,,
167,Ceruledge,,
168,Barboach,,
169,Whiscash,,
170,Tadbulb,,
171,Bellibolt,,
172,Goomy,,
173,Sliggoo,,
174,Goodra,,
175,Croagunk,,
176,Toxicroak,,
177,Wattrel,,
178,Kilowattrel,,
179,Eevee,,
180,Vaporeon,,
181,Jolteon,,
182,Flareon,,
183,Espeon,,
184,Umbreon,,
185,Leafeon,,
186,Glaceon,,
187,Sylveon,,
188,Dunsparce,,
189,Dudunsparce,,
190,Deerling,,
191,Sawsbuck,,
192,Girafarig,,
193,Farigiraf,,
194,Grimer,,
195,Muk,,
196,Maschiff,,
197,Mabosstiff,,
198,Toxel,,
199,Toxtricity,,
200,Dedenne,,
201,Pachirisu,,
202,Shroodle,,
203,Grafaiai,,
204,Stantler,,
205,Foongus,,
206,Amoonguss,,
207,Voltorb,,
208,Electrode,,
209,Magnemite,,
210,Magneton,,
211,Magnezone,,
212,Ditto,,
213,Growlithe,,
214,Arcanine,,
215,Teddiursa,,
216,Ursaring,,
217,Zangoose,,
218,Seviper,,
219,Swablu,,
220,Altaria,,
221,Skiddo,,
222,Gogoat,,
223,Tauros,,
224,Litleo,,
225,Pyroar,,
226,Stunky,,
227,Skuntank,,
228,Zorua,,
229,Zoroark,,
230,Sneasel,,
231,Weavile,,
232,Murkrow,,
233,Honchkrow,,
234,Gothita,,
235,Gothorita,,
236,Gothitelle,,
237,Sinistea,,
238,Polteageist,,
239,Mimikyu,,
240,Klefki,,
241,Indeedee,,
242,Bramblin,,
243,Brambleghast,,
244,Toedscool,,
245,Toedscruel,,
246,Tropius,,
247,Fomantis,,
248,Lurantis,,
249,Klawf,,
250,Capsakid,,
251,Scovillain,,
252,Cacnea,,
253,Cacturne,,
254,Rellor,,
255,Rabsca,,
256,Venonat,,
257,Venomoth,,
258,Pineco,,
259,Forretress,,
260,Scyther,,
261,Scizor,,
262,Heracross,,
263,Flittle,,
264,Espathra,,
265,Hippopotas,,
266,Hippowdon,,
267,Sandile,,
268,Krokorok,,
269,Krookodile,,
270,Silicobra,,
271,Sandaconda,,
272,Mudbray,,
273,Mudsdale,,
274,Larvesta,,
275,Volcarona,,
276,Bagon,,
277,Shelgon,,
278,Salamence,,
279,Tinkatink,,
280,Tinkatuff,,
281,Tinkaton,,
282,Hatenna,,
283,Hattrem,,
284,Hatterene,,
285,Impidimp,,
286,Morgrem,,
287,Grimmsnarl,,
288,Wiglett,,
289,Wugtrio,,
290,Bombirdier,,
291,Finizen,,
292,Palafin,,
293,Varoom,,
294,Revavroom,,
295,Cyclizar,,
296,Orthworm,,
297,Sableye,,
298,Shuppet,,
299,Banette,,
300,Falinks,,
301,Hawlucha,,
302,Spiritomb,,
303,Noibat,,
304,Noivern,,
305,Dreepy,,
306,Drakloak,,
307,Dragapult,,
308,Glimmet,,
309,Glimmora,,
310,Rotom,,
311,Greavard,,
312,Houndstone,,
313,Oranguru,,
314,Passimian,,
315,Komala,,
316,Larvitar,,
317,Pupitar,,
318,Tyranitar,,
319,Stonjourner,,
320,Eiscue,,
321,Pincurchin,,
322,Sandygast,,
323,Palossand,,
324,Slowpoke,,
325,Slowbro,,
326,Slowking,,
327,Shellos,,
328,Gastrodon,,
329,Shellder,,
330,Cloyster,,
331,Qwilfish,,
332,Luvdisc,,
333,Finneon,,
334,Lumineon,,
335,Bruxish,,
336,Alomomola,,
337,Skrelp,,
338,Dragalge,,
339,Clauncher,,
340,Clawitzer,,
341,Tynamo,,
342,Eelektrik,,
343,Eelektross,,
344,Mareanie,,
345,Toxapex,,
346,Flamigo,,
347,Dratini,,
348,Dragonair,,
349,Dragonite,,
350,Snom,,
351,Frosmoth,,
352,Snover,,
353,Abomasnow,,
354,Delibird,,
355,Cubchoo,,
356,Beartic,,
357,Snorunt,,
358,Glalie,,
359,Froslass,,
360,Cryogonal,,
361,Cetoddle,,
362,Cetitan,,
363,Bergmite,,
364,Avalugg,,
365,Rufflet,,
366,Braviary,,
367,Pawniard,,
368,Bisharp,,
369,Kingambit,,
370,Deino,,
371,Zweilous,,
372,Hydreigon,,
373,Veluza,,
374,Dondozo,,
375,Tatsugiri,,
376,Great Tusk,,
377,Scream Tail,,
378,Brute Bonnet,,
379,Flutter Mane,,
380,Slither Wing,,
381,Sandy Shocks,,
382,Iron Treads,,
383,Iron Bundle,,
384,Iron Hands,,
385,Iron Jugulis,,
386,Iron Moth,,
387,Iron Thorns,,
388,Frigibax,,
389,Arctibax,,
390,Baxcalibur,,
391,Gimmighoul,,
392,Gholdengo,,
393,Wo-Chien,,
394,Chien-Pao,,
395,Ting-Lu,,
396,Chi-Yu,,
397,Roaring Moon,,
398,Iron Valiant,,
399,Koraidon,,
400,Miraidon,,
1 dexNumber pokemon form notes
2 1 Sprigatito
3 2 Floragato
4 3 Meowscarada
5 4 Fuecoco
6 5 Crocalor
7 6 Skeledirge
8 7 Quaxly
9 8 Quaxwell
10 9 Quaquaval
11 10 Lechonk
12 11 Oinkologne
13 12 Tarountula
14 13 Spidops
15 14 Nymble
16 15 Lokix
17 16 Hoppip
18 17 Skiploom
19 18 Jumpluff
20 19 Fletchling
21 20 Fletchinder
22 21 Talonflame
23 22 Pawmi
24 23 Pawmo
25 24 Pawmot
26 25 Houndour
27 26 Houndoom
28 27 Yungoos
29 28 Gumshoos
30 29 Skwovet
31 30 Greedent
32 31 Sunkern
33 32 Sunflora
34 33 Kricketot
35 34 Kricketune
36 35 Scatterbug
37 36 Spewpa
38 37 Vivillon
39 38 Combee
40 39 Vespiquen
41 40 Rookidee
42 41 Corvisquire
43 42 Corviknight
44 43 Happiny
45 44 Chansey
46 45 Blissey
47 46 Azurill
48 47 Marill
49 48 Azumarill
50 49 Surskit
51 50 Masquerain
52 51 Buizel
53 52 Floatzel
54 53 Wooper
55 54 Clodsire
56 55 Psyduck
57 56 Golduck
58 57 Chewtle
59 58 Drednaw
60 59 Igglybuff
61 60 Jigglypuff
62 61 Wigglytuff
63 62 Ralts
64 63 Kirlia
65 64 Gardevoir
66 65 Gallade
67 66 Drowzee
68 67 Hypno
69 68 Gastly
70 69 Haunter
71 70 Gengar
72 71 Tandemaus
73 72 Maushold
74 73 Pichu
75 74 Pikachu
76 75 Raichu
77 76 Fidough
78 77 Dachsbun
79 78 Slakoth
80 79 Vigoroth
81 80 Slaking
82 81 Bounsweet
83 82 Steenee
84 83 Tsareena
85 84 Smoliv
86 85 Dolliv
87 86 Arboliva
88 87 Bonsly
89 88 Sudowoodo
90 89 Rockruff
91 90 Lycanroc
92 91 Rolycoly
93 92 Carkol
94 93 Coalossal
95 94 Shinx
96 95 Luxio
97 96 Luxray
98 97 Starly
99 98 Staravia
100 99 Staraptor
101 100 Oricorio
102 101 Mareep
103 102 Flaaffy
104 103 Ampharos
105 104 Petilil
106 105 Lilligant
107 106 Shroomish
108 107 Breloom
109 108 Applin
110 109 Flapple
111 110 Appletun
112 111 Spoink
113 112 Grumpig
114 113 Squawkabilly
115 114 Misdreavus
116 115 Mismagius
117 116 Makuhita
118 117 Hariyama
119 118 Crabrawler
120 119 Crabominable
121 120 Salandit
122 121 Salazzle
123 122 Phanpy
124 123 Donphan
125 124 Cufant
126 125 Copperajah
127 126 Gible
128 127 Gabite
129 128 Garchomp
130 129 Nacli
131 130 Naclstack
132 131 Garganacl
133 132 Wingull
134 133 Pelipper
135 134 Magikarp
136 135 Gyarados
137 136 Arrokuda
138 137 Barraskewda
139 138 Basculin
140 139 Gulpin
141 140 Swalot
142 141 Meowth
143 142 Persian
144 143 Drifloon
145 144 Drifblim
146 145 Flabébé
147 146 Floette
148 147 Florges
149 148 Diglett
150 149 Dugtrio
151 150 Torkoal
152 151 Numel
153 152 Camerupt
154 153 Bronzor
155 154 Bronzong
156 155 Axew
157 156 Fraxure
158 157 Haxorus
159 158 Mankey
160 159 Primeape
161 160 Annihilape
162 161 Meditite
163 162 Medicham
164 163 Riolu
165 164 Lucario
166 165 Charcadet
167 166 Armarouge
168 167 Ceruledge
169 168 Barboach
170 169 Whiscash
171 170 Tadbulb
172 171 Bellibolt
173 172 Goomy
174 173 Sliggoo
175 174 Goodra
176 175 Croagunk
177 176 Toxicroak
178 177 Wattrel
179 178 Kilowattrel
180 179 Eevee
181 180 Vaporeon
182 181 Jolteon
183 182 Flareon
184 183 Espeon
185 184 Umbreon
186 185 Leafeon
187 186 Glaceon
188 187 Sylveon
189 188 Dunsparce
190 189 Dudunsparce
191 190 Deerling
192 191 Sawsbuck
193 192 Girafarig
194 193 Farigiraf
195 194 Grimer
196 195 Muk
197 196 Maschiff
198 197 Mabosstiff
199 198 Toxel
200 199 Toxtricity
201 200 Dedenne
202 201 Pachirisu
203 202 Shroodle
204 203 Grafaiai
205 204 Stantler
206 205 Foongus
207 206 Amoonguss
208 207 Voltorb
209 208 Electrode
210 209 Magnemite
211 210 Magneton
212 211 Magnezone
213 212 Ditto
214 213 Growlithe
215 214 Arcanine
216 215 Teddiursa
217 216 Ursaring
218 217 Zangoose
219 218 Seviper
220 219 Swablu
221 220 Altaria
222 221 Skiddo
223 222 Gogoat
224 223 Tauros
225 224 Litleo
226 225 Pyroar
227 226 Stunky
228 227 Skuntank
229 228 Zorua
230 229 Zoroark
231 230 Sneasel
232 231 Weavile
233 232 Murkrow
234 233 Honchkrow
235 234 Gothita
236 235 Gothorita
237 236 Gothitelle
238 237 Sinistea
239 238 Polteageist
240 239 Mimikyu
241 240 Klefki
242 241 Indeedee
243 242 Bramblin
244 243 Brambleghast
245 244 Toedscool
246 245 Toedscruel
247 246 Tropius
248 247 Fomantis
249 248 Lurantis
250 249 Klawf
251 250 Capsakid
252 251 Scovillain
253 252 Cacnea
254 253 Cacturne
255 254 Rellor
256 255 Rabsca
257 256 Venonat
258 257 Venomoth
259 258 Pineco
260 259 Forretress
261 260 Scyther
262 261 Scizor
263 262 Heracross
264 263 Flittle
265 264 Espathra
266 265 Hippopotas
267 266 Hippowdon
268 267 Sandile
269 268 Krokorok
270 269 Krookodile
271 270 Silicobra
272 271 Sandaconda
273 272 Mudbray
274 273 Mudsdale
275 274 Larvesta
276 275 Volcarona
277 276 Bagon
278 277 Shelgon
279 278 Salamence
280 279 Tinkatink
281 280 Tinkatuff
282 281 Tinkaton
283 282 Hatenna
284 283 Hattrem
285 284 Hatterene
286 285 Impidimp
287 286 Morgrem
288 287 Grimmsnarl
289 288 Wiglett
290 289 Wugtrio
291 290 Bombirdier
292 291 Finizen
293 292 Palafin
294 293 Varoom
295 294 Revavroom
296 295 Cyclizar
297 296 Orthworm
298 297 Sableye
299 298 Shuppet
300 299 Banette
301 300 Falinks
302 301 Hawlucha
303 302 Spiritomb
304 303 Noibat
305 304 Noivern
306 305 Dreepy
307 306 Drakloak
308 307 Dragapult
309 308 Glimmet
310 309 Glimmora
311 310 Rotom
312 311 Greavard
313 312 Houndstone
314 313 Oranguru
315 314 Passimian
316 315 Komala
317 316 Larvitar
318 317 Pupitar
319 318 Tyranitar
320 319 Stonjourner
321 320 Eiscue
322 321 Pincurchin
323 322 Sandygast
324 323 Palossand
325 324 Slowpoke
326 325 Slowbro
327 326 Slowking
328 327 Shellos
329 328 Gastrodon
330 329 Shellder
331 330 Cloyster
332 331 Qwilfish
333 332 Luvdisc
334 333 Finneon
335 334 Lumineon
336 335 Bruxish
337 336 Alomomola
338 337 Skrelp
339 338 Dragalge
340 339 Clauncher
341 340 Clawitzer
342 341 Tynamo
343 342 Eelektrik
344 343 Eelektross
345 344 Mareanie
346 345 Toxapex
347 346 Flamigo
348 347 Dratini
349 348 Dragonair
350 349 Dragonite
351 350 Snom
352 351 Frosmoth
353 352 Snover
354 353 Abomasnow
355 354 Delibird
356 355 Cubchoo
357 356 Beartic
358 357 Snorunt
359 358 Glalie
360 359 Froslass
361 360 Cryogonal
362 361 Cetoddle
363 362 Cetitan
364 363 Bergmite
365 364 Avalugg
366 365 Rufflet
367 366 Braviary
368 367 Pawniard
369 368 Bisharp
370 369 Kingambit
371 370 Deino
372 371 Zweilous
373 372 Hydreigon
374 373 Veluza
375 374 Dondozo
376 375 Tatsugiri
377 376 Great Tusk
378 377 Scream Tail
379 378 Brute Bonnet
380 379 Flutter Mane
381 380 Slither Wing
382 381 Sandy Shocks
383 382 Iron Treads
384 383 Iron Bundle
385 384 Iron Hands
386 385 Iron Jugulis
387 386 Iron Moth
388 387 Iron Thorns
389 388 Frigibax
390 389 Arctibax
391 390 Baxcalibur
392 391 Gimmighoul
393 392 Gholdengo
394 393 Wo-Chien
395 394 Chien-Pao
396 395 Ting-Lu
397 396 Chi-Yu
398 397 Roaring Moon
399 398 Iron Valiant
400 399 Koraidon
401 400 Miraidon
@@ -0,0 +1,131 @@
dexNumber,pokemon,form,notes
1,Pikipek,,
2,Trumbeak,,
3,Toucannon,,
4,Yungoos,,
5,Gumshoos,,
6,Rattata,,
7,Raticate,,
8,Caterpie,,
9,Metapod,,
10,Butterfree,,
11,Grubbin,,
12,Charjabug,,
13,Vikavolt,,
14,Bonsly,,
15,Sudowoodo,,
16,Happiny,,
17,Chansey,,
18,Blissey,,
19,Wingull,,
20,Pelipper,,
21,Crabrawler,,
22,Crabominable,,
23,Gastly,,
24,Haunter,,
25,Gengar,,
26,Zubat,,
27,Golbat,,
28,Crobat,,
29,Diglett,,
30,Dugtrio,,
31,Oricorio,,
32,Psyduck,,
33,Golduck,,
34,Magikarp,,
35,Gyarados,,
36,Barboach,,
37,Whiscash,,
38,Tentacool,,
39,Tentacruel,,
40,Finneon,,
41,Lumineon,,
42,Wishiwashi,,
43,Luvdisc,,
44,Corsola,,
45,Mareanie,,
46,Toxapex,,
47,Lillipup,,
48,Herdier,,
49,Stoutland,,
50,Eevee,,
51,Vaporeon,,
52,Jolteon,,
53,Flareon,,
54,Espeon,,
55,Umbreon,,
56,Leafeon,,
57,Glaceon,,
58,Sylveon,,
59,Mudbray,,
60,Mudsdale,,
61,Igglybuff,,
62,Jigglypuff,,
63,Wigglytuff,,
64,Tauros,,
65,Miltank,,
66,Surskit,,
67,Masquerain,,
68,Dewpider,,
69,Araquanid,,
70,Fomantis,,
71,Lurantis,,
72,Morelull,,
73,Shiinotic,,
74,Paras,,
75,Parasect,,
76,Poliwag,,
77,Poliwhirl,,
78,Poliwrath,,
79,Politoed,,
80,Goldeen,,
81,Seaking,,
82,Feebas,,
83,Milotic,,
84,Alomomola,,
85,Fletchling,,
86,Fletchinder,,
87,Talonflame,,
88,Salandit,,
89,Salazzle,,
90,Cubone,,
91,Marowak,,
92,Kangaskhan,,
93,Magby,,
94,Magmar,,
95,Magmortar,,
96,Stufful,,
97,Bewear,,
98,Bounsweet,,
99,Steenee,,
100,Tsareena,,
101,Comfey,,
102,Pinsir,,
103,Oranguru,,
104,Passimian,,
105,Goomy,,
106,Sliggoo,,
107,Goodra,,
108,Castform,,
109,Wimpod,,
110,Golisopod,,
111,Staryu,,
112,Starmie,,
113,Sandygast,,
114,Palossand,,
115,Cranidos,,
116,Rampardos,,
117,Shieldon,,
118,Bastiodon,,
119,Archen,,
120,Archeops,,
121,Tirtouga,,
122,Carracosta,,
123,Phantump,,
124,Trevenant,,
125,Nosepass,,
126,Probopass,,
127,Pyukumuku,,
128,Chinchou,,
129,Lanturn,,
130,Tapu Lele,,
1 dexNumber pokemon form notes
2 1 Pikipek
3 2 Trumbeak
4 3 Toucannon
5 4 Yungoos
6 5 Gumshoos
7 6 Rattata
8 7 Raticate
9 8 Caterpie
10 9 Metapod
11 10 Butterfree
12 11 Grubbin
13 12 Charjabug
14 13 Vikavolt
15 14 Bonsly
16 15 Sudowoodo
17 16 Happiny
18 17 Chansey
19 18 Blissey
20 19 Wingull
21 20 Pelipper
22 21 Crabrawler
23 22 Crabominable
24 23 Gastly
25 24 Haunter
26 25 Gengar
27 26 Zubat
28 27 Golbat
29 28 Crobat
30 29 Diglett
31 30 Dugtrio
32 31 Oricorio
33 32 Psyduck
34 33 Golduck
35 34 Magikarp
36 35 Gyarados
37 36 Barboach
38 37 Whiscash
39 38 Tentacool
40 39 Tentacruel
41 40 Finneon
42 41 Lumineon
43 42 Wishiwashi
44 43 Luvdisc
45 44 Corsola
46 45 Mareanie
47 46 Toxapex
48 47 Lillipup
49 48 Herdier
50 49 Stoutland
51 50 Eevee
52 51 Vaporeon
53 52 Jolteon
54 53 Flareon
55 54 Espeon
56 55 Umbreon
57 56 Leafeon
58 57 Glaceon
59 58 Sylveon
60 59 Mudbray
61 60 Mudsdale
62 61 Igglybuff
63 62 Jigglypuff
64 63 Wigglytuff
65 64 Tauros
66 65 Miltank
67 66 Surskit
68 67 Masquerain
69 68 Dewpider
70 69 Araquanid
71 70 Fomantis
72 71 Lurantis
73 72 Morelull
74 73 Shiinotic
75 74 Paras
76 75 Parasect
77 76 Poliwag
78 77 Poliwhirl
79 78 Poliwrath
80 79 Politoed
81 80 Goldeen
82 81 Seaking
83 82 Feebas
84 83 Milotic
85 84 Alomomola
86 85 Fletchling
87 86 Fletchinder
88 87 Talonflame
89 88 Salandit
90 89 Salazzle
91 90 Cubone
92 91 Marowak
93 92 Kangaskhan
94 93 Magby
95 94 Magmar
96 95 Magmortar
97 96 Stufful
98 97 Bewear
99 98 Bounsweet
100 99 Steenee
101 100 Tsareena
102 101 Comfey
103 102 Pinsir
104 103 Oranguru
105 104 Passimian
106 105 Goomy
107 106 Sliggoo
108 107 Goodra
109 108 Castform
110 109 Wimpod
111 110 Golisopod
112 111 Staryu
113 112 Starmie
114 113 Sandygast
115 114 Palossand
116 115 Cranidos
117 116 Rampardos
118 117 Shieldon
119 118 Bastiodon
120 119 Archen
121 120 Archeops
122 121 Tirtouga
123 122 Carracosta
124 123 Phantump
125 124 Trevenant
126 125 Nosepass
127 126 Probopass
128 127 Pyukumuku
129 128 Chinchou
130 129 Lanturn
131 130 Tapu Lele
@@ -0,0 +1,303 @@
dexNumber,pokemon,form,notes
1,Rowlet,,
2,Dartrix,,
3,Decidueye,,
4,Litten,,
5,Torracat,,
6,Incineroar,,
7,Popplio,,
8,Brionne,,
9,Primarina,,
10,Pikipek,,
11,Trumbeak,,
12,Toucannon,,
13,Yungoos,,
14,Gumshoos,,
15,Rattata,,
16,Raticate,,
17,Caterpie,,
18,Metapod,,
19,Butterfree,,
20,Ledyba,,
21,Ledian,,
22,Spinarak,,
23,Ariados,,
24,Pichu,,
25,Pikachu,,
26,Raichu,,
27,Grubbin,,
28,Charjabug,,
29,Vikavolt,,
30,Bonsly,,
31,Sudowoodo,,
32,Happiny,,
33,Chansey,,
34,Blissey,,
35,Munchlax,,
36,Snorlax,,
37,Slowpoke,,
38,Slowbro,,
39,Slowking,,
40,Wingull,,
41,Pelipper,,
42,Abra,,
43,Kadabra,,
44,Alakazam,,
45,Meowth,,
46,Persian,,
47,Magnemite,,
48,Magneton,,
49,Magnezone,,
50,Grimer,,
51,Muk,,
52,Growlithe,,
53,Arcanine,,
54,Drowzee,,
55,Hypno,,
56,Makuhita,,
57,Hariyama,,
58,Smeargle,,
59,Crabrawler,,
60,Crabominable,,
61,Gastly,,
62,Haunter,,
63,Gengar,,
64,Drifloon,,
65,Drifblim,,
66,Misdreavus,,
67,Mismagius,,
68,Zubat,,
69,Golbat,,
70,Crobat,,
71,Diglett,,
72,Dugtrio,,
73,Spearow,,
74,Fearow,,
75,Rufflet,,
76,Braviary,,
77,Vullaby,,
78,Mandibuzz,,
79,Mankey,,
80,Primeape,,
81,Delibird,,
82,Oricorio,,
83,Cutiefly,,
84,Ribombee,,
85,Petilil,,
86,Lilligant,,
87,Cottonee,,
88,Whimsicott,,
89,Psyduck,,
90,Golduck,,
91,Magikarp,,
92,Gyarados,,
93,Barboach,,
94,Whiscash,,
95,Machop,,
96,Machoke,,
97,Machamp,,
98,Roggenrola,,
99,Boldore,,
100,Gigalith,,
101,Carbink,,
102,Sableye,,
103,Rockruff,,
104,Lycanroc,,
105,Spinda,,
106,Tentacool,,
107,Tentacruel,,
108,Finneon,,
109,Lumineon,,
110,Wishiwashi,,
111,Luvdisc,,
112,Corsola,,
113,Mareanie,,
114,Toxapex,,
115,Shellder,,
116,Cloyster,,
117,Bagon,,
118,Shelgon,,
119,Salamence,,
120,Lillipup,,
121,Herdier,,
122,Stoutland,,
123,Eevee,,
124,Vaporeon,,
125,Jolteon,,
126,Flareon,,
127,Espeon,,
128,Umbreon,,
129,Leafeon,,
130,Glaceon,,
131,Sylveon,,
132,Mudbray,,
133,Mudsdale,,
134,Igglybuff,,
135,Jigglypuff,,
136,Wigglytuff,,
137,Tauros,,
138,Miltank,,
139,Surskit,,
140,Masquerain,,
141,Dewpider,,
142,Araquanid,,
143,Fomantis,,
144,Lurantis,,
145,Morelull,,
146,Shiinotic,,
147,Paras,,
148,Parasect,,
149,Poliwag,,
150,Poliwhirl,,
151,Poliwrath,,
152,Politoed,,
153,Goldeen,,
154,Seaking,,
155,Feebas,,
156,Milotic,,
157,Alomomola,,
158,Fletchling,,
159,Fletchinder,,
160,Talonflame,,
161,Salandit,,
162,Salazzle,,
163,Cubone,,
164,Marowak,,
165,Kangaskhan,,
166,Magby,,
167,Magmar,,
168,Magmortar,,
169,Stufful,,
170,Bewear,,
171,Bounsweet,,
172,Steenee,,
173,Tsareena,,
174,Comfey,,
175,Pinsir,,
176,Oranguru,,
177,Passimian,,
178,Goomy,,
179,Sliggoo,,
180,Goodra,,
181,Castform,,
182,Wimpod,,
183,Golisopod,,
184,Staryu,,
185,Starmie,,
186,Sandygast,,
187,Palossand,,
188,Cranidos,,
189,Rampardos,,
190,Shieldon,,
191,Bastiodon,,
192,Archen,,
193,Archeops,,
194,Tirtouga,,
195,Carracosta,,
196,Phantump,,
197,Trevenant,,
198,Nosepass,,
199,Probopass,,
200,Pyukumuku,,
201,Chinchou,,
202,Lanturn,,
203,Type: Null,,
204,Silvally,,
205,Zygarde,,
206,Trubbish,,
207,Garbodor,,
208,Skarmory,,
209,Ditto,,
210,Cleffa,,
211,Clefairy,,
212,Clefable,,
213,Minior,,
214,Beldum,,
215,Metang,,
216,Metagross,,
217,Porygon,,
218,Porygon2,,
219,Porygon-Z,,
220,Pancham,,
221,Pangoro,,
222,Komala,,
223,Torkoal,,
224,Turtonator,,
225,Togedemaru,,
226,Elekid,,
227,Electabuzz,,
228,Electivire,,
229,Geodude,,
230,Graveler,,
231,Golem,,
232,Sandile,,
233,Krokorok,,
234,Krookodile,,
235,Trapinch,,
236,Vibrava,,
237,Flygon,,
238,Gible,,
239,Gabite,,
240,Garchomp,,
241,Klefki,,
242,Mimikyu,,
243,Bruxish,,
244,Drampa,,
245,Absol,,
246,Snorunt,,
247,Glalie,,
248,Froslass,,
249,Sneasel,,
250,Weavile,,
251,Sandshrew,,
252,Sandslash,,
253,Vulpix,,
254,Ninetales,,
255,Vanillite,,
256,Vanillish,,
257,Vanilluxe,,
258,Snubbull,,
259,Granbull,,
260,Shellos,,
261,Gastrodon,,
262,Relicanth,,
263,Dhelmise,,
264,Carvanha,,
265,Sharpedo,,
266,Wailmer,,
267,Wailord,,
268,Lapras,,
269,Exeggcute,,
270,Exeggutor,,
271,Jangmo-o,,
272,Hakamo-o,,
273,Kommo-o,,
274,Emolga,,
275,Scyther,,
276,Scizor,,
277,Murkrow,,
278,Honchkrow,,
279,Riolu,,
280,Lucario,,
281,Dratini,,
282,Dragonair,,
283,Dragonite,,
284,Aerodactyl,,
285,Tapu Koko,,
286,Tapu Lele,,
287,Tapu Bulu,,
288,Tapu Fini,,
289,Cosmog,,
290,Cosmoem,,
291,Solgaleo,,
292,Lunala,,
293,Nihilego,,
294,Buzzwole,,
295,Pheromosa,,
296,Xurkitree,,
297,Celesteela,,
298,Kartana,,
299,Guzzlord,,
300,Necrozma,,
301,Magearna,,
302,Marshadow,,
1 dexNumber pokemon form notes
2 1 Rowlet
3 2 Dartrix
4 3 Decidueye
5 4 Litten
6 5 Torracat
7 6 Incineroar
8 7 Popplio
9 8 Brionne
10 9 Primarina
11 10 Pikipek
12 11 Trumbeak
13 12 Toucannon
14 13 Yungoos
15 14 Gumshoos
16 15 Rattata
17 16 Raticate
18 17 Caterpie
19 18 Metapod
20 19 Butterfree
21 20 Ledyba
22 21 Ledian
23 22 Spinarak
24 23 Ariados
25 24 Pichu
26 25 Pikachu
27 26 Raichu
28 27 Grubbin
29 28 Charjabug
30 29 Vikavolt
31 30 Bonsly
32 31 Sudowoodo
33 32 Happiny
34 33 Chansey
35 34 Blissey
36 35 Munchlax
37 36 Snorlax
38 37 Slowpoke
39 38 Slowbro
40 39 Slowking
41 40 Wingull
42 41 Pelipper
43 42 Abra
44 43 Kadabra
45 44 Alakazam
46 45 Meowth
47 46 Persian
48 47 Magnemite
49 48 Magneton
50 49 Magnezone
51 50 Grimer
52 51 Muk
53 52 Growlithe
54 53 Arcanine
55 54 Drowzee
56 55 Hypno
57 56 Makuhita
58 57 Hariyama
59 58 Smeargle
60 59 Crabrawler
61 60 Crabominable
62 61 Gastly
63 62 Haunter
64 63 Gengar
65 64 Drifloon
66 65 Drifblim
67 66 Misdreavus
68 67 Mismagius
69 68 Zubat
70 69 Golbat
71 70 Crobat
72 71 Diglett
73 72 Dugtrio
74 73 Spearow
75 74 Fearow
76 75 Rufflet
77 76 Braviary
78 77 Vullaby
79 78 Mandibuzz
80 79 Mankey
81 80 Primeape
82 81 Delibird
83 82 Oricorio
84 83 Cutiefly
85 84 Ribombee
86 85 Petilil
87 86 Lilligant
88 87 Cottonee
89 88 Whimsicott
90 89 Psyduck
91 90 Golduck
92 91 Magikarp
93 92 Gyarados
94 93 Barboach
95 94 Whiscash
96 95 Machop
97 96 Machoke
98 97 Machamp
99 98 Roggenrola
100 99 Boldore
101 100 Gigalith
102 101 Carbink
103 102 Sableye
104 103 Rockruff
105 104 Lycanroc
106 105 Spinda
107 106 Tentacool
108 107 Tentacruel
109 108 Finneon
110 109 Lumineon
111 110 Wishiwashi
112 111 Luvdisc
113 112 Corsola
114 113 Mareanie
115 114 Toxapex
116 115 Shellder
117 116 Cloyster
118 117 Bagon
119 118 Shelgon
120 119 Salamence
121 120 Lillipup
122 121 Herdier
123 122 Stoutland
124 123 Eevee
125 124 Vaporeon
126 125 Jolteon
127 126 Flareon
128 127 Espeon
129 128 Umbreon
130 129 Leafeon
131 130 Glaceon
132 131 Sylveon
133 132 Mudbray
134 133 Mudsdale
135 134 Igglybuff
136 135 Jigglypuff
137 136 Wigglytuff
138 137 Tauros
139 138 Miltank
140 139 Surskit
141 140 Masquerain
142 141 Dewpider
143 142 Araquanid
144 143 Fomantis
145 144 Lurantis
146 145 Morelull
147 146 Shiinotic
148 147 Paras
149 148 Parasect
150 149 Poliwag
151 150 Poliwhirl
152 151 Poliwrath
153 152 Politoed
154 153 Goldeen
155 154 Seaking
156 155 Feebas
157 156 Milotic
158 157 Alomomola
159 158 Fletchling
160 159 Fletchinder
161 160 Talonflame
162 161 Salandit
163 162 Salazzle
164 163 Cubone
165 164 Marowak
166 165 Kangaskhan
167 166 Magby
168 167 Magmar
169 168 Magmortar
170 169 Stufful
171 170 Bewear
172 171 Bounsweet
173 172 Steenee
174 173 Tsareena
175 174 Comfey
176 175 Pinsir
177 176 Oranguru
178 177 Passimian
179 178 Goomy
180 179 Sliggoo
181 180 Goodra
182 181 Castform
183 182 Wimpod
184 183 Golisopod
185 184 Staryu
186 185 Starmie
187 186 Sandygast
188 187 Palossand
189 188 Cranidos
190 189 Rampardos
191 190 Shieldon
192 191 Bastiodon
193 192 Archen
194 193 Archeops
195 194 Tirtouga
196 195 Carracosta
197 196 Phantump
198 197 Trevenant
199 198 Nosepass
200 199 Probopass
201 200 Pyukumuku
202 201 Chinchou
203 202 Lanturn
204 203 Type: Null
205 204 Silvally
206 205 Zygarde
207 206 Trubbish
208 207 Garbodor
209 208 Skarmory
210 209 Ditto
211 210 Cleffa
212 211 Clefairy
213 212 Clefable
214 213 Minior
215 214 Beldum
216 215 Metang
217 216 Metagross
218 217 Porygon
219 218 Porygon2
220 219 Porygon-Z
221 220 Pancham
222 221 Pangoro
223 222 Komala
224 223 Torkoal
225 224 Turtonator
226 225 Togedemaru
227 226 Elekid
228 227 Electabuzz
229 228 Electivire
230 229 Geodude
231 230 Graveler
232 231 Golem
233 232 Sandile
234 233 Krokorok
235 234 Krookodile
236 235 Trapinch
237 236 Vibrava
238 237 Flygon
239 238 Gible
240 239 Gabite
241 240 Garchomp
242 241 Klefki
243 242 Mimikyu
244 243 Bruxish
245 244 Drampa
246 245 Absol
247 246 Snorunt
248 247 Glalie
249 248 Froslass
250 249 Sneasel
251 250 Weavile
252 251 Sandshrew
253 252 Sandslash
254 253 Vulpix
255 254 Ninetales
256 255 Vanillite
257 256 Vanillish
258 257 Vanilluxe
259 258 Snubbull
260 259 Granbull
261 260 Shellos
262 261 Gastrodon
263 262 Relicanth
264 263 Dhelmise
265 264 Carvanha
266 265 Sharpedo
267 266 Wailmer
268 267 Wailord
269 268 Lapras
270 269 Exeggcute
271 270 Exeggutor
272 271 Jangmo-o
273 272 Hakamo-o
274 273 Kommo-o
275 274 Emolga
276 275 Scyther
277 276 Scizor
278 277 Murkrow
279 278 Honchkrow
280 279 Riolu
281 280 Lucario
282 281 Dratini
283 282 Dragonair
284 283 Dragonite
285 284 Aerodactyl
286 285 Tapu Koko
287 286 Tapu Lele
288 287 Tapu Bulu
289 288 Tapu Fini
290 289 Cosmog
291 290 Cosmoem
292 291 Solgaleo
293 292 Lunala
294 293 Nihilego
295 294 Buzzwole
296 295 Pheromosa
297 296 Xurkitree
298 297 Celesteela
299 298 Kartana
300 299 Guzzlord
301 300 Necrozma
302 301 Magearna
303 302 Marshadow
@@ -0,0 +1,121 @@
dexNumber,pokemon,form,notes
1,Rowlet,,
2,Dartrix,,
3,Decidueye,,
4,Litten,,
5,Torracat,,
6,Incineroar,,
7,Popplio,,
8,Brionne,,
9,Primarina,,
10,Pikipek,,
11,Trumbeak,,
12,Toucannon,,
13,Yungoos,,
14,Gumshoos,,
15,Rattata,,
16,Raticate,,
17,Caterpie,,
18,Metapod,,
19,Butterfree,,
20,Ledyba,,
21,Ledian,,
22,Spinarak,,
23,Ariados,,
24,Pichu,,
25,Pikachu,,
26,Raichu,,
27,Grubbin,,
28,Charjabug,,
29,Vikavolt,,
30,Bonsly,,
31,Sudowoodo,,
32,Happiny,,
33,Chansey,,
34,Blissey,,
35,Munchlax,,
36,Snorlax,,
37,Slowpoke,,
38,Slowbro,,
39,Slowking,,
40,Wingull,,
41,Pelipper,,
42,Abra,,
43,Kadabra,,
44,Alakazam,,
45,Meowth,,
46,Persian,,
47,Magnemite,,
48,Magneton,,
49,Magnezone,,
50,Grimer,,
51,Muk,,
52,Growlithe,,
53,Arcanine,,
54,Drowzee,,
55,Hypno,,
56,Makuhita,,
57,Hariyama,,
58,Smeargle,,
59,Crabrawler,,
60,Crabominable,,
61,Gastly,,
62,Haunter,,
63,Gengar,,
64,Drifloon,,
65,Drifblim,,
66,Misdreavus,,
67,Mismagius,,
68,Zubat,,
69,Golbat,,
70,Crobat,,
71,Diglett,,
72,Dugtrio,,
73,Spearow,,
74,Fearow,,
75,Rufflet,,
76,Braviary,,
77,Vullaby,,
78,Mandibuzz,,
79,Mankey,,
80,Primeape,,
81,Delibird,,
82,Oricorio,,
83,Cutiefly,,
84,Ribombee,,
85,Petilil,,
86,Lilligant,,
87,Cottonee,,
88,Whimsicott,,
89,Psyduck,,
90,Golduck,,
91,Magikarp,,
92,Gyarados,,
93,Barboach,,
94,Whiscash,,
95,Machop,,
96,Machoke,,
97,Machamp,,
98,Roggenrola,,
99,Boldore,,
100,Gigalith,,
101,Carbink,,
102,Sableye,,
103,Rockruff,,
104,Lycanroc,,
105,Spinda,,
106,Tentacool,,
107,Tentacruel,,
108,Finneon,,
109,Lumineon,,
110,Wishiwashi,,
111,Luvdisc,,
112,Corsola,,
113,Mareanie,,
114,Toxapex,,
115,Shellder,,
116,Cloyster,,
117,Bagon,,
118,Shelgon,,
119,Salamence,,
120,Tapu Koko,,
1 dexNumber pokemon form notes
2 1 Rowlet
3 2 Dartrix
4 3 Decidueye
5 4 Litten
6 5 Torracat
7 6 Incineroar
8 7 Popplio
9 8 Brionne
10 9 Primarina
11 10 Pikipek
12 11 Trumbeak
13 12 Toucannon
14 13 Yungoos
15 14 Gumshoos
16 15 Rattata
17 16 Raticate
18 17 Caterpie
19 18 Metapod
20 19 Butterfree
21 20 Ledyba
22 21 Ledian
23 22 Spinarak
24 23 Ariados
25 24 Pichu
26 25 Pikachu
27 26 Raichu
28 27 Grubbin
29 28 Charjabug
30 29 Vikavolt
31 30 Bonsly
32 31 Sudowoodo
33 32 Happiny
34 33 Chansey
35 34 Blissey
36 35 Munchlax
37 36 Snorlax
38 37 Slowpoke
39 38 Slowbro
40 39 Slowking
41 40 Wingull
42 41 Pelipper
43 42 Abra
44 43 Kadabra
45 44 Alakazam
46 45 Meowth
47 46 Persian
48 47 Magnemite
49 48 Magneton
50 49 Magnezone
51 50 Grimer
52 51 Muk
53 52 Growlithe
54 53 Arcanine
55 54 Drowzee
56 55 Hypno
57 56 Makuhita
58 57 Hariyama
59 58 Smeargle
60 59 Crabrawler
61 60 Crabominable
62 61 Gastly
63 62 Haunter
64 63 Gengar
65 64 Drifloon
66 65 Drifblim
67 66 Misdreavus
68 67 Mismagius
69 68 Zubat
70 69 Golbat
71 70 Crobat
72 71 Diglett
73 72 Dugtrio
74 73 Spearow
75 74 Fearow
76 75 Rufflet
77 76 Braviary
78 77 Vullaby
79 78 Mandibuzz
80 79 Mankey
81 80 Primeape
82 81 Delibird
83 82 Oricorio
84 83 Cutiefly
85 84 Ribombee
86 85 Petilil
87 86 Lilligant
88 87 Cottonee
89 88 Whimsicott
90 89 Psyduck
91 90 Golduck
92 91 Magikarp
93 92 Gyarados
94 93 Barboach
95 94 Whiscash
96 95 Machop
97 96 Machoke
98 97 Machamp
99 98 Roggenrola
100 99 Boldore
101 100 Gigalith
102 101 Carbink
103 102 Sableye
104 103 Rockruff
105 104 Lycanroc
106 105 Spinda
107 106 Tentacool
108 107 Tentacruel
109 108 Finneon
110 109 Lumineon
111 110 Wishiwashi
112 111 Luvdisc
113 112 Corsola
114 113 Mareanie
115 114 Toxapex
116 115 Shellder
117 116 Cloyster
118 117 Bagon
119 118 Shelgon
120 119 Salamence
121 120 Tapu Koko
@@ -0,0 +1,101 @@
dexNumber,pokemon,form,notes
1,Pikipek,,
2,Trumbeak,,
3,Toucannon,,
4,Yungoos,,
5,Gumshoos,,
6,Rattata,,
7,Raticate,,
8,Happiny,,
9,Chansey,,
10,Blissey,,
11,Wingull,,
12,Pelipper,,
13,Drowzee,,
14,Hypno,,
15,Makuhita,,
16,Hariyama,,
17,Crabrawler,,
18,Crabominable,,
19,Zubat,,
20,Golbat,,
21,Crobat,,
22,Diglett,,
23,Dugtrio,,
24,Spearow,,
25,Fearow,,
26,Rufflet,,
27,Braviary,,
28,Vullaby,,
29,Mandibuzz,,
30,Mankey,,
31,Primeape,,
32,Oricorio,,
33,Cutiefly,,
34,Ribombee,,
35,Petilil,,
36,Lilligant,,
37,Cottonee,,
38,Whimsicott,,
39,Psyduck,,
40,Golduck,,
41,Magikarp,,
42,Gyarados,,
43,Barboach,,
44,Whiscash,,
45,Machop,,
46,Machoke,,
47,Machamp,,
48,Roggenrola,,
49,Boldore,,
50,Gigalith,,
51,Carbink,,
52,Sableye,,
53,Rockruff,,
54,Lycanroc,,
55,Tentacool,,
56,Tentacruel,,
57,Finneon,,
58,Lumineon,,
59,Mudbray,,
60,Mudsdale,,
61,Tauros,,
62,Miltank,,
63,Stufful,,
64,Bewear,,
65,Pinsir,,
66,Goomy,,
67,Sliggoo,,
68,Goodra,,
69,Castform,,
70,Wimpod,,
71,Golisopod,,
72,Skarmory,,
73,Snubbull,,
74,Granbull,,
75,Shellos,,
76,Gastrodon,,
77,Relicanth,,
78,Dhelmise,,
79,Carvanha,,
80,Sharpedo,,
81,Wailmer,,
82,Wailord,,
83,Lapras,,
84,Exeggcute,,
85,Exeggutor,,
86,Jangmo-o,,
87,Hakamo-o,,
88,Kommo-o,,
89,Emolga,,
90,Scyther,,
91,Scizor,,
92,Murkrow,,
93,Honchkrow,,
94,Riolu,,
95,Lucario,,
96,Dratini,,
97,Dragonair,,
98,Dragonite,,
99,Aerodactyl,,
100,Tapu Fini,,
1 dexNumber pokemon form notes
2 1 Pikipek
3 2 Trumbeak
4 3 Toucannon
5 4 Yungoos
6 5 Gumshoos
7 6 Rattata
8 7 Raticate
9 8 Happiny
10 9 Chansey
11 10 Blissey
12 11 Wingull
13 12 Pelipper
14 13 Drowzee
15 14 Hypno
16 15 Makuhita
17 16 Hariyama
18 17 Crabrawler
19 18 Crabominable
20 19 Zubat
21 20 Golbat
22 21 Crobat
23 22 Diglett
24 23 Dugtrio
25 24 Spearow
26 25 Fearow
27 26 Rufflet
28 27 Braviary
29 28 Vullaby
30 29 Mandibuzz
31 30 Mankey
32 31 Primeape
33 32 Oricorio
34 33 Cutiefly
35 34 Ribombee
36 35 Petilil
37 36 Lilligant
38 37 Cottonee
39 38 Whimsicott
40 39 Psyduck
41 40 Golduck
42 41 Magikarp
43 42 Gyarados
44 43 Barboach
45 44 Whiscash
46 45 Machop
47 46 Machoke
48 47 Machamp
49 48 Roggenrola
50 49 Boldore
51 50 Gigalith
52 51 Carbink
53 52 Sableye
54 53 Rockruff
55 54 Lycanroc
56 55 Tentacool
57 56 Tentacruel
58 57 Finneon
59 58 Lumineon
60 59 Mudbray
61 60 Mudsdale
62 61 Tauros
63 62 Miltank
64 63 Stufful
65 64 Bewear
66 65 Pinsir
67 66 Goomy
68 67 Sliggoo
69 68 Goodra
70 69 Castform
71 70 Wimpod
72 71 Golisopod
73 72 Skarmory
74 73 Snubbull
75 74 Granbull
76 75 Shellos
77 76 Gastrodon
78 77 Relicanth
79 78 Dhelmise
80 79 Carvanha
81 80 Sharpedo
82 81 Wailmer
83 82 Wailord
84 83 Lapras
85 84 Exeggcute
86 85 Exeggutor
87 86 Jangmo-o
88 87 Hakamo-o
89 88 Kommo-o
90 89 Emolga
91 90 Scyther
92 91 Scizor
93 92 Murkrow
94 93 Honchkrow
95 94 Riolu
96 95 Lucario
97 96 Dratini
98 97 Dragonair
99 98 Dragonite
100 99 Aerodactyl
101 100 Tapu Fini
@@ -0,0 +1,131 @@
dexNumber,pokemon,form,notes
1,Pikipek,,
2,Trumbeak,,
3,Toucannon,,
4,Yungoos,,
5,Gumshoos,,
6,Rattata,,
7,Raticate,,
8,Ledyba,,
9,Ledian,,
10,Spinarak,,
11,Ariados,,
12,Grubbin,,
13,Charjabug,,
14,Vikavolt,,
15,Happiny,,
16,Chansey,,
17,Blissey,,
18,Slowpoke,,
19,Slowbro,,
20,Slowking,,
21,Wingull,,
22,Pelipper,,
23,Meowth,,
24,Persian,,
25,Magnemite,,
26,Magneton,,
27,Magnezone,,
28,Grimer,,
29,Muk,,
30,Crabrawler,,
31,Crabominable,,
32,Gastly,,
33,Haunter,,
34,Gengar,,
35,Zubat,,
36,Golbat,,
37,Crobat,,
38,Diglett,,
39,Dugtrio,,
40,Spearow,,
41,Fearow,,
42,Oricorio,,
43,Cutiefly,,
44,Ribombee,,
45,Petilil,,
46,Lilligant,,
47,Cottonee,,
48,Whimsicott,,
49,Psyduck,,
50,Golduck,,
51,Magikarp,,
52,Gyarados,,
53,Tentacool,,
54,Tentacruel,,
55,Finneon,,
56,Lumineon,,
57,Wishiwashi,,
58,Mudbray,,
59,Mudsdale,,
60,Surskit,,
61,Masquerain,,
62,Dewpider,,
63,Araquanid,,
64,Morelull,,
65,Shiinotic,,
66,Paras,,
67,Parasect,,
68,Poliwag,,
69,Poliwhirl,,
70,Poliwrath,,
71,Politoed,,
72,Goldeen,,
73,Seaking,,
74,Goomy,,
75,Sliggoo,,
76,Goodra,,
77,Castform,,
78,Trubbish,,
79,Garbodor,,
80,Skarmory,,
81,Ditto,,
82,Cleffa,,
83,Clefairy,,
84,Clefable,,
85,Minior,,
86,Beldum,,
87,Metang,,
88,Metagross,,
89,Porygon,,
90,Porygon2,,
91,Porygon-Z,,
92,Pancham,,
93,Pangoro,,
94,Komala,,
95,Torkoal,,
96,Turtonator,,
97,Togedemaru,,
98,Elekid,,
99,Electabuzz,,
100,Electivire,,
101,Geodude,,
102,Graveler,,
103,Golem,,
104,Sandile,,
105,Krokorok,,
106,Krookodile,,
107,Trapinch,,
108,Vibrava,,
109,Flygon,,
110,Gible,,
111,Gabite,,
112,Garchomp,,
113,Klefki,,
114,Mimikyu,,
115,Bruxish,,
116,Drampa,,
117,Absol,,
118,Snorunt,,
119,Glalie,,
120,Froslass,,
121,Sneasel,,
122,Weavile,,
123,Sandshrew,,
124,Sandslash,,
125,Vulpix,,
126,Ninetales,,
127,Vanillite,,
128,Vanillish,,
129,Vanilluxe,,
130,Tapu Bulu,,
1 dexNumber pokemon form notes
2 1 Pikipek
3 2 Trumbeak
4 3 Toucannon
5 4 Yungoos
6 5 Gumshoos
7 6 Rattata
8 7 Raticate
9 8 Ledyba
10 9 Ledian
11 10 Spinarak
12 11 Ariados
13 12 Grubbin
14 13 Charjabug
15 14 Vikavolt
16 15 Happiny
17 16 Chansey
18 17 Blissey
19 18 Slowpoke
20 19 Slowbro
21 20 Slowking
22 21 Wingull
23 22 Pelipper
24 23 Meowth
25 24 Persian
26 25 Magnemite
27 26 Magneton
28 27 Magnezone
29 28 Grimer
30 29 Muk
31 30 Crabrawler
32 31 Crabominable
33 32 Gastly
34 33 Haunter
35 34 Gengar
36 35 Zubat
37 36 Golbat
38 37 Crobat
39 38 Diglett
40 39 Dugtrio
41 40 Spearow
42 41 Fearow
43 42 Oricorio
44 43 Cutiefly
45 44 Ribombee
46 45 Petilil
47 46 Lilligant
48 47 Cottonee
49 48 Whimsicott
50 49 Psyduck
51 50 Golduck
52 51 Magikarp
53 52 Gyarados
54 53 Tentacool
55 54 Tentacruel
56 55 Finneon
57 56 Lumineon
58 57 Wishiwashi
59 58 Mudbray
60 59 Mudsdale
61 60 Surskit
62 61 Masquerain
63 62 Dewpider
64 63 Araquanid
65 64 Morelull
66 65 Shiinotic
67 66 Paras
68 67 Parasect
69 68 Poliwag
70 69 Poliwhirl
71 70 Poliwrath
72 71 Politoed
73 72 Goldeen
74 73 Seaking
75 74 Goomy
76 75 Sliggoo
77 76 Goodra
78 77 Castform
79 78 Trubbish
80 79 Garbodor
81 80 Skarmory
82 81 Ditto
83 82 Cleffa
84 83 Clefairy
85 84 Clefable
86 85 Minior
87 86 Beldum
88 87 Metang
89 88 Metagross
90 89 Porygon
91 90 Porygon2
92 91 Porygon-Z
93 92 Pancham
94 93 Pangoro
95 94 Komala
96 95 Torkoal
97 96 Turtonator
98 97 Togedemaru
99 98 Elekid
100 99 Electabuzz
101 100 Electivire
102 101 Geodude
103 102 Graveler
104 103 Golem
105 104 Sandile
106 105 Krokorok
107 106 Krookodile
108 107 Trapinch
109 108 Vibrava
110 109 Flygon
111 110 Gible
112 111 Gabite
113 112 Garchomp
114 113 Klefki
115 114 Mimikyu
116 115 Bruxish
117 116 Drampa
118 117 Absol
119 118 Snorunt
120 119 Glalie
121 120 Froslass
122 121 Sneasel
123 122 Weavile
124 123 Sandshrew
125 124 Sandslash
126 125 Vulpix
127 126 Ninetales
128 127 Vanillite
129 128 Vanillish
130 129 Vanilluxe
131 130 Tapu Bulu
@@ -0,0 +1,211 @@
dexNumber,pokemon,form,notes
1,Snom,,
2,Frosmoth,,
3,Wooloo,,
4,Dubwool,,
5,Skwovet,,
6,Greedent,,
7,Swinub,,
8,Piloswine,,
9,Mamoswine,,
10,Mime Jr.,,
11,Mr. Mime,,
12,Mr. Rime,,
13,Smoochum,,
14,Jynx,,
15,Elekid,,
16,Electabuzz,,
17,Electivire,,
18,Magby,,
19,Magmar,,
20,Magmortar,,
21,Audino,,
22,Vanillite,,
23,Vanillish,,
24,Vanilluxe,,
25,Snorunt,,
26,Glalie,,
27,Froslass,,
28,Sneasel,,
29,Weavile,,
30,Cryogonal,,
31,Snover,,
32,Abomasnow,,
33,Phantump,,
34,Trevenant,,
35,Swablu,,
36,Altaria,,
37,Impidimp,,
38,Morgrem,,
39,Grimmsnarl,,
40,Hatenna,,
41,Hattrem,,
42,Hatterene,,
43,Cleffa,,
44,Clefairy,,
45,Clefable,,
46,Mimikyu,,
47,Spiritomb,,
48,Litwick,,
49,Lampent,,
50,Chandelure,,
51,Gothita,,
52,Gothorita,,
53,Gothitelle,,
54,Solosis,,
55,Duosion,,
56,Reuniclus,,
57,Timburr,,
58,Gurdurr,,
59,Conkeldurr,,
60,Barboach,,
61,Whiscash,,
62,Magikarp,,
63,Gyarados,,
64,Basculin,,
65,Nidoran♀,,
66,Nidorina,,
67,Nidoqueen,,
68,Nidoran♂,,
69,Nidorino,,
70,Nidoking,,
71,Zigzagoon,,
72,Linoone,,
73,Obstagoon,,
74,Eevee,,
75,Vaporeon,,
76,Jolteon,,
77,Flareon,,
78,Umbreon,,
79,Espeon,,
80,Glaceon,,
81,Leafeon,,
82,Sylveon,,
83,Tyrunt,,
84,Tyrantrum,,
85,Amaura,,
86,Aurorus,,
87,Bronzor,,
88,Bronzong,,
89,Stonjourner,,
90,Eiscue,,
91,Dewpider,,
92,Araquanid,,
93,Joltik,,
94,Galvantula,,
95,Karrablast,,
96,Escavalier,,
97,Shelmet,,
98,Accelgor,,
99,Sizzlipede,,
100,Centiskorch,,
101,Durant,,
102,Heatmor,,
103,Darumaka,,
104,Darmanitan,,
105,Ponyta,,
106,Rapidash,,
107,Absol,,
108,Cufant,,
109,Copperajah,,
110,Dreepy,,
111,Drakloak,,
112,Dragapult,,
113,Bagon,,
114,Shelgon,,
115,Salamence,,
116,Gible,,
117,Gabite,,
118,Garchomp,,
119,Druddigon,,
120,Delibird,,
121,Cubchoo,,
122,Beartic,,
123,Omanyte,,
124,Omastar,,
125,Kabuto,,
126,Kabutops,,
127,Aerodactyl,,
128,Carbink,,
129,Beldum,,
130,Metang,,
131,Metagross,,
132,Sinistea,,
133,Polteageist,,
134,Riolu,,
135,Lucario,,
136,Deino,,
137,Zweilous,,
138,Hydreigon,,
139,Larvitar,,
140,Pupitar,,
141,Tyranitar,,
142,Bergmite,,
143,Avalugg,,
144,Zubat,,
145,Golbat,,
146,Crobat,,
147,Tirtouga,,
148,Carracosta,,
149,Archen,,
150,Archeops,,
151,Baltoy,,
152,Claydol,,
153,Golett,,
154,Golurk,,
155,Yamper,,
156,Boltund,,
157,Morpeko,,
158,Pincurchin,,
159,Spheal,,
160,Sealeo,,
161,Walrein,,
162,Dhelmise,,
163,Rookidee,,
164,Corvisquire,,
165,Corviknight,,
166,Gossifleur,,
167,Eldegoss,,
168,Cottonee,,
169,Whimsicott,,
170,Shuckle,,
171,Indeedee,,
172,Munchlax,,
173,Snorlax,,
174,Sableye,,
175,Mawile,,
176,Rolycoly,,
177,Carkol,,
178,Coalossal,,
179,Ferroseed,,
180,Ferrothorn,,
181,Noibat,,
182,Noivern,,
183,Lileep,,
184,Cradily,,
185,Anorith,,
186,Armaldo,,
187,Relicanth,,
188,Feebas,,
189,Milotic,,
190,Lapras,,
191,Aron,,
192,Lairon,,
193,Aggron,,
194,Dratini,,
195,Dragonair,,
196,Dragonite,,
197,Regirock,,
198,Regice,,
199,Registeel,,
200,Regieleki,,
201,Regidrago,,
202,Articuno,,
203,Zapdos,,
204,Moltres,,
205,Cobalion,,
206,Terrakion,,
207,Virizion,,
208,Glastrier,,
209,Spectrier,,
210,Calyrex,,
1 dexNumber pokemon form notes
2 1 Snom
3 2 Frosmoth
4 3 Wooloo
5 4 Dubwool
6 5 Skwovet
7 6 Greedent
8 7 Swinub
9 8 Piloswine
10 9 Mamoswine
11 10 Mime Jr.
12 11 Mr. Mime
13 12 Mr. Rime
14 13 Smoochum
15 14 Jynx
16 15 Elekid
17 16 Electabuzz
18 17 Electivire
19 18 Magby
20 19 Magmar
21 20 Magmortar
22 21 Audino
23 22 Vanillite
24 23 Vanillish
25 24 Vanilluxe
26 25 Snorunt
27 26 Glalie
28 27 Froslass
29 28 Sneasel
30 29 Weavile
31 30 Cryogonal
32 31 Snover
33 32 Abomasnow
34 33 Phantump
35 34 Trevenant
36 35 Swablu
37 36 Altaria
38 37 Impidimp
39 38 Morgrem
40 39 Grimmsnarl
41 40 Hatenna
42 41 Hattrem
43 42 Hatterene
44 43 Cleffa
45 44 Clefairy
46 45 Clefable
47 46 Mimikyu
48 47 Spiritomb
49 48 Litwick
50 49 Lampent
51 50 Chandelure
52 51 Gothita
53 52 Gothorita
54 53 Gothitelle
55 54 Solosis
56 55 Duosion
57 56 Reuniclus
58 57 Timburr
59 58 Gurdurr
60 59 Conkeldurr
61 60 Barboach
62 61 Whiscash
63 62 Magikarp
64 63 Gyarados
65 64 Basculin
66 65 Nidoran♀
67 66 Nidorina
68 67 Nidoqueen
69 68 Nidoran♂
70 69 Nidorino
71 70 Nidoking
72 71 Zigzagoon
73 72 Linoone
74 73 Obstagoon
75 74 Eevee
76 75 Vaporeon
77 76 Jolteon
78 77 Flareon
79 78 Umbreon
80 79 Espeon
81 80 Glaceon
82 81 Leafeon
83 82 Sylveon
84 83 Tyrunt
85 84 Tyrantrum
86 85 Amaura
87 86 Aurorus
88 87 Bronzor
89 88 Bronzong
90 89 Stonjourner
91 90 Eiscue
92 91 Dewpider
93 92 Araquanid
94 93 Joltik
95 94 Galvantula
96 95 Karrablast
97 96 Escavalier
98 97 Shelmet
99 98 Accelgor
100 99 Sizzlipede
101 100 Centiskorch
102 101 Durant
103 102 Heatmor
104 103 Darumaka
105 104 Darmanitan
106 105 Ponyta
107 106 Rapidash
108 107 Absol
109 108 Cufant
110 109 Copperajah
111 110 Dreepy
112 111 Drakloak
113 112 Dragapult
114 113 Bagon
115 114 Shelgon
116 115 Salamence
117 116 Gible
118 117 Gabite
119 118 Garchomp
120 119 Druddigon
121 120 Delibird
122 121 Cubchoo
123 122 Beartic
124 123 Omanyte
125 124 Omastar
126 125 Kabuto
127 126 Kabutops
128 127 Aerodactyl
129 128 Carbink
130 129 Beldum
131 130 Metang
132 131 Metagross
133 132 Sinistea
134 133 Polteageist
135 134 Riolu
136 135 Lucario
137 136 Deino
138 137 Zweilous
139 138 Hydreigon
140 139 Larvitar
141 140 Pupitar
142 141 Tyranitar
143 142 Bergmite
144 143 Avalugg
145 144 Zubat
146 145 Golbat
147 146 Crobat
148 147 Tirtouga
149 148 Carracosta
150 149 Archen
151 150 Archeops
152 151 Baltoy
153 152 Claydol
154 153 Golett
155 154 Golurk
156 155 Yamper
157 156 Boltund
158 157 Morpeko
159 158 Pincurchin
160 159 Spheal
161 160 Sealeo
162 161 Walrein
163 162 Dhelmise
164 163 Rookidee
165 164 Corvisquire
166 165 Corviknight
167 166 Gossifleur
168 167 Eldegoss
169 168 Cottonee
170 169 Whimsicott
171 170 Shuckle
172 171 Indeedee
173 172 Munchlax
174 173 Snorlax
175 174 Sableye
176 175 Mawile
177 176 Rolycoly
178 177 Carkol
179 178 Coalossal
180 179 Ferroseed
181 180 Ferrothorn
182 181 Noibat
183 182 Noivern
184 183 Lileep
185 184 Cradily
186 185 Anorith
187 186 Armaldo
188 187 Relicanth
189 188 Feebas
190 189 Milotic
191 190 Lapras
192 191 Aron
193 192 Lairon
194 193 Aggron
195 194 Dratini
196 195 Dragonair
197 196 Dragonite
198 197 Regirock
199 198 Regice
200 199 Registeel
201 200 Regieleki
202 201 Regidrago
203 202 Articuno
204 203 Zapdos
205 204 Moltres
206 205 Cobalion
207 206 Terrakion
208 207 Virizion
209 208 Glastrier
210 209 Spectrier
211 210 Calyrex
@@ -0,0 +1,212 @@
dexNumber,pokemon,form,notes
1,Slowpoke,,
2,Slowbro,,
3,Slowking,,
4,Buneary,,
5,Lopunny,,
6,Happiny,,
7,Chansey,,
8,Blissey,,
9,Skwovet,,
10,Greedent,,
11,Igglybuff,,
12,Jigglypuff,,
13,Wigglytuff,,
14,Blipbug,,
15,Dottler,,
16,Orbeetle,,
17,Fomantis,,
18,Lurantis,,
19,Applin,,
20,Flapple,,
21,Appletun,,
22,Fletchling,,
23,Fletchinder,,
24,Talonflame,,
25,Shinx,,
26,Luxio,,
27,Luxray,,
28,Klefki,,
29,Pawniard,,
30,Bisharp,,
31,Abra,,
32,Kadabra,,
33,Alakazam,,
34,Ralts,,
35,Kirlia,,
36,Gardevoir,,
37,Gallade,,
38,Krabby,,
39,Kingler,,
40,Tentacool,,
41,Tentacruel,,
42,Magikarp,,
43,Gyarados,,
44,Remoraid,,
45,Octillery,,
46,Mantyke,,
47,Mantine,,
48,Wingull,,
49,Pelipper,,
50,Skorupi,,
51,Drapion,,
52,Dunsparce,,
53,Bouffalant,,
54,Lickitung,,
55,Lickilicky,,
56,Chewtle,,
57,Drednaw,,
58,Wooper,,
59,Quagsire,,
60,Goomy,,
61,Sliggoo,,
62,Goodra,,
63,Druddigon,,
64,Shelmet,,
65,Accelgor,,
66,Karrablast,,
67,Escavalier,,
68,Bulbasaur,,
69,Ivysaur,,
70,Venusaur,,
71,Squirtle,,
72,Wartortle,,
73,Blastoise,,
74,Venipede,,
75,Whirlipede,,
76,Scolipede,,
77,Foongus,,
78,Amoonguss,,
79,Comfey,,
80,Tangela,,
81,Tangrowth,,
82,Croagunk,,
83,Toxicroak,,
84,Pichu,,
85,Pikachu,,
86,Raichu,,
87,Zorua,,
88,Zoroark,,
89,Oranguru,,
90,Passimian,,
91,Corphish,,
92,Crawdaunt,,
93,Cramorant,,
94,Goldeen,,
95,Seaking,,
96,Arrokuda,,
97,Barraskewda,,
98,Staryu,,
99,Starmie,,
100,Kubfu,,
101,Urshifu,,
102,Emolga,,
103,Dedenne,,
104,Morpeko,,
105,Magnemite,,
106,Magneton,,
107,Magnezone,,
108,Inkay,,
109,Malamar,,
110,Wishiwashi,,
111,Carvanha,,
112,Sharpedo,,
113,Lillipup,,
114,Herdier,,
115,Stoutland,,
116,Tauros,,
117,Miltank,,
118,Scyther,,
119,Scizor,,
120,Pinsir,,
121,Heracross,,
122,Dwebble,,
123,Crustle,,
124,Wimpod,,
125,Golisopod,,
126,Pincurchin,,
127,Mareanie,,
128,Toxapex,,
129,Clobbopus,,
130,Grapploct,,
131,Shellder,,
132,Cloyster,,
133,Sandygast,,
134,Palossand,,
135,Drifloon,,
136,Drifblim,,
137,Barboach,,
138,Whiscash,,
139,Azurill,,
140,Marill,,
141,Azumarill,,
142,Poliwag,,
143,Poliwhirl,,
144,Poliwrath,,
145,Politoed,,
146,Psyduck,,
147,Golduck,,
148,Whismur,,
149,Loudred,,
150,Exploud,,
151,Woobat,,
152,Swoobat,,
153,Skarmory,,
154,Roggenrola,,
155,Boldore,,
156,Gigalith,,
157,Rockruff,,
158,Lycanroc,,
159,Salandit,,
160,Salazzle,,
161,Scraggy,,
162,Scrafty,,
163,Mienfoo,,
164,Mienshao,,
165,Jangmo-o,,
166,Hakamo-o,,
167,Kommo-o,,
168,Sandshrew,,
169,Sandslash,,
170,Cubone,,
171,Marowak,,
172,Kangaskhan,,
173,Torkoal,,
174,Silicobra,,
175,Sandaconda,,
176,Sandile,,
177,Krokorok,,
178,Krookodile,,
179,Rufflet,,
180,Braviary,,
181,Vullaby,,
182,Mandibuzz,,
183,Rhyhorn,,
184,Rhydon,,
185,Rhyperior,,
186,Larvesta,,
187,Volcarona,,
188,Chinchou,,
189,Lanturn,,
190,Wailmer,,
191,Wailord,,
192,Frillish,,
193,Jellicent,,
194,Skrelp,,
195,Dragalge,,
196,Clauncher,,
197,Clawitzer,,
198,Horsea,,
199,Seadra,,
200,Kingdra,,
201,Petilil,,
202,Lilligant,,
203,Combee,,
204,Vespiquen,,
205,Exeggcute,,
206,Exeggutor,,
207,Ditto,,
208,Porygon,,
209,Porygon2,,
210,Porygon-Z,,
211,Zarude,,
1 dexNumber pokemon form notes
2 1 Slowpoke
3 2 Slowbro
4 3 Slowking
5 4 Buneary
6 5 Lopunny
7 6 Happiny
8 7 Chansey
9 8 Blissey
10 9 Skwovet
11 10 Greedent
12 11 Igglybuff
13 12 Jigglypuff
14 13 Wigglytuff
15 14 Blipbug
16 15 Dottler
17 16 Orbeetle
18 17 Fomantis
19 18 Lurantis
20 19 Applin
21 20 Flapple
22 21 Appletun
23 22 Fletchling
24 23 Fletchinder
25 24 Talonflame
26 25 Shinx
27 26 Luxio
28 27 Luxray
29 28 Klefki
30 29 Pawniard
31 30 Bisharp
32 31 Abra
33 32 Kadabra
34 33 Alakazam
35 34 Ralts
36 35 Kirlia
37 36 Gardevoir
38 37 Gallade
39 38 Krabby
40 39 Kingler
41 40 Tentacool
42 41 Tentacruel
43 42 Magikarp
44 43 Gyarados
45 44 Remoraid
46 45 Octillery
47 46 Mantyke
48 47 Mantine
49 48 Wingull
50 49 Pelipper
51 50 Skorupi
52 51 Drapion
53 52 Dunsparce
54 53 Bouffalant
55 54 Lickitung
56 55 Lickilicky
57 56 Chewtle
58 57 Drednaw
59 58 Wooper
60 59 Quagsire
61 60 Goomy
62 61 Sliggoo
63 62 Goodra
64 63 Druddigon
65 64 Shelmet
66 65 Accelgor
67 66 Karrablast
68 67 Escavalier
69 68 Bulbasaur
70 69 Ivysaur
71 70 Venusaur
72 71 Squirtle
73 72 Wartortle
74 73 Blastoise
75 74 Venipede
76 75 Whirlipede
77 76 Scolipede
78 77 Foongus
79 78 Amoonguss
80 79 Comfey
81 80 Tangela
82 81 Tangrowth
83 82 Croagunk
84 83 Toxicroak
85 84 Pichu
86 85 Pikachu
87 86 Raichu
88 87 Zorua
89 88 Zoroark
90 89 Oranguru
91 90 Passimian
92 91 Corphish
93 92 Crawdaunt
94 93 Cramorant
95 94 Goldeen
96 95 Seaking
97 96 Arrokuda
98 97 Barraskewda
99 98 Staryu
100 99 Starmie
101 100 Kubfu
102 101 Urshifu
103 102 Emolga
104 103 Dedenne
105 104 Morpeko
106 105 Magnemite
107 106 Magneton
108 107 Magnezone
109 108 Inkay
110 109 Malamar
111 110 Wishiwashi
112 111 Carvanha
113 112 Sharpedo
114 113 Lillipup
115 114 Herdier
116 115 Stoutland
117 116 Tauros
118 117 Miltank
119 118 Scyther
120 119 Scizor
121 120 Pinsir
122 121 Heracross
123 122 Dwebble
124 123 Crustle
125 124 Wimpod
126 125 Golisopod
127 126 Pincurchin
128 127 Mareanie
129 128 Toxapex
130 129 Clobbopus
131 130 Grapploct
132 131 Shellder
133 132 Cloyster
134 133 Sandygast
135 134 Palossand
136 135 Drifloon
137 136 Drifblim
138 137 Barboach
139 138 Whiscash
140 139 Azurill
141 140 Marill
142 141 Azumarill
143 142 Poliwag
144 143 Poliwhirl
145 144 Poliwrath
146 145 Politoed
147 146 Psyduck
148 147 Golduck
149 148 Whismur
150 149 Loudred
151 150 Exploud
152 151 Woobat
153 152 Swoobat
154 153 Skarmory
155 154 Roggenrola
156 155 Boldore
157 156 Gigalith
158 157 Rockruff
159 158 Lycanroc
160 159 Salandit
161 160 Salazzle
162 161 Scraggy
163 162 Scrafty
164 163 Mienfoo
165 164 Mienshao
166 165 Jangmo-o
167 166 Hakamo-o
168 167 Kommo-o
169 168 Sandshrew
170 169 Sandslash
171 170 Cubone
172 171 Marowak
173 172 Kangaskhan
174 173 Torkoal
175 174 Silicobra
176 175 Sandaconda
177 176 Sandile
178 177 Krokorok
179 178 Krookodile
180 179 Rufflet
181 180 Braviary
182 181 Vullaby
183 182 Mandibuzz
184 183 Rhyhorn
185 184 Rhydon
186 185 Rhyperior
187 186 Larvesta
188 187 Volcarona
189 188 Chinchou
190 189 Lanturn
191 190 Wailmer
192 191 Wailord
193 192 Frillish
194 193 Jellicent
195 194 Skrelp
196 195 Dragalge
197 196 Clauncher
198 197 Clawitzer
199 198 Horsea
200 199 Seadra
201 200 Kingdra
202 201 Petilil
203 202 Lilligant
204 203 Combee
205 204 Vespiquen
206 205 Exeggcute
207 206 Exeggutor
208 207 Ditto
209 208 Porygon
210 209 Porygon2
211 210 Porygon-Z
212 211 Zarude
@@ -0,0 +1,401 @@
dexNumber,pokemon,form,notes
1,Grookey,,
2,Thwackey,,
3,Rillaboom,,
4,Scorbunny,,
5,Raboot,,
6,Cinderace,,
7,Sobble,,
8,Drizzile,,
9,Inteleon,,
10,Blipbug,,
11,Dottler,,
12,Orbeetle,,
13,Caterpie,,
14,Metapod,,
15,Butterfree,,
16,Grubbin,,
17,Charjabug,,
18,Vikavolt,,
19,Hoothoot,,
20,Noctowl,,
21,Rookidee,,
22,Corvisquire,,
23,Corviknight,,
24,Skwovet,,
25,Greedent,,
26,Pidove,,
27,Tranquill,,
28,Unfezant,,
29,Nickit,,
30,Thievul,,
31,Zigzagoon,,
32,Linoone,,
33,Obstagoon,,
34,Wooloo,,
35,Dubwool,,
36,Lotad,,
37,Lombre,,
38,Ludicolo,,
39,Seedot,,
40,Nuzleaf,,
41,Shiftry,,
42,Chewtle,,
43,Drednaw,,
44,Purrloin,,
45,Liepard,,
46,Yamper,,
47,Boltund,,
48,Bunnelby,,
49,Diggersby,,
50,Minccino,,
51,Cinccino,,
52,Bounsweet,,
53,Steenee,,
54,Tsareena,,
55,Oddish,,
56,Gloom,,
57,Vileplume,,
58,Bellossom,,
59,Budew,,
60,Roselia,,
61,Roserade,,
62,Wingull,,
63,Pelipper,,
64,Joltik,,
65,Galvantula,,
66,Electrike,,
67,Manectric,,
68,Vulpix,,
69,Ninetales,,
70,Growlithe,,
71,Arcanine,,
72,Vanillite,,
73,Vanillish,,
74,Vanilluxe,,
75,Swinub,,
76,Piloswine,,
77,Mamoswine,,
78,Delibird,,
79,Snorunt,,
80,Glalie,,
81,Froslass,,
82,Baltoy,,
83,Claydol,,
84,Mudbray,,
85,Mudsdale,,
86,Dwebble,,
87,Crustle,,
88,Golett,,
89,Golurk,,
90,Munna,,
91,Musharna,,
92,Natu,,
93,Xatu,,
94,Stufful,,
95,Bewear,,
96,Snover,,
97,Abomasnow,,
98,Krabby,,
99,Kingler,,
100,Wooper,,
101,Quagsire,,
102,Corphish,,
103,Crawdaunt,,
104,Nincada,,
105,Ninjask,,
106,Shedinja,,
107,Tyrogue,,
108,Hitmonlee,,
109,Hitmonchan,,
110,Hitmontop,,
111,Pancham,,
112,Pangoro,,
113,Klink,,
114,Klang,,
115,Klinklang,,
116,Combee,,
117,Vespiquen,,
118,Bronzor,,
119,Bronzong,,
120,Ralts,,
121,Kirlia,,
122,Gardevoir,,
123,Gallade,,
124,Drifloon,,
125,Drifblim,,
126,Gossifleur,,
127,Eldegoss,,
128,Cherubi,,
129,Cherrim,,
130,Stunky,,
131,Skuntank,,
132,Tympole,,
133,Palpitoad,,
134,Seismitoad,,
135,Duskull,,
136,Dusclops,,
137,Dusknoir,,
138,Machop,,
139,Machoke,,
140,Machamp,,
141,Gastly,,
142,Haunter,,
143,Gengar,,
144,Magikarp,,
145,Gyarados,,
146,Goldeen,,
147,Seaking,,
148,Remoraid,,
149,Octillery,,
150,Shellder,,
151,Cloyster,,
152,Feebas,,
153,Milotic,,
154,Basculin,,
155,Wishiwashi,,
156,Pyukumuku,,
157,Trubbish,,
158,Garbodor,,
159,Sizzlipede,,
160,Centiskorch,,
161,Rolycoly,,
162,Carkol,,
163,Coalossal,,
164,Diglett,,
165,Dugtrio,,
166,Drilbur,,
167,Excadrill,,
168,Roggenrola,,
169,Boldore,,
170,Gigalith,,
171,Timburr,,
172,Gurdurr,,
173,Conkeldurr,,
174,Woobat,,
175,Swoobat,,
176,Noibat,,
177,Noivern,,
178,Onix,,
179,Steelix,,
180,Arrokuda,,
181,Barraskewda,,
182,Meowth,,
183,Perrserker,,
184,Persian,,
185,Milcery,,
186,Alcremie,,
187,Cutiefly,,
188,Ribombee,,
189,Ferroseed,,
190,Ferrothorn,,
191,Pumpkaboo,,
192,Gourgeist,,
193,Pichu,,
194,Pikachu,,
195,Raichu,,
196,Eevee,,
197,Vaporeon,,
198,Jolteon,,
199,Flareon,,
200,Espeon,,
201,Umbreon,,
202,Leafeon,,
203,Glaceon,,
204,Sylveon,,
205,Applin,,
206,Flapple,,
207,Appletun,,
208,Espurr,,
209,Meowstic,,
210,Swirlix,,
211,Slurpuff,,
212,Spritzee,,
213,Aromatisse,,
214,Dewpider,,
215,Araquanid,,
216,Wynaut,,
217,Wobbuffet,,
218,Farfetchd,,
219,Sirfetchd,,
220,Chinchou,,
221,Lanturn,,
222,Croagunk,,
223,Toxicroak,,
224,Scraggy,,
225,Scrafty,,
226,Stunfisk,,
227,Shuckle,,
228,Barboach,,
229,Whiscash,,
230,Shellos,,
231,Gastrodon,,
232,Wimpod,,
233,Golisopod,,
234,Binacle,,
235,Barbaracle,,
236,Corsola,,
237,Cursola,,
238,Impidimp,,
239,Morgrem,,
240,Grimmsnarl,,
241,Hatenna,,
242,Hattrem,,
243,Hatterene,,
244,Salandit,,
245,Salazzle,,
246,Pawniard,,
247,Bisharp,,
248,Throh,,
249,Sawk,,
250,Koffing,,
251,Weezing,,
252,Bonsly,,
253,Sudowoodo,,
254,Cleffa,,
255,Clefairy,,
256,Clefable,,
257,Togepi,,
258,Togetic,,
259,Togekiss,,
260,Munchlax,,
261,Snorlax,,
262,Cottonee,,
263,Whimsicott,,
264,Rhyhorn,,
265,Rhydon,,
266,Rhyperior,,
267,Gothita,,
268,Gothorita,,
269,Gothitelle,,
270,Solosis,,
271,Duosion,,
272,Reuniclus,,
273,Karrablast,,
274,Escavalier,,
275,Shelmet,,
276,Accelgor,,
277,Elgyem,,
278,Beheeyem,,
279,Cubchoo,,
280,Beartic,,
281,Rufflet,,
282,Braviary,,
283,Vullaby,,
284,Mandibuzz,,
285,Skorupi,,
286,Drapion,,
287,Litwick,,
288,Lampent,,
289,Chandelure,,
290,Inkay,,
291,Malamar,,
292,Sneasel,,
293,Weavile,,
294,Sableye,,
295,Mawile,,
296,Maractus,,
297,Sigilyph,,
298,Riolu,,
299,Lucario,,
300,Torkoal,,
301,Mimikyu,,
302,Cufant,,
303,Copperajah,,
304,Qwilfish,,
305,Frillish,,
306,Jellicent,,
307,Mareanie,,
308,Toxapex,,
309,Cramorant,,
310,Toxel,,
311,Toxtricity,,
312,Silicobra,,
313,Sandaconda,,
314,Hippopotas,,
315,Hippowdon,,
316,Durant,,
317,Heatmor,,
318,Helioptile,,
319,Heliolisk,,
320,Hawlucha,,
321,Trapinch,,
322,Vibrava,,
323,Flygon,,
324,Axew,,
325,Fraxure,,
326,Haxorus,,
327,Yamask,,
328,Runerigus,,
329,Cofagrigus,,
330,Honedge,,
331,Doublade,,
332,Aegislash,,
333,Ponyta,,
334,Rapidash,,
335,Sinistea,,
336,Polteageist,,
337,Indeedee,,
338,Phantump,,
339,Trevenant,,
340,Morelull,,
341,Shiinotic,,
342,Oranguru,,
343,Passimian,,
344,Morpeko,,
345,Falinks,,
346,Drampa,,
347,Turtonator,,
348,Togedemaru,,
349,Snom,,
350,Frosmoth,,
351,Clobbopus,,
352,Grapploct,,
353,Pincurchin,,
354,Mantyke,,
355,Mantine,,
356,Wailmer,,
357,Wailord,,
358,Bergmite,,
359,Avalugg,,
360,Dhelmise,,
361,Lapras,,
362,Lunatone,,
363,Solrock,,
364,Mime Jr.,,
365,Mr. Mime,,
366,Mr. Rime,,
367,Darumaka,,
368,Darmanitan,,
369,Stonjourner,,
370,Eiscue,,
371,Duraludon,,
372,Rotom,,
373,Ditto,,
374,Dracozolt,,
375,Arctozolt,,
376,Dracovish,,
377,Arctovish,,
378,Charmander,,
379,Charmeleon,,
380,Charizard,,
381,Type: Null,,
382,Silvally,,
383,Larvitar,,
384,Pupitar,,
385,Tyranitar,,
386,Deino,,
387,Zweilous,,
388,Hydreigon,,
389,Goomy,,
390,Sliggoo,,
391,Goodra,,
392,Jangmo-o,,
393,Hakamo-o,,
394,Kommo-o,,
395,Dreepy,,
396,Drakloak,,
397,Dragapult,,
398,Zacian,,
399,Zamazenta,,
400,Eternatus,,
1 dexNumber pokemon form notes
2 1 Grookey
3 2 Thwackey
4 3 Rillaboom
5 4 Scorbunny
6 5 Raboot
7 6 Cinderace
8 7 Sobble
9 8 Drizzile
10 9 Inteleon
11 10 Blipbug
12 11 Dottler
13 12 Orbeetle
14 13 Caterpie
15 14 Metapod
16 15 Butterfree
17 16 Grubbin
18 17 Charjabug
19 18 Vikavolt
20 19 Hoothoot
21 20 Noctowl
22 21 Rookidee
23 22 Corvisquire
24 23 Corviknight
25 24 Skwovet
26 25 Greedent
27 26 Pidove
28 27 Tranquill
29 28 Unfezant
30 29 Nickit
31 30 Thievul
32 31 Zigzagoon
33 32 Linoone
34 33 Obstagoon
35 34 Wooloo
36 35 Dubwool
37 36 Lotad
38 37 Lombre
39 38 Ludicolo
40 39 Seedot
41 40 Nuzleaf
42 41 Shiftry
43 42 Chewtle
44 43 Drednaw
45 44 Purrloin
46 45 Liepard
47 46 Yamper
48 47 Boltund
49 48 Bunnelby
50 49 Diggersby
51 50 Minccino
52 51 Cinccino
53 52 Bounsweet
54 53 Steenee
55 54 Tsareena
56 55 Oddish
57 56 Gloom
58 57 Vileplume
59 58 Bellossom
60 59 Budew
61 60 Roselia
62 61 Roserade
63 62 Wingull
64 63 Pelipper
65 64 Joltik
66 65 Galvantula
67 66 Electrike
68 67 Manectric
69 68 Vulpix
70 69 Ninetales
71 70 Growlithe
72 71 Arcanine
73 72 Vanillite
74 73 Vanillish
75 74 Vanilluxe
76 75 Swinub
77 76 Piloswine
78 77 Mamoswine
79 78 Delibird
80 79 Snorunt
81 80 Glalie
82 81 Froslass
83 82 Baltoy
84 83 Claydol
85 84 Mudbray
86 85 Mudsdale
87 86 Dwebble
88 87 Crustle
89 88 Golett
90 89 Golurk
91 90 Munna
92 91 Musharna
93 92 Natu
94 93 Xatu
95 94 Stufful
96 95 Bewear
97 96 Snover
98 97 Abomasnow
99 98 Krabby
100 99 Kingler
101 100 Wooper
102 101 Quagsire
103 102 Corphish
104 103 Crawdaunt
105 104 Nincada
106 105 Ninjask
107 106 Shedinja
108 107 Tyrogue
109 108 Hitmonlee
110 109 Hitmonchan
111 110 Hitmontop
112 111 Pancham
113 112 Pangoro
114 113 Klink
115 114 Klang
116 115 Klinklang
117 116 Combee
118 117 Vespiquen
119 118 Bronzor
120 119 Bronzong
121 120 Ralts
122 121 Kirlia
123 122 Gardevoir
124 123 Gallade
125 124 Drifloon
126 125 Drifblim
127 126 Gossifleur
128 127 Eldegoss
129 128 Cherubi
130 129 Cherrim
131 130 Stunky
132 131 Skuntank
133 132 Tympole
134 133 Palpitoad
135 134 Seismitoad
136 135 Duskull
137 136 Dusclops
138 137 Dusknoir
139 138 Machop
140 139 Machoke
141 140 Machamp
142 141 Gastly
143 142 Haunter
144 143 Gengar
145 144 Magikarp
146 145 Gyarados
147 146 Goldeen
148 147 Seaking
149 148 Remoraid
150 149 Octillery
151 150 Shellder
152 151 Cloyster
153 152 Feebas
154 153 Milotic
155 154 Basculin
156 155 Wishiwashi
157 156 Pyukumuku
158 157 Trubbish
159 158 Garbodor
160 159 Sizzlipede
161 160 Centiskorch
162 161 Rolycoly
163 162 Carkol
164 163 Coalossal
165 164 Diglett
166 165 Dugtrio
167 166 Drilbur
168 167 Excadrill
169 168 Roggenrola
170 169 Boldore
171 170 Gigalith
172 171 Timburr
173 172 Gurdurr
174 173 Conkeldurr
175 174 Woobat
176 175 Swoobat
177 176 Noibat
178 177 Noivern
179 178 Onix
180 179 Steelix
181 180 Arrokuda
182 181 Barraskewda
183 182 Meowth
184 183 Perrserker
185 184 Persian
186 185 Milcery
187 186 Alcremie
188 187 Cutiefly
189 188 Ribombee
190 189 Ferroseed
191 190 Ferrothorn
192 191 Pumpkaboo
193 192 Gourgeist
194 193 Pichu
195 194 Pikachu
196 195 Raichu
197 196 Eevee
198 197 Vaporeon
199 198 Jolteon
200 199 Flareon
201 200 Espeon
202 201 Umbreon
203 202 Leafeon
204 203 Glaceon
205 204 Sylveon
206 205 Applin
207 206 Flapple
208 207 Appletun
209 208 Espurr
210 209 Meowstic
211 210 Swirlix
212 211 Slurpuff
213 212 Spritzee
214 213 Aromatisse
215 214 Dewpider
216 215 Araquanid
217 216 Wynaut
218 217 Wobbuffet
219 218 Farfetch’d
220 219 Sirfetch’d
221 220 Chinchou
222 221 Lanturn
223 222 Croagunk
224 223 Toxicroak
225 224 Scraggy
226 225 Scrafty
227 226 Stunfisk
228 227 Shuckle
229 228 Barboach
230 229 Whiscash
231 230 Shellos
232 231 Gastrodon
233 232 Wimpod
234 233 Golisopod
235 234 Binacle
236 235 Barbaracle
237 236 Corsola
238 237 Cursola
239 238 Impidimp
240 239 Morgrem
241 240 Grimmsnarl
242 241 Hatenna
243 242 Hattrem
244 243 Hatterene
245 244 Salandit
246 245 Salazzle
247 246 Pawniard
248 247 Bisharp
249 248 Throh
250 249 Sawk
251 250 Koffing
252 251 Weezing
253 252 Bonsly
254 253 Sudowoodo
255 254 Cleffa
256 255 Clefairy
257 256 Clefable
258 257 Togepi
259 258 Togetic
260 259 Togekiss
261 260 Munchlax
262 261 Snorlax
263 262 Cottonee
264 263 Whimsicott
265 264 Rhyhorn
266 265 Rhydon
267 266 Rhyperior
268 267 Gothita
269 268 Gothorita
270 269 Gothitelle
271 270 Solosis
272 271 Duosion
273 272 Reuniclus
274 273 Karrablast
275 274 Escavalier
276 275 Shelmet
277 276 Accelgor
278 277 Elgyem
279 278 Beheeyem
280 279 Cubchoo
281 280 Beartic
282 281 Rufflet
283 282 Braviary
284 283 Vullaby
285 284 Mandibuzz
286 285 Skorupi
287 286 Drapion
288 287 Litwick
289 288 Lampent
290 289 Chandelure
291 290 Inkay
292 291 Malamar
293 292 Sneasel
294 293 Weavile
295 294 Sableye
296 295 Mawile
297 296 Maractus
298 297 Sigilyph
299 298 Riolu
300 299 Lucario
301 300 Torkoal
302 301 Mimikyu
303 302 Cufant
304 303 Copperajah
305 304 Qwilfish
306 305 Frillish
307 306 Jellicent
308 307 Mareanie
309 308 Toxapex
310 309 Cramorant
311 310 Toxel
312 311 Toxtricity
313 312 Silicobra
314 313 Sandaconda
315 314 Hippopotas
316 315 Hippowdon
317 316 Durant
318 317 Heatmor
319 318 Helioptile
320 319 Heliolisk
321 320 Hawlucha
322 321 Trapinch
323 322 Vibrava
324 323 Flygon
325 324 Axew
326 325 Fraxure
327 326 Haxorus
328 327 Yamask
329 328 Runerigus
330 329 Cofagrigus
331 330 Honedge
332 331 Doublade
333 332 Aegislash
334 333 Ponyta
335 334 Rapidash
336 335 Sinistea
337 336 Polteageist
338 337 Indeedee
339 338 Phantump
340 339 Trevenant
341 340 Morelull
342 341 Shiinotic
343 342 Oranguru
344 343 Passimian
345 344 Morpeko
346 345 Falinks
347 346 Drampa
348 347 Turtonator
349 348 Togedemaru
350 349 Snom
351 350 Frosmoth
352 351 Clobbopus
353 352 Grapploct
354 353 Pincurchin
355 354 Mantyke
356 355 Mantine
357 356 Wailmer
358 357 Wailord
359 358 Bergmite
360 359 Avalugg
361 360 Dhelmise
362 361 Lapras
363 362 Lunatone
364 363 Solrock
365 364 Mime Jr.
366 365 Mr. Mime
367 366 Mr. Rime
368 367 Darumaka
369 368 Darmanitan
370 369 Stonjourner
371 370 Eiscue
372 371 Duraludon
373 372 Rotom
374 373 Ditto
375 374 Dracozolt
376 375 Arctozolt
377 376 Dracovish
378 377 Arctovish
379 378 Charmander
380 379 Charmeleon
381 380 Charizard
382 381 Type: Null
383 382 Silvally
384 383 Larvitar
385 384 Pupitar
386 385 Tyranitar
387 386 Deino
388 387 Zweilous
389 388 Hydreigon
390 389 Goomy
391 390 Sliggoo
392 391 Goodra
393 392 Jangmo-o
394 393 Hakamo-o
395 394 Kommo-o
396 395 Dreepy
397 396 Drakloak
398 397 Dragapult
399 398 Zacian
400 399 Zamazenta
401 400 Eternatus
@@ -0,0 +1,161 @@
dexNumber,pokemon,form,notes
1,Pikipek,,
2,Trumbeak,,
3,Toucannon,,
4,Yungoos,,
5,Gumshoos,,
6,Rattata,,
7,Raticate,,
8,Caterpie,,
9,Metapod,,
10,Butterfree,,
11,Grubbin,,
12,Charjabug,,
13,Vikavolt,,
14,Bonsly,,
15,Sudowoodo,,
16,Happiny,,
17,Chansey,,
18,Blissey,,
19,Wingull,,
20,Pelipper,,
21,Crabrawler,,
22,Crabominable,,
23,Gastly,,
24,Haunter,,
25,Gengar,,
26,Zubat,,
27,Golbat,,
28,Crobat,,
29,Diglett,,
30,Dugtrio,,
31,Oricorio,,
32,Psyduck,,
33,Golduck,,
34,Magikarp,,
35,Gyarados,,
36,Barboach,,
37,Whiscash,,
38,Tentacool,,
39,Tentacruel,,
40,Finneon,,
41,Lumineon,,
42,Wishiwashi,,
43,Luvdisc,,
44,Corsola,,
45,Mareanie,,
46,Toxapex,,
47,Remoraid,,
48,Octillery,,
49,Mantyke,,
50,Mantine,,
51,Lillipup,,
52,Herdier,,
53,Stoutland,,
54,Eevee,,
55,Vaporeon,,
56,Jolteon,,
57,Flareon,,
58,Espeon,,
59,Umbreon,,
60,Leafeon,,
61,Glaceon,,
62,Sylveon,,
63,Mareep,,
64,Flaaffy,,
65,Ampharos,,
66,Mudbray,,
67,Mudsdale,,
68,Igglybuff,,
69,Jigglypuff,,
70,Wigglytuff,,
71,Tauros,,
72,Miltank,,
73,Surskit,,
74,Masquerain,,
75,Dewpider,,
76,Araquanid,,
77,Fomantis,,
78,Lurantis,,
79,Morelull,,
80,Shiinotic,,
81,Paras,,
82,Parasect,,
83,Poliwag,,
84,Poliwhirl,,
85,Poliwrath,,
86,Politoed,,
87,Goldeen,,
88,Seaking,,
89,Basculin,,
90,Feebas,,
91,Milotic,,
92,Alomomola,,
93,Fletchling,,
94,Fletchinder,,
95,Talonflame,,
96,Salandit,,
97,Salazzle,,
98,Cubone,,
99,Marowak,,
100,Kangaskhan,,
101,Magby,,
102,Magmar,,
103,Magmortar,,
104,Larvesta,,
105,Volcarona,,
106,Stufful,,
107,Bewear,,
108,Bounsweet,,
109,Steenee,,
110,Tsareena,,
111,Comfey,,
112,Pinsir,,
113,Hoothoot,,
114,Noctowl,,
115,Kecleon,,
116,Oranguru,,
117,Passimian,,
118,Goomy,,
119,Sliggoo,,
120,Goodra,,
121,Castform,,
122,Wimpod,,
123,Golisopod,,
124,Staryu,,
125,Starmie,,
126,Sandygast,,
127,Palossand,,
128,Omanyte,,
129,Omastar,,
130,Kabuto,,
131,Kabutops,,
132,Lileep,,
133,Cradily,,
134,Anorith,,
135,Armaldo,,
136,Cranidos,,
137,Rampardos,,
138,Shieldon,,
139,Bastiodon,,
140,Archen,,
141,Archeops,,
142,Tirtouga,,
143,Carracosta,,
144,Tyrunt,,
145,Tyrantrum,,
146,Amaura,,
147,Aurorus,,
148,Larvitar,,
149,Pupitar,,
150,Tyranitar,,
151,Phantump,,
152,Trevenant,,
153,Natu,,
154,Xatu,,
155,Nosepass,,
156,Probopass,,
157,Pyukumuku,,
158,Chinchou,,
159,Lanturn,,
160,Tapu Lele,,
1 dexNumber pokemon form notes
2 1 Pikipek
3 2 Trumbeak
4 3 Toucannon
5 4 Yungoos
6 5 Gumshoos
7 6 Rattata
8 7 Raticate
9 8 Caterpie
10 9 Metapod
11 10 Butterfree
12 11 Grubbin
13 12 Charjabug
14 13 Vikavolt
15 14 Bonsly
16 15 Sudowoodo
17 16 Happiny
18 17 Chansey
19 18 Blissey
20 19 Wingull
21 20 Pelipper
22 21 Crabrawler
23 22 Crabominable
24 23 Gastly
25 24 Haunter
26 25 Gengar
27 26 Zubat
28 27 Golbat
29 28 Crobat
30 29 Diglett
31 30 Dugtrio
32 31 Oricorio
33 32 Psyduck
34 33 Golduck
35 34 Magikarp
36 35 Gyarados
37 36 Barboach
38 37 Whiscash
39 38 Tentacool
40 39 Tentacruel
41 40 Finneon
42 41 Lumineon
43 42 Wishiwashi
44 43 Luvdisc
45 44 Corsola
46 45 Mareanie
47 46 Toxapex
48 47 Remoraid
49 48 Octillery
50 49 Mantyke
51 50 Mantine
52 51 Lillipup
53 52 Herdier
54 53 Stoutland
55 54 Eevee
56 55 Vaporeon
57 56 Jolteon
58 57 Flareon
59 58 Espeon
60 59 Umbreon
61 60 Leafeon
62 61 Glaceon
63 62 Sylveon
64 63 Mareep
65 64 Flaaffy
66 65 Ampharos
67 66 Mudbray
68 67 Mudsdale
69 68 Igglybuff
70 69 Jigglypuff
71 70 Wigglytuff
72 71 Tauros
73 72 Miltank
74 73 Surskit
75 74 Masquerain
76 75 Dewpider
77 76 Araquanid
78 77 Fomantis
79 78 Lurantis
80 79 Morelull
81 80 Shiinotic
82 81 Paras
83 82 Parasect
84 83 Poliwag
85 84 Poliwhirl
86 85 Poliwrath
87 86 Politoed
88 87 Goldeen
89 88 Seaking
90 89 Basculin
91 90 Feebas
92 91 Milotic
93 92 Alomomola
94 93 Fletchling
95 94 Fletchinder
96 95 Talonflame
97 96 Salandit
98 97 Salazzle
99 98 Cubone
100 99 Marowak
101 100 Kangaskhan
102 101 Magby
103 102 Magmar
104 103 Magmortar
105 104 Larvesta
106 105 Volcarona
107 106 Stufful
108 107 Bewear
109 108 Bounsweet
110 109 Steenee
111 110 Tsareena
112 111 Comfey
113 112 Pinsir
114 113 Hoothoot
115 114 Noctowl
116 115 Kecleon
117 116 Oranguru
118 117 Passimian
119 118 Goomy
120 119 Sliggoo
121 120 Goodra
122 121 Castform
123 122 Wimpod
124 123 Golisopod
125 124 Staryu
126 125 Starmie
127 126 Sandygast
128 127 Palossand
129 128 Omanyte
130 129 Omastar
131 130 Kabuto
132 131 Kabutops
133 132 Lileep
134 133 Cradily
135 134 Anorith
136 135 Armaldo
137 136 Cranidos
138 137 Rampardos
139 138 Shieldon
140 139 Bastiodon
141 140 Archen
142 141 Archeops
143 142 Tirtouga
144 143 Carracosta
145 144 Tyrunt
146 145 Tyrantrum
147 146 Amaura
148 147 Aurorus
149 148 Larvitar
150 149 Pupitar
151 150 Tyranitar
152 151 Phantump
153 152 Trevenant
154 153 Natu
155 154 Xatu
156 155 Nosepass
157 156 Probopass
158 157 Pyukumuku
159 158 Chinchou
160 159 Lanturn
161 160 Tapu Lele
@@ -0,0 +1,404 @@
dexNumber,pokemon,form,notes
1,Rowlet,,
2,Dartrix,,
3,Decidueye,,
4,Litten,,
5,Torracat,,
6,Incineroar,,
7,Popplio,,
8,Brionne,,
9,Primarina,,
10,Pikipek,,
11,Trumbeak,,
12,Toucannon,,
13,Yungoos,,
14,Gumshoos,,
15,Rattata,,
16,Raticate,,
17,Caterpie,,
18,Metapod,,
19,Butterfree,,
20,Ledyba,,
21,Ledian,,
22,Spinarak,,
23,Ariados,,
24,Buneary,,
25,Lopunny,,
26,Inkay,,
27,Malamar,,
28,Zorua,,
29,Zoroark,,
30,Furfrou,,
31,Pichu,,
32,Pikachu,,
33,Raichu,,
34,Grubbin,,
35,Charjabug,,
36,Vikavolt,,
37,Bonsly,,
38,Sudowoodo,,
39,Happiny,,
40,Chansey,,
41,Blissey,,
42,Munchlax,,
43,Snorlax,,
44,Slowpoke,,
45,Slowbro,,
46,Slowking,,
47,Wingull,,
48,Pelipper,,
49,Abra,,
50,Kadabra,,
51,Alakazam,,
52,Meowth,,
53,Persian,,
54,Magnemite,,
55,Magneton,,
56,Magnezone,,
57,Grimer,,
58,Muk,,
59,Mime Jr.,,
60,Mr. Mime,,
61,Ekans,,
62,Arbok,,
63,Dunsparce,,
64,Growlithe,,
65,Arcanine,,
66,Drowzee,,
67,Hypno,,
68,Makuhita,,
69,Hariyama,,
70,Smeargle,,
71,Crabrawler,,
72,Crabominable,,
73,Gastly,,
74,Haunter,,
75,Gengar,,
76,Drifloon,,
77,Drifblim,,
78,Murkrow,,
79,Honchkrow,,
80,Zubat,,
81,Golbat,,
82,Crobat,,
83,Noibat,,
84,Noivern,,
85,Diglett,,
86,Dugtrio,,
87,Spearow,,
88,Fearow,,
89,Rufflet,,
90,Braviary,,
91,Vullaby,,
92,Mandibuzz,,
93,Mankey,,
94,Primeape,,
95,Delibird,,
96,Hawlucha,,
97,Oricorio,,
98,Cutiefly,,
99,Ribombee,,
100,Flabébé,,
101,Floette,,
102,Florges,,
103,Petilil,,
104,Lilligant,,
105,Cottonee,,
106,Whimsicott,,
107,Psyduck,,
108,Golduck,,
109,Smoochum,,
110,Jynx,,
111,Magikarp,,
112,Gyarados,,
113,Barboach,,
114,Whiscash,,
115,Seel,,
116,Dewgong,,
117,Machop,,
118,Machoke,,
119,Machamp,,
120,Roggenrola,,
121,Boldore,,
122,Gigalith,,
123,Carbink,,
124,Sableye,,
125,Mawile,,
126,Rockruff,,
127,Lycanroc,,
128,Spinda,,
129,Tentacool,,
130,Tentacruel,,
131,Finneon,,
132,Lumineon,,
133,Wishiwashi,,
134,Luvdisc,,
135,Corsola,,
136,Mareanie,,
137,Toxapex,,
138,Shellder,,
139,Cloyster,,
140,Clamperl,,
141,Huntail,,
142,Gorebyss,,
143,Remoraid,,
144,Octillery,,
145,Mantyke,,
146,Mantine,,
147,Bagon,,
148,Shelgon,,
149,Salamence,,
150,Lillipup,,
151,Herdier,,
152,Stoutland,,
153,Eevee,,
154,Vaporeon,,
155,Jolteon,,
156,Flareon,,
157,Espeon,,
158,Umbreon,,
159,Leafeon,,
160,Glaceon,,
161,Sylveon,,
162,Mareep,,
163,Flaaffy,,
164,Ampharos,,
165,Mudbray,,
166,Mudsdale,,
167,Igglybuff,,
168,Jigglypuff,,
169,Wigglytuff,,
170,Tauros,,
171,Miltank,,
172,Surskit,,
173,Masquerain,,
174,Dewpider,,
175,Araquanid,,
176,Fomantis,,
177,Lurantis,,
178,Morelull,,
179,Shiinotic,,
180,Paras,,
181,Parasect,,
182,Poliwag,,
183,Poliwhirl,,
184,Poliwrath,,
185,Politoed,,
186,Goldeen,,
187,Seaking,,
188,Basculin,,
189,Feebas,,
190,Milotic,,
191,Alomomola,,
192,Fletchling,,
193,Fletchinder,,
194,Talonflame,,
195,Salandit,,
196,Salazzle,,
197,Cubone,,
198,Marowak,,
199,Kangaskhan,,
200,Magby,,
201,Magmar,,
202,Magmortar,,
203,Larvesta,,
204,Volcarona,,
205,Stufful,,
206,Bewear,,
207,Bounsweet,,
208,Steenee,,
209,Tsareena,,
210,Comfey,,
211,Pinsir,,
212,Hoothoot,,
213,Noctowl,,
214,Kecleon,,
215,Oranguru,,
216,Passimian,,
217,Goomy,,
218,Sliggoo,,
219,Goodra,,
220,Castform,,
221,Wimpod,,
222,Golisopod,,
223,Staryu,,
224,Starmie,,
225,Sandygast,,
226,Palossand,,
227,Omanyte,,
228,Omastar,,
229,Kabuto,,
230,Kabutops,,
231,Lileep,,
232,Cradily,,
233,Anorith,,
234,Armaldo,,
235,Cranidos,,
236,Rampardos,,
237,Shieldon,,
238,Bastiodon,,
239,Archen,,
240,Archeops,,
241,Tirtouga,,
242,Carracosta,,
243,Tyrunt,,
244,Tyrantrum,,
245,Amaura,,
246,Aurorus,,
247,Larvitar,,
248,Pupitar,,
249,Tyranitar,,
250,Phantump,,
251,Trevenant,,
252,Natu,,
253,Xatu,,
254,Nosepass,,
255,Probopass,,
256,Pyukumuku,,
257,Chinchou,,
258,Lanturn,,
259,Type: Null,,
260,Silvally,,
261,Poipole,,
262,Naganadel,,
263,Zygarde,,
264,Trubbish,,
265,Garbodor,,
266,Minccino,,
267,Cinccino,,
268,Pineco,,
269,Forretress,,
270,Skarmory,,
271,Ditto,,
272,Cleffa,,
273,Clefairy,,
274,Clefable,,
275,Elgyem,,
276,Beheeyem,,
277,Minior,,
278,Beldum,,
279,Metang,,
280,Metagross,,
281,Porygon,,
282,Porygon2,,
283,Porygon-Z,,
284,Pancham,,
285,Pangoro,,
286,Komala,,
287,Torkoal,,
288,Turtonator,,
289,Houndour,,
290,Houndoom,,
291,Dedenne,,
292,Togedemaru,,
293,Electrike,,
294,Manectric,,
295,Elekid,,
296,Electabuzz,,
297,Electivire,,
298,Geodude,,
299,Graveler,,
300,Golem,,
301,Sandile,,
302,Krokorok,,
303,Krookodile,,
304,Trapinch,,
305,Vibrava,,
306,Flygon,,
307,Gible,,
308,Gabite,,
309,Garchomp,,
310,Baltoy,,
311,Claydol,,
312,Golett,,
313,Golurk,,
314,Klefki,,
315,Mimikyu,,
316,Shuppet,,
317,Banette,,
318,Frillish,,
319,Jellicent,,
320,Bruxish,,
321,Drampa,,
322,Absol,,
323,Snorunt,,
324,Glalie,,
325,Froslass,,
326,Sneasel,,
327,Weavile,,
328,Sandshrew,,
329,Sandslash,,
330,Vulpix,,
331,Ninetales,,
332,Vanillite,,
333,Vanillish,,
334,Vanilluxe,,
335,Scraggy,,
336,Scrafty,,
337,Pawniard,,
338,Bisharp,,
339,Snubbull,,
340,Granbull,,
341,Shellos,,
342,Gastrodon,,
343,Relicanth,,
344,Dhelmise,,
345,Carvanha,,
346,Sharpedo,,
347,Skrelp,,
348,Dragalge,,
349,Clauncher,,
350,Clawitzer,,
351,Wailmer,,
352,Wailord,,
353,Lapras,,
354,Tropius,,
355,Exeggcute,,
356,Exeggutor,,
357,Corphish,,
358,Crawdaunt,,
359,Mienfoo,,
360,Mienshao,,
361,Jangmo-o,,
362,Hakamo-o,,
363,Kommo-o,,
364,Emolga,,
365,Scyther,,
366,Scizor,,
367,Heracross,,
368,Aipom,,
369,Ambipom,,
370,Litleo,,
371,Pyroar,,
372,Misdreavus,,
373,Mismagius,,
374,Druddigon,,
375,Lickitung,,
376,Lickilicky,,
377,Riolu,,
378,Lucario,,
379,Dratini,,
380,Dragonair,,
381,Dragonite,,
382,Aerodactyl,,
383,Tapu Koko,,
384,Tapu Lele,,
385,Tapu Bulu,,
386,Tapu Fini,,
387,Cosmog,,
388,Cosmoem,,
389,Solgaleo,,
390,Lunala,,
391,Stakataka,,
392,Blacephalon,,
393,Nihilego,,
394,Buzzwole,,
395,Pheromosa,,
396,Xurkitree,,
397,Celesteela,,
398,Kartana,,
399,Guzzlord,,
400,Necrozma,,
401,Magearna,,
402,Marshadow,,
403,Zeraora,,
1 dexNumber pokemon form notes
2 1 Rowlet
3 2 Dartrix
4 3 Decidueye
5 4 Litten
6 5 Torracat
7 6 Incineroar
8 7 Popplio
9 8 Brionne
10 9 Primarina
11 10 Pikipek
12 11 Trumbeak
13 12 Toucannon
14 13 Yungoos
15 14 Gumshoos
16 15 Rattata
17 16 Raticate
18 17 Caterpie
19 18 Metapod
20 19 Butterfree
21 20 Ledyba
22 21 Ledian
23 22 Spinarak
24 23 Ariados
25 24 Buneary
26 25 Lopunny
27 26 Inkay
28 27 Malamar
29 28 Zorua
30 29 Zoroark
31 30 Furfrou
32 31 Pichu
33 32 Pikachu
34 33 Raichu
35 34 Grubbin
36 35 Charjabug
37 36 Vikavolt
38 37 Bonsly
39 38 Sudowoodo
40 39 Happiny
41 40 Chansey
42 41 Blissey
43 42 Munchlax
44 43 Snorlax
45 44 Slowpoke
46 45 Slowbro
47 46 Slowking
48 47 Wingull
49 48 Pelipper
50 49 Abra
51 50 Kadabra
52 51 Alakazam
53 52 Meowth
54 53 Persian
55 54 Magnemite
56 55 Magneton
57 56 Magnezone
58 57 Grimer
59 58 Muk
60 59 Mime Jr.
61 60 Mr. Mime
62 61 Ekans
63 62 Arbok
64 63 Dunsparce
65 64 Growlithe
66 65 Arcanine
67 66 Drowzee
68 67 Hypno
69 68 Makuhita
70 69 Hariyama
71 70 Smeargle
72 71 Crabrawler
73 72 Crabominable
74 73 Gastly
75 74 Haunter
76 75 Gengar
77 76 Drifloon
78 77 Drifblim
79 78 Murkrow
80 79 Honchkrow
81 80 Zubat
82 81 Golbat
83 82 Crobat
84 83 Noibat
85 84 Noivern
86 85 Diglett
87 86 Dugtrio
88 87 Spearow
89 88 Fearow
90 89 Rufflet
91 90 Braviary
92 91 Vullaby
93 92 Mandibuzz
94 93 Mankey
95 94 Primeape
96 95 Delibird
97 96 Hawlucha
98 97 Oricorio
99 98 Cutiefly
100 99 Ribombee
101 100 Flabébé
102 101 Floette
103 102 Florges
104 103 Petilil
105 104 Lilligant
106 105 Cottonee
107 106 Whimsicott
108 107 Psyduck
109 108 Golduck
110 109 Smoochum
111 110 Jynx
112 111 Magikarp
113 112 Gyarados
114 113 Barboach
115 114 Whiscash
116 115 Seel
117 116 Dewgong
118 117 Machop
119 118 Machoke
120 119 Machamp
121 120 Roggenrola
122 121 Boldore
123 122 Gigalith
124 123 Carbink
125 124 Sableye
126 125 Mawile
127 126 Rockruff
128 127 Lycanroc
129 128 Spinda
130 129 Tentacool
131 130 Tentacruel
132 131 Finneon
133 132 Lumineon
134 133 Wishiwashi
135 134 Luvdisc
136 135 Corsola
137 136 Mareanie
138 137 Toxapex
139 138 Shellder
140 139 Cloyster
141 140 Clamperl
142 141 Huntail
143 142 Gorebyss
144 143 Remoraid
145 144 Octillery
146 145 Mantyke
147 146 Mantine
148 147 Bagon
149 148 Shelgon
150 149 Salamence
151 150 Lillipup
152 151 Herdier
153 152 Stoutland
154 153 Eevee
155 154 Vaporeon
156 155 Jolteon
157 156 Flareon
158 157 Espeon
159 158 Umbreon
160 159 Leafeon
161 160 Glaceon
162 161 Sylveon
163 162 Mareep
164 163 Flaaffy
165 164 Ampharos
166 165 Mudbray
167 166 Mudsdale
168 167 Igglybuff
169 168 Jigglypuff
170 169 Wigglytuff
171 170 Tauros
172 171 Miltank
173 172 Surskit
174 173 Masquerain
175 174 Dewpider
176 175 Araquanid
177 176 Fomantis
178 177 Lurantis
179 178 Morelull
180 179 Shiinotic
181 180 Paras
182 181 Parasect
183 182 Poliwag
184 183 Poliwhirl
185 184 Poliwrath
186 185 Politoed
187 186 Goldeen
188 187 Seaking
189 188 Basculin
190 189 Feebas
191 190 Milotic
192 191 Alomomola
193 192 Fletchling
194 193 Fletchinder
195 194 Talonflame
196 195 Salandit
197 196 Salazzle
198 197 Cubone
199 198 Marowak
200 199 Kangaskhan
201 200 Magby
202 201 Magmar
203 202 Magmortar
204 203 Larvesta
205 204 Volcarona
206 205 Stufful
207 206 Bewear
208 207 Bounsweet
209 208 Steenee
210 209 Tsareena
211 210 Comfey
212 211 Pinsir
213 212 Hoothoot
214 213 Noctowl
215 214 Kecleon
216 215 Oranguru
217 216 Passimian
218 217 Goomy
219 218 Sliggoo
220 219 Goodra
221 220 Castform
222 221 Wimpod
223 222 Golisopod
224 223 Staryu
225 224 Starmie
226 225 Sandygast
227 226 Palossand
228 227 Omanyte
229 228 Omastar
230 229 Kabuto
231 230 Kabutops
232 231 Lileep
233 232 Cradily
234 233 Anorith
235 234 Armaldo
236 235 Cranidos
237 236 Rampardos
238 237 Shieldon
239 238 Bastiodon
240 239 Archen
241 240 Archeops
242 241 Tirtouga
243 242 Carracosta
244 243 Tyrunt
245 244 Tyrantrum
246 245 Amaura
247 246 Aurorus
248 247 Larvitar
249 248 Pupitar
250 249 Tyranitar
251 250 Phantump
252 251 Trevenant
253 252 Natu
254 253 Xatu
255 254 Nosepass
256 255 Probopass
257 256 Pyukumuku
258 257 Chinchou
259 258 Lanturn
260 259 Type: Null
261 260 Silvally
262 261 Poipole
263 262 Naganadel
264 263 Zygarde
265 264 Trubbish
266 265 Garbodor
267 266 Minccino
268 267 Cinccino
269 268 Pineco
270 269 Forretress
271 270 Skarmory
272 271 Ditto
273 272 Cleffa
274 273 Clefairy
275 274 Clefable
276 275 Elgyem
277 276 Beheeyem
278 277 Minior
279 278 Beldum
280 279 Metang
281 280 Metagross
282 281 Porygon
283 282 Porygon2
284 283 Porygon-Z
285 284 Pancham
286 285 Pangoro
287 286 Komala
288 287 Torkoal
289 288 Turtonator
290 289 Houndour
291 290 Houndoom
292 291 Dedenne
293 292 Togedemaru
294 293 Electrike
295 294 Manectric
296 295 Elekid
297 296 Electabuzz
298 297 Electivire
299 298 Geodude
300 299 Graveler
301 300 Golem
302 301 Sandile
303 302 Krokorok
304 303 Krookodile
305 304 Trapinch
306 305 Vibrava
307 306 Flygon
308 307 Gible
309 308 Gabite
310 309 Garchomp
311 310 Baltoy
312 311 Claydol
313 312 Golett
314 313 Golurk
315 314 Klefki
316 315 Mimikyu
317 316 Shuppet
318 317 Banette
319 318 Frillish
320 319 Jellicent
321 320 Bruxish
322 321 Drampa
323 322 Absol
324 323 Snorunt
325 324 Glalie
326 325 Froslass
327 326 Sneasel
328 327 Weavile
329 328 Sandshrew
330 329 Sandslash
331 330 Vulpix
332 331 Ninetales
333 332 Vanillite
334 333 Vanillish
335 334 Vanilluxe
336 335 Scraggy
337 336 Scrafty
338 337 Pawniard
339 338 Bisharp
340 339 Snubbull
341 340 Granbull
342 341 Shellos
343 342 Gastrodon
344 343 Relicanth
345 344 Dhelmise
346 345 Carvanha
347 346 Sharpedo
348 347 Skrelp
349 348 Dragalge
350 349 Clauncher
351 350 Clawitzer
352 351 Wailmer
353 352 Wailord
354 353 Lapras
355 354 Tropius
356 355 Exeggcute
357 356 Exeggutor
358 357 Corphish
359 358 Crawdaunt
360 359 Mienfoo
361 360 Mienshao
362 361 Jangmo-o
363 362 Hakamo-o
364 363 Kommo-o
365 364 Emolga
366 365 Scyther
367 366 Scizor
368 367 Heracross
369 368 Aipom
370 369 Ambipom
371 370 Litleo
372 371 Pyroar
373 372 Misdreavus
374 373 Mismagius
375 374 Druddigon
376 375 Lickitung
377 376 Lickilicky
378 377 Riolu
379 378 Lucario
380 379 Dratini
381 380 Dragonair
382 381 Dragonite
383 382 Aerodactyl
384 383 Tapu Koko
385 384 Tapu Lele
386 385 Tapu Bulu
387 386 Tapu Fini
388 387 Cosmog
389 388 Cosmoem
390 389 Solgaleo
391 390 Lunala
392 391 Stakataka
393 392 Blacephalon
394 393 Nihilego
395 394 Buzzwole
396 395 Pheromosa
397 396 Xurkitree
398 397 Celesteela
399 398 Kartana
400 399 Guzzlord
401 400 Necrozma
402 401 Magearna
403 402 Marshadow
404 403 Zeraora
@@ -0,0 +1,151 @@
dexNumber,pokemon,form,notes
1,Rowlet,,
2,Dartrix,,
3,Decidueye,,
4,Litten,,
5,Torracat,,
6,Incineroar,,
7,Popplio,,
8,Brionne,,
9,Primarina,,
10,Pikipek,,
11,Trumbeak,,
12,Toucannon,,
13,Yungoos,,
14,Gumshoos,,
15,Rattata,,
16,Raticate,,
17,Caterpie,,
18,Metapod,,
19,Butterfree,,
20,Ledyba,,
21,Ledian,,
22,Spinarak,,
23,Ariados,,
24,Buneary,,
25,Lopunny,,
26,Inkay,,
27,Malamar,,
28,Zorua,,
29,Zoroark,,
30,Furfrou,,
31,Pichu,,
32,Pikachu,,
33,Raichu,,
34,Grubbin,,
35,Charjabug,,
36,Vikavolt,,
37,Bonsly,,
38,Sudowoodo,,
39,Happiny,,
40,Chansey,,
41,Blissey,,
42,Munchlax,,
43,Snorlax,,
44,Slowpoke,,
45,Slowbro,,
46,Slowking,,
47,Wingull,,
48,Pelipper,,
49,Abra,,
50,Kadabra,,
51,Alakazam,,
52,Meowth,,
53,Persian,,
54,Magnemite,,
55,Magneton,,
56,Magnezone,,
57,Grimer,,
58,Muk,,
59,Mime Jr.,,
60,Mr. Mime,,
61,Ekans,,
62,Arbok,,
63,Dunsparce,,
64,Growlithe,,
65,Arcanine,,
66,Drowzee,,
67,Hypno,,
68,Makuhita,,
69,Hariyama,,
70,Smeargle,,
71,Crabrawler,,
72,Crabominable,,
73,Gastly,,
74,Haunter,,
75,Gengar,,
76,Drifloon,,
77,Drifblim,,
78,Murkrow,,
79,Honchkrow,,
80,Zubat,,
81,Golbat,,
82,Crobat,,
83,Noibat,,
84,Noivern,,
85,Diglett,,
86,Dugtrio,,
87,Spearow,,
88,Fearow,,
89,Rufflet,,
90,Braviary,,
91,Vullaby,,
92,Mandibuzz,,
93,Mankey,,
94,Primeape,,
95,Delibird,,
96,Hawlucha,,
97,Oricorio,,
98,Cutiefly,,
99,Ribombee,,
100,Flabébé,,
101,Floette,,
102,Florges,,
103,Petilil,,
104,Lilligant,,
105,Cottonee,,
106,Whimsicott,,
107,Psyduck,,
108,Golduck,,
109,Smoochum,,
110,Jynx,,
111,Magikarp,,
112,Gyarados,,
113,Barboach,,
114,Whiscash,,
115,Seel,,
116,Dewgong,,
117,Machop,,
118,Machoke,,
119,Machamp,,
120,Roggenrola,,
121,Boldore,,
122,Gigalith,,
123,Carbink,,
124,Sableye,,
125,Mawile,,
126,Rockruff,,
127,Lycanroc,,
128,Spinda,,
129,Tentacool,,
130,Tentacruel,,
131,Finneon,,
132,Lumineon,,
133,Wishiwashi,,
134,Luvdisc,,
135,Corsola,,
136,Mareanie,,
137,Toxapex,,
138,Shellder,,
139,Cloyster,,
140,Clamperl,,
141,Huntail,,
142,Gorebyss,,
143,Remoraid,,
144,Octillery,,
145,Mantyke,,
146,Mantine,,
147,Bagon,,
148,Shelgon,,
149,Salamence,,
150,Tapu Koko,,
1 dexNumber pokemon form notes
2 1 Rowlet
3 2 Dartrix
4 3 Decidueye
5 4 Litten
6 5 Torracat
7 6 Incineroar
8 7 Popplio
9 8 Brionne
10 9 Primarina
11 10 Pikipek
12 11 Trumbeak
13 12 Toucannon
14 13 Yungoos
15 14 Gumshoos
16 15 Rattata
17 16 Raticate
18 17 Caterpie
19 18 Metapod
20 19 Butterfree
21 20 Ledyba
22 21 Ledian
23 22 Spinarak
24 23 Ariados
25 24 Buneary
26 25 Lopunny
27 26 Inkay
28 27 Malamar
29 28 Zorua
30 29 Zoroark
31 30 Furfrou
32 31 Pichu
33 32 Pikachu
34 33 Raichu
35 34 Grubbin
36 35 Charjabug
37 36 Vikavolt
38 37 Bonsly
39 38 Sudowoodo
40 39 Happiny
41 40 Chansey
42 41 Blissey
43 42 Munchlax
44 43 Snorlax
45 44 Slowpoke
46 45 Slowbro
47 46 Slowking
48 47 Wingull
49 48 Pelipper
50 49 Abra
51 50 Kadabra
52 51 Alakazam
53 52 Meowth
54 53 Persian
55 54 Magnemite
56 55 Magneton
57 56 Magnezone
58 57 Grimer
59 58 Muk
60 59 Mime Jr.
61 60 Mr. Mime
62 61 Ekans
63 62 Arbok
64 63 Dunsparce
65 64 Growlithe
66 65 Arcanine
67 66 Drowzee
68 67 Hypno
69 68 Makuhita
70 69 Hariyama
71 70 Smeargle
72 71 Crabrawler
73 72 Crabominable
74 73 Gastly
75 74 Haunter
76 75 Gengar
77 76 Drifloon
78 77 Drifblim
79 78 Murkrow
80 79 Honchkrow
81 80 Zubat
82 81 Golbat
83 82 Crobat
84 83 Noibat
85 84 Noivern
86 85 Diglett
87 86 Dugtrio
88 87 Spearow
89 88 Fearow
90 89 Rufflet
91 90 Braviary
92 91 Vullaby
93 92 Mandibuzz
94 93 Mankey
95 94 Primeape
96 95 Delibird
97 96 Hawlucha
98 97 Oricorio
99 98 Cutiefly
100 99 Ribombee
101 100 Flabébé
102 101 Floette
103 102 Florges
104 103 Petilil
105 104 Lilligant
106 105 Cottonee
107 106 Whimsicott
108 107 Psyduck
109 108 Golduck
110 109 Smoochum
111 110 Jynx
112 111 Magikarp
113 112 Gyarados
114 113 Barboach
115 114 Whiscash
116 115 Seel
117 116 Dewgong
118 117 Machop
119 118 Machoke
120 119 Machamp
121 120 Roggenrola
122 121 Boldore
123 122 Gigalith
124 123 Carbink
125 124 Sableye
126 125 Mawile
127 126 Rockruff
128 127 Lycanroc
129 128 Spinda
130 129 Tentacool
131 130 Tentacruel
132 131 Finneon
133 132 Lumineon
134 133 Wishiwashi
135 134 Luvdisc
136 135 Corsola
137 136 Mareanie
138 137 Toxapex
139 138 Shellder
140 139 Cloyster
141 140 Clamperl
142 141 Huntail
143 142 Gorebyss
144 143 Remoraid
145 144 Octillery
146 145 Mantyke
147 146 Mantine
148 147 Bagon
149 148 Shelgon
150 149 Salamence
151 150 Tapu Koko
@@ -0,0 +1,131 @@
dexNumber,pokemon,form,notes
1,Pikipek,,
2,Trumbeak,,
3,Toucannon,,
4,Yungoos,,
5,Gumshoos,,
6,Rattata,,
7,Raticate,,
8,Buneary,,
9,Lopunny,,
10,Inkay,,
11,Malamar,,
12,Zorua,,
13,Zoroark,,
14,Furfrou,,
15,Happiny,,
16,Chansey,,
17,Blissey,,
18,Wingull,,
19,Pelipper,,
20,Drowzee,,
21,Hypno,,
22,Makuhita,,
23,Hariyama,,
24,Crabrawler,,
25,Crabominable,,
26,Zubat,,
27,Golbat,,
28,Crobat,,
29,Noibat,,
30,Noivern,,
31,Diglett,,
32,Dugtrio,,
33,Spearow,,
34,Fearow,,
35,Rufflet,,
36,Braviary,,
37,Vullaby,,
38,Mandibuzz,,
39,Mankey,,
40,Primeape,,
41,Oricorio,,
42,Cutiefly,,
43,Ribombee,,
44,Flabébé,,
45,Floette,,
46,Florges,,
47,Petilil,,
48,Lilligant,,
49,Cottonee,,
50,Whimsicott,,
51,Psyduck,,
52,Golduck,,
53,Magikarp,,
54,Gyarados,,
55,Barboach,,
56,Whiscash,,
57,Machop,,
58,Machoke,,
59,Machamp,,
60,Roggenrola,,
61,Boldore,,
62,Gigalith,,
63,Carbink,,
64,Sableye,,
65,Rockruff,,
66,Lycanroc,,
67,Tentacool,,
68,Tentacruel,,
69,Finneon,,
70,Lumineon,,
71,Mudbray,,
72,Mudsdale,,
73,Tauros,,
74,Miltank,,
75,Basculin,,
76,Stufful,,
77,Bewear,,
78,Pinsir,,
79,Goomy,,
80,Sliggoo,,
81,Goodra,,
82,Castform,,
83,Wimpod,,
84,Golisopod,,
85,Skarmory,,
86,Snubbull,,
87,Granbull,,
88,Shellos,,
89,Gastrodon,,
90,Relicanth,,
91,Dhelmise,,
92,Carvanha,,
93,Sharpedo,,
94,Skrelp,,
95,Dragalge,,
96,Clauncher,,
97,Clawitzer,,
98,Wailmer,,
99,Wailord,,
100,Lapras,,
101,Tropius,,
102,Exeggcute,,
103,Exeggutor,,
104,Corphish,,
105,Crawdaunt,,
106,Mienfoo,,
107,Mienshao,,
108,Jangmo-o,,
109,Hakamo-o,,
110,Kommo-o,,
111,Emolga,,
112,Scyther,,
113,Scizor,,
114,Heracross,,
115,Aipom,,
116,Ambipom,,
117,Litleo,,
118,Pyroar,,
119,Misdreavus,,
120,Mismagius,,
121,Druddigon,,
122,Lickitung,,
123,Lickilicky,,
124,Riolu,,
125,Lucario,,
126,Dratini,,
127,Dragonair,,
128,Dragonite,,
129,Aerodactyl,,
130,Tapu Fini,,
1 dexNumber pokemon form notes
2 1 Pikipek
3 2 Trumbeak
4 3 Toucannon
5 4 Yungoos
6 5 Gumshoos
7 6 Rattata
8 7 Raticate
9 8 Buneary
10 9 Lopunny
11 10 Inkay
12 11 Malamar
13 12 Zorua
14 13 Zoroark
15 14 Furfrou
16 15 Happiny
17 16 Chansey
18 17 Blissey
19 18 Wingull
20 19 Pelipper
21 20 Drowzee
22 21 Hypno
23 22 Makuhita
24 23 Hariyama
25 24 Crabrawler
26 25 Crabominable
27 26 Zubat
28 27 Golbat
29 28 Crobat
30 29 Noibat
31 30 Noivern
32 31 Diglett
33 32 Dugtrio
34 33 Spearow
35 34 Fearow
36 35 Rufflet
37 36 Braviary
38 37 Vullaby
39 38 Mandibuzz
40 39 Mankey
41 40 Primeape
42 41 Oricorio
43 42 Cutiefly
44 43 Ribombee
45 44 Flabébé
46 45 Floette
47 46 Florges
48 47 Petilil
49 48 Lilligant
50 49 Cottonee
51 50 Whimsicott
52 51 Psyduck
53 52 Golduck
54 53 Magikarp
55 54 Gyarados
56 55 Barboach
57 56 Whiscash
58 57 Machop
59 58 Machoke
60 59 Machamp
61 60 Roggenrola
62 61 Boldore
63 62 Gigalith
64 63 Carbink
65 64 Sableye
66 65 Rockruff
67 66 Lycanroc
68 67 Tentacool
69 68 Tentacruel
70 69 Finneon
71 70 Lumineon
72 71 Mudbray
73 72 Mudsdale
74 73 Tauros
75 74 Miltank
76 75 Basculin
77 76 Stufful
78 77 Bewear
79 78 Pinsir
80 79 Goomy
81 80 Sliggoo
82 81 Goodra
83 82 Castform
84 83 Wimpod
85 84 Golisopod
86 85 Skarmory
87 86 Snubbull
88 87 Granbull
89 88 Shellos
90 89 Gastrodon
91 90 Relicanth
92 91 Dhelmise
93 92 Carvanha
94 93 Sharpedo
95 94 Skrelp
96 95 Dragalge
97 96 Clauncher
98 97 Clawitzer
99 98 Wailmer
100 99 Wailord
101 100 Lapras
102 101 Tropius
103 102 Exeggcute
104 103 Exeggutor
105 104 Corphish
106 105 Crawdaunt
107 106 Mienfoo
108 107 Mienshao
109 108 Jangmo-o
110 109 Hakamo-o
111 110 Kommo-o
112 111 Emolga
113 112 Scyther
114 113 Scizor
115 114 Heracross
116 115 Aipom
117 116 Ambipom
118 117 Litleo
119 118 Pyroar
120 119 Misdreavus
121 120 Mismagius
122 121 Druddigon
123 122 Lickitung
124 123 Lickilicky
125 124 Riolu
126 125 Lucario
127 126 Dratini
128 127 Dragonair
129 128 Dragonite
130 129 Aerodactyl
131 130 Tapu Fini
@@ -0,0 +1,161 @@
dexNumber,pokemon,form,notes
1,Pikipek,,
2,Trumbeak,,
3,Toucannon,,
4,Yungoos,,
5,Gumshoos,,
6,Rattata,,
7,Raticate,,
8,Ledyba,,
9,Ledian,,
10,Spinarak,,
11,Ariados,,
12,Grubbin,,
13,Charjabug,,
14,Vikavolt,,
15,Happiny,,
16,Chansey,,
17,Blissey,,
18,Slowpoke,,
19,Slowbro,,
20,Slowking,,
21,Wingull,,
22,Pelipper,,
23,Meowth,,
24,Persian,,
25,Magnemite,,
26,Magneton,,
27,Magnezone,,
28,Grimer,,
29,Muk,,
30,Crabrawler,,
31,Crabominable,,
32,Gastly,,
33,Haunter,,
34,Gengar,,
35,Zubat,,
36,Golbat,,
37,Crobat,,
38,Diglett,,
39,Dugtrio,,
40,Spearow,,
41,Fearow,,
42,Oricorio,,
43,Cutiefly,,
44,Ribombee,,
45,Flabébé,,
46,Floette,,
47,Florges,,
48,Petilil,,
49,Lilligant,,
50,Cottonee,,
51,Whimsicott,,
52,Psyduck,,
53,Golduck,,
54,Magikarp,,
55,Gyarados,,
56,Tentacool,,
57,Tentacruel,,
58,Finneon,,
59,Lumineon,,
60,Wishiwashi,,
61,Clamperl,,
62,Huntail,,
63,Gorebyss,,
64,Mudbray,,
65,Mudsdale,,
66,Surskit,,
67,Masquerain,,
68,Dewpider,,
69,Araquanid,,
70,Morelull,,
71,Shiinotic,,
72,Paras,,
73,Parasect,,
74,Poliwag,,
75,Poliwhirl,,
76,Poliwrath,,
77,Politoed,,
78,Goldeen,,
79,Seaking,,
80,Basculin,,
81,Goomy,,
82,Sliggoo,,
83,Goodra,,
84,Castform,,
85,Trubbish,,
86,Garbodor,,
87,Minccino,,
88,Cinccino,,
89,Pineco,,
90,Forretress,,
91,Skarmory,,
92,Ditto,,
93,Cleffa,,
94,Clefairy,,
95,Clefable,,
96,Elgyem,,
97,Beheeyem,,
98,Minior,,
99,Beldum,,
100,Metang,,
101,Metagross,,
102,Porygon,,
103,Porygon2,,
104,Porygon-Z,,
105,Pancham,,
106,Pangoro,,
107,Komala,,
108,Torkoal,,
109,Turtonator,,
110,Houndour,,
111,Houndoom,,
112,Dedenne,,
113,Togedemaru,,
114,Electrike,,
115,Manectric,,
116,Elekid,,
117,Electabuzz,,
118,Electivire,,
119,Geodude,,
120,Graveler,,
121,Golem,,
122,Sandile,,
123,Krokorok,,
124,Krookodile,,
125,Trapinch,,
126,Vibrava,,
127,Flygon,,
128,Gible,,
129,Gabite,,
130,Garchomp,,
131,Baltoy,,
132,Claydol,,
133,Golett,,
134,Golurk,,
135,Klefki,,
136,Mimikyu,,
137,Shuppet,,
138,Banette,,
139,Frillish,,
140,Jellicent,,
141,Bruxish,,
142,Drampa,,
143,Absol,,
144,Snorunt,,
145,Glalie,,
146,Froslass,,
147,Sneasel,,
148,Weavile,,
149,Sandshrew,,
150,Sandslash,,
151,Vulpix,,
152,Ninetales,,
153,Vanillite,,
154,Vanillish,,
155,Vanilluxe,,
156,Scraggy,,
157,Scrafty,,
158,Pawniard,,
159,Bisharp,,
160,Tapu Bulu,,
1 dexNumber pokemon form notes
2 1 Pikipek
3 2 Trumbeak
4 3 Toucannon
5 4 Yungoos
6 5 Gumshoos
7 6 Rattata
8 7 Raticate
9 8 Ledyba
10 9 Ledian
11 10 Spinarak
12 11 Ariados
13 12 Grubbin
14 13 Charjabug
15 14 Vikavolt
16 15 Happiny
17 16 Chansey
18 17 Blissey
19 18 Slowpoke
20 19 Slowbro
21 20 Slowking
22 21 Wingull
23 22 Pelipper
24 23 Meowth
25 24 Persian
26 25 Magnemite
27 26 Magneton
28 27 Magnezone
29 28 Grimer
30 29 Muk
31 30 Crabrawler
32 31 Crabominable
33 32 Gastly
34 33 Haunter
35 34 Gengar
36 35 Zubat
37 36 Golbat
38 37 Crobat
39 38 Diglett
40 39 Dugtrio
41 40 Spearow
42 41 Fearow
43 42 Oricorio
44 43 Cutiefly
45 44 Ribombee
46 45 Flabébé
47 46 Floette
48 47 Florges
49 48 Petilil
50 49 Lilligant
51 50 Cottonee
52 51 Whimsicott
53 52 Psyduck
54 53 Golduck
55 54 Magikarp
56 55 Gyarados
57 56 Tentacool
58 57 Tentacruel
59 58 Finneon
60 59 Lumineon
61 60 Wishiwashi
62 61 Clamperl
63 62 Huntail
64 63 Gorebyss
65 64 Mudbray
66 65 Mudsdale
67 66 Surskit
68 67 Masquerain
69 68 Dewpider
70 69 Araquanid
71 70 Morelull
72 71 Shiinotic
73 72 Paras
74 73 Parasect
75 74 Poliwag
76 75 Poliwhirl
77 76 Poliwrath
78 77 Politoed
79 78 Goldeen
80 79 Seaking
81 80 Basculin
82 81 Goomy
83 82 Sliggoo
84 83 Goodra
85 84 Castform
86 85 Trubbish
87 86 Garbodor
88 87 Minccino
89 88 Cinccino
90 89 Pineco
91 90 Forretress
92 91 Skarmory
93 92 Ditto
94 93 Cleffa
95 94 Clefairy
96 95 Clefable
97 96 Elgyem
98 97 Beheeyem
99 98 Minior
100 99 Beldum
101 100 Metang
102 101 Metagross
103 102 Porygon
104 103 Porygon2
105 104 Porygon-Z
106 105 Pancham
107 106 Pangoro
108 107 Komala
109 108 Torkoal
110 109 Turtonator
111 110 Houndour
112 111 Houndoom
113 112 Dedenne
114 113 Togedemaru
115 114 Electrike
116 115 Manectric
117 116 Elekid
118 117 Electabuzz
119 118 Electivire
120 119 Geodude
121 120 Graveler
122 121 Golem
123 122 Sandile
124 123 Krokorok
125 124 Krookodile
126 125 Trapinch
127 126 Vibrava
128 127 Flygon
129 128 Gible
130 129 Gabite
131 130 Garchomp
132 131 Baltoy
133 132 Claydol
134 133 Golett
135 134 Golurk
136 135 Klefki
137 136 Mimikyu
138 137 Shuppet
139 138 Banette
140 139 Frillish
141 140 Jellicent
142 141 Bruxish
143 142 Drampa
144 143 Absol
145 144 Snorunt
146 145 Glalie
147 146 Froslass
148 147 Sneasel
149 148 Weavile
150 149 Sandshrew
151 150 Sandslash
152 151 Vulpix
153 152 Ninetales
154 153 Vanillite
155 154 Vanillish
156 155 Vanilluxe
157 156 Scraggy
158 157 Scrafty
159 158 Pawniard
160 159 Bisharp
161 160 Tapu Bulu
@@ -0,0 +1,154 @@
dexNumber,pokemon,form,notes
1,Chespin,,
2,Quilladin,,
3,Chesnaught,,
4,Fennekin,,
5,Braixen,,
6,Delphox,,
7,Froakie,,
8,Frogadier,,
9,Greninja,,
10,Bunnelby,,
11,Diggersby,,
12,Zigzagoon,,
13,Linoone,,
14,Fletchling,,
15,Fletchinder,,
16,Talonflame,,
17,Pidgey,,
18,Pidgeotto,,
19,Pidgeot,,
20,Scatterbug,,
21,Spewpa,,
22,Vivillon,,
23,Caterpie,,
24,Metapod,,
25,Butterfree,,
26,Weedle,,
27,Kakuna,,
28,Beedrill,,
29,Pansage,,
30,Simisage,,
31,Pansear,,
32,Simisear,,
33,Panpour,,
34,Simipour,,
35,Pichu,,
36,Pikachu,,
37,Raichu,,
38,Bidoof,,
39,Bibarel,,
40,Dunsparce,,
41,Azurill,,
42,Marill,,
43,Azumarill,,
44,Burmy,,
45,Wormadam,,
46,Mothim,,
47,Surskit,,
48,Masquerain,,
49,Magikarp,,
50,Gyarados,,
51,Corphish,,
52,Crawdaunt,,
53,Goldeen,,
54,Seaking,,
55,Carvanha,,
56,Sharpedo,,
57,Litleo,,
58,Pyroar,,
59,Psyduck,,
60,Golduck,,
61,Farfetchd,,
62,Riolu,,
63,Lucario,,
64,Ralts,,
65,Kirlia,,
66,Gardevoir,,
67,Gallade,,
68,Flabébé,,
69,Floette,,
70,Florges,,
71,Budew,,
72,Roselia,,
73,Roserade,,
74,Ledyba,,
75,Ledian,,
76,Combee,,
77,Vespiquen,,
78,Skitty,,
79,Delcatty,,
80,Bulbasaur,,
81,Ivysaur,,
82,Venusaur,,
83,Charmander,,
84,Charmeleon,,
85,Charizard,,
86,Squirtle,,
87,Wartortle,,
88,Blastoise,,
89,Skiddo,,
90,Gogoat,,
91,Pancham,,
92,Pangoro,,
93,Furfrou,,
94,Doduo,,
95,Dodrio,,
96,Plusle,,
97,Minun,,
98,Gulpin,,
99,Swalot,,
100,Scraggy,,
101,Scrafty,,
102,Abra,,
103,Kadabra,,
104,Alakazam,,
105,Oddish,,
106,Gloom,,
107,Vileplume,,
108,Bellossom,,
109,Sentret,,
110,Furret,,
111,Nincada,,
112,Ninjask,,
113,Shedinja,,
114,Espurr,,
115,Meowstic,,
116,Kecleon,,
117,Honedge,,
118,Doublade,,
119,Aegislash,,
120,Venipede,,
121,Whirlipede,,
122,Scolipede,,
123,Audino,,
124,Smeargle,,
125,Croagunk,,
126,Toxicroak,,
127,Ducklett,,
128,Swanna,,
129,Spritzee,,
130,Aromatisse,,
131,Swirlix,,
132,Slurpuff,,
133,Volbeat,,
134,Illumise,,
135,Hoppip,,
136,Skiploom,,
137,Jumpluff,,
138,Munchlax,,
139,Snorlax,,
140,Whismur,,
141,Loudred,,
142,Exploud,,
143,Meditite,,
144,Medicham,,
145,Zubat,,
146,Golbat,,
147,Crobat,,
148,Axew,,
149,Fraxure,,
150,Haxorus,,
151,Diancie,,
152,Hoopa,,
153,Volcanion,,
1 dexNumber pokemon form notes
2 1 Chespin
3 2 Quilladin
4 3 Chesnaught
5 4 Fennekin
6 5 Braixen
7 6 Delphox
8 7 Froakie
9 8 Frogadier
10 9 Greninja
11 10 Bunnelby
12 11 Diggersby
13 12 Zigzagoon
14 13 Linoone
15 14 Fletchling
16 15 Fletchinder
17 16 Talonflame
18 17 Pidgey
19 18 Pidgeotto
20 19 Pidgeot
21 20 Scatterbug
22 21 Spewpa
23 22 Vivillon
24 23 Caterpie
25 24 Metapod
26 25 Butterfree
27 26 Weedle
28 27 Kakuna
29 28 Beedrill
30 29 Pansage
31 30 Simisage
32 31 Pansear
33 32 Simisear
34 33 Panpour
35 34 Simipour
36 35 Pichu
37 36 Pikachu
38 37 Raichu
39 38 Bidoof
40 39 Bibarel
41 40 Dunsparce
42 41 Azurill
43 42 Marill
44 43 Azumarill
45 44 Burmy
46 45 Wormadam
47 46 Mothim
48 47 Surskit
49 48 Masquerain
50 49 Magikarp
51 50 Gyarados
52 51 Corphish
53 52 Crawdaunt
54 53 Goldeen
55 54 Seaking
56 55 Carvanha
57 56 Sharpedo
58 57 Litleo
59 58 Pyroar
60 59 Psyduck
61 60 Golduck
62 61 Farfetch’d
63 62 Riolu
64 63 Lucario
65 64 Ralts
66 65 Kirlia
67 66 Gardevoir
68 67 Gallade
69 68 Flabébé
70 69 Floette
71 70 Florges
72 71 Budew
73 72 Roselia
74 73 Roserade
75 74 Ledyba
76 75 Ledian
77 76 Combee
78 77 Vespiquen
79 78 Skitty
80 79 Delcatty
81 80 Bulbasaur
82 81 Ivysaur
83 82 Venusaur
84 83 Charmander
85 84 Charmeleon
86 85 Charizard
87 86 Squirtle
88 87 Wartortle
89 88 Blastoise
90 89 Skiddo
91 90 Gogoat
92 91 Pancham
93 92 Pangoro
94 93 Furfrou
95 94 Doduo
96 95 Dodrio
97 96 Plusle
98 97 Minun
99 98 Gulpin
100 99 Swalot
101 100 Scraggy
102 101 Scrafty
103 102 Abra
104 103 Kadabra
105 104 Alakazam
106 105 Oddish
107 106 Gloom
108 107 Vileplume
109 108 Bellossom
110 109 Sentret
111 110 Furret
112 111 Nincada
113 112 Ninjask
114 113 Shedinja
115 114 Espurr
116 115 Meowstic
117 116 Kecleon
118 117 Honedge
119 118 Doublade
120 119 Aegislash
121 120 Venipede
122 121 Whirlipede
123 122 Scolipede
124 123 Audino
125 124 Smeargle
126 125 Croagunk
127 126 Toxicroak
128 127 Ducklett
129 128 Swanna
130 129 Spritzee
131 130 Aromatisse
132 131 Swirlix
133 132 Slurpuff
134 133 Volbeat
135 134 Illumise
136 135 Hoppip
137 136 Skiploom
138 137 Jumpluff
139 138 Munchlax
140 139 Snorlax
141 140 Whismur
142 141 Loudred
143 142 Exploud
144 143 Meditite
145 144 Medicham
146 145 Zubat
147 146 Golbat
148 147 Crobat
149 148 Axew
150 149 Fraxure
151 150 Haxorus
152 151 Diancie
153 152 Hoopa
154 153 Volcanion
@@ -0,0 +1,154 @@
dexNumber,pokemon,form,notes
1,Drifloon,,
2,Drifblim,,
3,Mienfoo,,
4,Mienshao,,
5,Zangoose,,
6,Seviper,,
7,Spoink,,
8,Grumpig,,
9,Absol,,
10,Inkay,,
11,Malamar,,
12,Lunatone,,
13,Solrock,,
14,Bagon,,
15,Shelgon,,
16,Salamence,,
17,Wingull,,
18,Pelipper,,
19,Taillow,,
20,Swellow,,
21,Binacle,,
22,Barbaracle,,
23,Dwebble,,
24,Crustle,,
25,Tentacool,,
26,Tentacruel,,
27,Wailmer,,
28,Wailord,,
29,Luvdisc,,
30,Skrelp,,
31,Dragalge,,
32,Clauncher,,
33,Clawitzer,,
34,Staryu,,
35,Starmie,,
36,Shellder,,
37,Cloyster,,
38,Qwilfish,,
39,Horsea,,
40,Seadra,,
41,Kingdra,,
42,Relicanth,,
43,Sandile,,
44,Krokorok,,
45,Krookodile,,
46,Helioptile,,
47,Heliolisk,,
48,Hippopotas,,
49,Hippowdon,,
50,Rhyhorn,,
51,Rhydon,,
52,Rhyperior,,
53,Onix,,
54,Steelix,,
55,Woobat,,
56,Swoobat,,
57,Machop,,
58,Machoke,,
59,Machamp,,
60,Cubone,,
61,Marowak,,
62,Kangaskhan,,
63,Mawile,,
64,Tyrunt,,
65,Tyrantrum,,
66,Amaura,,
67,Aurorus,,
68,Aerodactyl,,
69,Ferroseed,,
70,Ferrothorn,,
71,Snubbull,,
72,Granbull,,
73,Electrike,,
74,Manectric,,
75,Houndour,,
76,Houndoom,,
77,Eevee,,
78,Vaporeon,,
79,Jolteon,,
80,Flareon,,
81,Espeon,,
82,Umbreon,,
83,Leafeon,,
84,Glaceon,,
85,Sylveon,,
86,Emolga,,
87,Yanma,,
88,Yanmega,,
89,Hawlucha,,
90,Sigilyph,,
91,Golett,,
92,Golurk,,
93,Nosepass,,
94,Probopass,,
95,Makuhita,,
96,Hariyama,,
97,Throh,,
98,Sawk,,
99,Starly,,
100,Staravia,,
101,Staraptor,,
102,Stunky,,
103,Skuntank,,
104,Nidoran♀,,
105,Nidorina,,
106,Nidoqueen,,
107,Nidoran♂,,
108,Nidorino,,
109,Nidoking,,
110,Dedenne,,
111,Chingling,,
112,Chimecho,,
113,Mime Jr.,,
114,Mr. Mime,,
115,Solosis,,
116,Duosion,,
117,Reuniclus,,
118,Wynaut,,
119,Wobbuffet,,
120,Roggenrola,,
121,Boldore,,
122,Gigalith,,
123,Sableye,,
124,Carbink,,
125,Tauros,,
126,Miltank,,
127,Mareep,,
128,Flaaffy,,
129,Ampharos,,
130,Pinsir,,
131,Heracross,,
132,Pachirisu,,
133,Slowpoke,,
134,Slowbro,,
135,Slowking,,
136,Exeggcute,,
137,Exeggutor,,
138,Chatot,,
139,Mantyke,,
140,Mantine,,
141,Clamperl,,
142,Huntail,,
143,Gorebyss,,
144,Remoraid,,
145,Octillery,,
146,Corsola,,
147,Chinchou,,
148,Lanturn,,
149,Alomomola,,
150,Lapras,,
151,Articuno,,
152,Zapdos,,
153,Moltres,,
1 dexNumber pokemon form notes
2 1 Drifloon
3 2 Drifblim
4 3 Mienfoo
5 4 Mienshao
6 5 Zangoose
7 6 Seviper
8 7 Spoink
9 8 Grumpig
10 9 Absol
11 10 Inkay
12 11 Malamar
13 12 Lunatone
14 13 Solrock
15 14 Bagon
16 15 Shelgon
17 16 Salamence
18 17 Wingull
19 18 Pelipper
20 19 Taillow
21 20 Swellow
22 21 Binacle
23 22 Barbaracle
24 23 Dwebble
25 24 Crustle
26 25 Tentacool
27 26 Tentacruel
28 27 Wailmer
29 28 Wailord
30 29 Luvdisc
31 30 Skrelp
32 31 Dragalge
33 32 Clauncher
34 33 Clawitzer
35 34 Staryu
36 35 Starmie
37 36 Shellder
38 37 Cloyster
39 38 Qwilfish
40 39 Horsea
41 40 Seadra
42 41 Kingdra
43 42 Relicanth
44 43 Sandile
45 44 Krokorok
46 45 Krookodile
47 46 Helioptile
48 47 Heliolisk
49 48 Hippopotas
50 49 Hippowdon
51 50 Rhyhorn
52 51 Rhydon
53 52 Rhyperior
54 53 Onix
55 54 Steelix
56 55 Woobat
57 56 Swoobat
58 57 Machop
59 58 Machoke
60 59 Machamp
61 60 Cubone
62 61 Marowak
63 62 Kangaskhan
64 63 Mawile
65 64 Tyrunt
66 65 Tyrantrum
67 66 Amaura
68 67 Aurorus
69 68 Aerodactyl
70 69 Ferroseed
71 70 Ferrothorn
72 71 Snubbull
73 72 Granbull
74 73 Electrike
75 74 Manectric
76 75 Houndour
77 76 Houndoom
78 77 Eevee
79 78 Vaporeon
80 79 Jolteon
81 80 Flareon
82 81 Espeon
83 82 Umbreon
84 83 Leafeon
85 84 Glaceon
86 85 Sylveon
87 86 Emolga
88 87 Yanma
89 88 Yanmega
90 89 Hawlucha
91 90 Sigilyph
92 91 Golett
93 92 Golurk
94 93 Nosepass
95 94 Probopass
96 95 Makuhita
97 96 Hariyama
98 97 Throh
99 98 Sawk
100 99 Starly
101 100 Staravia
102 101 Staraptor
103 102 Stunky
104 103 Skuntank
105 104 Nidoran♀
106 105 Nidorina
107 106 Nidoqueen
108 107 Nidoran♂
109 108 Nidorino
110 109 Nidoking
111 110 Dedenne
112 111 Chingling
113 112 Chimecho
114 113 Mime Jr.
115 114 Mr. Mime
116 115 Solosis
117 116 Duosion
118 117 Reuniclus
119 118 Wynaut
120 119 Wobbuffet
121 120 Roggenrola
122 121 Boldore
123 122 Gigalith
124 123 Sableye
125 124 Carbink
126 125 Tauros
127 126 Miltank
128 127 Mareep
129 128 Flaaffy
130 129 Ampharos
131 130 Pinsir
132 131 Heracross
133 132 Pachirisu
134 133 Slowpoke
135 134 Slowbro
136 135 Slowking
137 136 Exeggcute
138 137 Exeggutor
139 138 Chatot
140 139 Mantyke
141 140 Mantine
142 141 Clamperl
143 142 Huntail
144 143 Gorebyss
145 144 Remoraid
146 145 Octillery
147 146 Corsola
148 147 Chinchou
149 148 Lanturn
150 149 Alomomola
151 150 Lapras
152 151 Articuno
153 152 Zapdos
154 153 Moltres
@@ -0,0 +1,152 @@
dexNumber,pokemon,form,notes
1,Diglett,,
2,Dugtrio,,
3,Trapinch,,
4,Vibrava,,
5,Flygon,,
6,Gible,,
7,Gabite,,
8,Garchomp,,
9,Geodude,,
10,Graveler,,
11,Golem,,
12,Slugma,,
13,Magcargo,,
14,Shuckle,,
15,Skorupi,,
16,Drapion,,
17,Wooper,,
18,Quagsire,,
19,Goomy,,
20,Sliggoo,,
21,Goodra,,
22,Karrablast,,
23,Escavalier,,
24,Shelmet,,
25,Accelgor,,
26,Bellsprout,,
27,Weepinbell,,
28,Victreebel,,
29,Carnivine,,
30,Gastly,,
31,Haunter,,
32,Gengar,,
33,Poliwag,,
34,Poliwhirl,,
35,Poliwrath,,
36,Politoed,,
37,Ekans,,
38,Arbok,,
39,Stunfisk,,
40,Barboach,,
41,Whiscash,,
42,Purrloin,,
43,Liepard,,
44,Poochyena,,
45,Mightyena,,
46,Patrat,,
47,Watchog,,
48,Pawniard,,
49,Bisharp,,
50,Klefki,,
51,Murkrow,,
52,Honchkrow,,
53,Foongus,,
54,Amoonguss,,
55,Lotad,,
56,Lombre,,
57,Ludicolo,,
58,Buizel,,
59,Floatzel,,
60,Basculin,,
61,Phantump,,
62,Trevenant,,
63,Pumpkaboo,,
64,Gourgeist,,
65,Litwick,,
66,Lampent,,
67,Chandelure,,
68,Rotom,,
69,Magnemite,,
70,Magneton,,
71,Magnezone,,
72,Voltorb,,
73,Electrode,,
74,Trubbish,,
75,Garbodor,,
76,Swinub,,
77,Piloswine,,
78,Mamoswine,,
79,Bergmite,,
80,Avalugg,,
81,Cubchoo,,
82,Beartic,,
83,Smoochum,,
84,Jynx,,
85,Vanillite,,
86,Vanillish,,
87,Vanilluxe,,
88,Snover,,
89,Abomasnow,,
90,Delibird,,
91,Sneasel,,
92,Weavile,,
93,Timburr,,
94,Gurdurr,,
95,Conkeldurr,,
96,Torkoal,,
97,Sandshrew,,
98,Sandslash,,
99,Aron,,
100,Lairon,,
101,Aggron,,
102,Larvitar,,
103,Pupitar,,
104,Tyranitar,,
105,Heatmor,,
106,Durant,,
107,Spinarak,,
108,Ariados,,
109,Spearow,,
110,Fearow,,
111,Cryogonal,,
112,Skarmory,,
113,Noibat,,
114,Noivern,,
115,Gligar,,
116,Gliscor,,
117,Hoothoot,,
118,Noctowl,,
119,Igglybuff,,
120,Jigglypuff,,
121,Wigglytuff,,
122,Shuppet,,
123,Banette,,
124,Zorua,,
125,Zoroark,,
126,Gothita,,
127,Gothorita,,
128,Gothitelle,,
129,Bonsly,,
130,Sudowoodo,,
131,Spinda,,
132,Teddiursa,,
133,Ursaring,,
134,Lickitung,,
135,Lickilicky,,
136,Scyther,,
137,Scizor,,
138,Ditto,,
139,Swablu,,
140,Altaria,,
141,Druddigon,,
142,Deino,,
143,Zweilous,,
144,Hydreigon,,
145,Dratini,,
146,Dragonair,,
147,Dragonite,,
148,Xerneas,,
149,Yveltal,,
150,Zygarde,,
151,Mewtwo,,
1 dexNumber pokemon form notes
2 1 Diglett
3 2 Dugtrio
4 3 Trapinch
5 4 Vibrava
6 5 Flygon
7 6 Gible
8 7 Gabite
9 8 Garchomp
10 9 Geodude
11 10 Graveler
12 11 Golem
13 12 Slugma
14 13 Magcargo
15 14 Shuckle
16 15 Skorupi
17 16 Drapion
18 17 Wooper
19 18 Quagsire
20 19 Goomy
21 20 Sliggoo
22 21 Goodra
23 22 Karrablast
24 23 Escavalier
25 24 Shelmet
26 25 Accelgor
27 26 Bellsprout
28 27 Weepinbell
29 28 Victreebel
30 29 Carnivine
31 30 Gastly
32 31 Haunter
33 32 Gengar
34 33 Poliwag
35 34 Poliwhirl
36 35 Poliwrath
37 36 Politoed
38 37 Ekans
39 38 Arbok
40 39 Stunfisk
41 40 Barboach
42 41 Whiscash
43 42 Purrloin
44 43 Liepard
45 44 Poochyena
46 45 Mightyena
47 46 Patrat
48 47 Watchog
49 48 Pawniard
50 49 Bisharp
51 50 Klefki
52 51 Murkrow
53 52 Honchkrow
54 53 Foongus
55 54 Amoonguss
56 55 Lotad
57 56 Lombre
58 57 Ludicolo
59 58 Buizel
60 59 Floatzel
61 60 Basculin
62 61 Phantump
63 62 Trevenant
64 63 Pumpkaboo
65 64 Gourgeist
66 65 Litwick
67 66 Lampent
68 67 Chandelure
69 68 Rotom
70 69 Magnemite
71 70 Magneton
72 71 Magnezone
73 72 Voltorb
74 73 Electrode
75 74 Trubbish
76 75 Garbodor
77 76 Swinub
78 77 Piloswine
79 78 Mamoswine
80 79 Bergmite
81 80 Avalugg
82 81 Cubchoo
83 82 Beartic
84 83 Smoochum
85 84 Jynx
86 85 Vanillite
87 86 Vanillish
88 87 Vanilluxe
89 88 Snover
90 89 Abomasnow
91 90 Delibird
92 91 Sneasel
93 92 Weavile
94 93 Timburr
95 94 Gurdurr
96 95 Conkeldurr
97 96 Torkoal
98 97 Sandshrew
99 98 Sandslash
100 99 Aron
101 100 Lairon
102 101 Aggron
103 102 Larvitar
104 103 Pupitar
105 104 Tyranitar
106 105 Heatmor
107 106 Durant
108 107 Spinarak
109 108 Ariados
110 109 Spearow
111 110 Fearow
112 111 Cryogonal
113 112 Skarmory
114 113 Noibat
115 114 Noivern
116 115 Gligar
117 116 Gliscor
118 117 Hoothoot
119 118 Noctowl
120 119 Igglybuff
121 120 Jigglypuff
122 121 Wigglytuff
123 122 Shuppet
124 123 Banette
125 124 Zorua
126 125 Zoroark
127 126 Gothita
128 127 Gothorita
129 128 Gothitelle
130 129 Bonsly
131 130 Sudowoodo
132 131 Spinda
133 132 Teddiursa
134 133 Ursaring
135 134 Lickitung
136 135 Lickilicky
137 136 Scyther
138 137 Scizor
139 138 Ditto
140 139 Swablu
141 140 Altaria
142 141 Druddigon
143 142 Deino
144 143 Zweilous
145 144 Hydreigon
146 145 Dratini
147 146 Dragonair
148 147 Dragonite
149 148 Xerneas
150 149 Yveltal
151 150 Zygarde
152 151 Mewtwo
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
region,releaseOrder
Kanto,1
Johto,2
Hoenn,3
Orre,4
Sinnoh,5
Ranch,6
Unova,7
Kalos,8
Alola,9
Go,10
Galar,11
Home,12
Hisui,13
Paldea,14
1 region releaseOrder
2 Kanto 1
3 Johto 2
4 Hoenn 3
5 Orre 4
6 Sinnoh 5
7 Ranch 6
8 Unova 7
9 Kalos 8
10 Alola 9
11 Go 10
12 Galar 11
13 Home 12
14 Hisui 13
15 Paldea 14
@@ -0,0 +1,57 @@
# Hosting evaluation: retain Netlify pending deployed evidence
Date: 15 September 2026. This is an interim decision report. **Do not cut over to Cloudflare yet.** The application improvements and selectable preview build are implemented, but the agreed real-host comparison cannot be completed with the current access and compatibility state.
## Evidence and decision
| Item | Observed result | Consequence |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| Production Netlify site | `livingdextracker`, `www.dextracker.uk`; published revision inspected: `31fd959350962c1f1b973a06ecd5cf4eeef86514` | This is the existing deployment, not this working tree |
| Function/database regions | Netlify `us-east-1`; linked Supabase `eu-north-1`; production public database URL matches that project | Cross-region round trips are a plausible contributor; their latency share is unmeasured |
| Node production checks | Compact SSR, details, status writes, offline behavior and rendering budgets exercised locally | Application evidence only |
| Cloudflare build | Adapter 7.2.9, Wrangler 4.131.2, compatibility date 2026-09-15, `nodejs_compat`; build and dry-run passed | Packaging is viable |
| Final Worker artifact | Approximately 1,876 KiB uncompressed / 336 KiB gzip; 9,621 static assets | Within published size/count limits; re-audit after renderer changes |
| Actual local workerd | Home, authenticated dex and public share page returned 200 | Basic runtime support demonstrated |
| Share image in workerd | `/shared/:token/preview.png` returned 500; `sharp` native module dynamic require is unsupported | **Compatibility gate failed**; see separate renderer proposal below |
| Remote preview access | Netlify CLI authenticated; Wrangler not authenticated; equivalent staging fixtures/accounts not supplied | No paired deployed samples collected |
No production deployment, DNS change, database migration or region change was performed. Retaining Netlify now is a decision under incomplete evidence and a failed compatibility gate, not evidence that Netlify is faster.
Netlify supports streaming; the investigation's buffering describes the installed adapter/runtime combination, not the entire platform. Cloudflare's supported SvelteKit adapter and partial Node compatibility do not imply support for native `sharp`. Sources: [Netlify streaming](https://docs.netlify.com/build/functions/lambda-compatibility/), [SvelteKit Cloudflare adapter](https://svelte.dev/docs/kit/adapter-cloudflare), [Cloudflare Node compatibility](https://developers.cloudflare.com/workers/runtime-apis/nodejs/).
## Build and environment requirements
- Default builds remain Netlify. `NODE_ADAPTER=true` or `DEPLOY_TARGET=node` selects Node. `npm run build:cloudflare` selects Workers with Static Assets; `npm run check:cloudflare` checks packaging; `npm run preview:cloudflare` runs workerd locally. Do not run builds concurrently.
- Cloudflare uses platform compression rather than the Node compression implementation. Verify actual deployed content encoding for HTML, SvelteKit data and JSON responses.
- Supply public Supabase URL/anon key at build time, and private Supabase/export/OAuth secrets through platform bindings. Preview secrets must belong to the same staging project on both hosts. Keep provider redirect allowlists and cookie/domain settings explicit.
- Authenticate Wrangler and select the intended account before creating a remote preview. Build/dry-run success does not authorize production routing.
- Current documented limits include 128 MB memory, one-second startup, 64 MiB uncompressed Worker size and 20,000/100,000 static files on Free/Paid. Each static file must be at most 25 MiB. Free CPU allowance is only 10 ms per invocation; do not assume the app or renderer fits it. Measure CPU/memory/startup under actual workerd and deployment. [Workers limits](https://developers.cloudflare.com/workers/platform/limits/)
## Separate proposal: Worker-compatible share-image renderer
This is the concrete implementation proposal required by the migration gate. It is **not implemented** in this change.
1. Extract the existing SVG construction, XML escaping and text truncation into a platform-neutral module. Preserve the endpoint, 1,200 × 630 dimensions, progress values, privacy behavior and cache headers.
2. Keep a Node renderer using `sharp`. Add a Cloudflare renderer using `@resvg/resvg-wasm`, selected through the same build-time platform alias pattern as compression. Pin a verified version in the renderer change; exclude native `sharp` from the Worker dependency graph.
3. Bundle the renderer's WASM as a module and initialize lazily once per isolate through a shared promise. Import a compiled WebAssembly module using the supported Workers approach, rather than assuming a browser-style URL fetch loader works. Release per-render allocations after producing a PNG byte array. [Workers WASM support](https://developers.cloudflare.com/workers/runtime-apis/webassembly/javascript/), [resvg WASM package](https://github.com/thx/resvg-js/tree/main/wasm)
4. Bundle licensed regular/bold fonts, for example Noto Sans with its license. Explicitly map SVG weights to those fonts; do not rely on operating-system fonts. Verify accented Pokémon names, punctuation, long descriptions and the intended non-Latin fallback policy. Font appearance will need review against existing PNGs.
5. Add golden-image/metadata tests for empty/long names, XML special characters, all badges and 0/100% progress. Exercise concurrent requests, first invocation, repeated renders and error recovery in built workerd. Require HTTP 200, PNG signature/dimensions, correct sharing access and no private notes.
6. Re-audit bundle/assets, CPU, memory and startup after adding WASM/fonts. Run the deployed share-image test and backup/export/auth matrix before setting compatibility to passed. If this renderer exceeds operating constraints, compare a separately hosted image service in a new proposal; do not silently redirect rendering to production Netlify.
## Remaining deployed benchmark
1. Supply equivalent staging credentials and disposable national/scoped-form fixtures, then publish this exact code to both preview hosts. Preserve actual deployed revision and environment metadata.
2. Establish improved Netlify document/data baselines. Consider a separate region-aligned Netlify preview as an additional experiment; do not change the primary paired comparison mid-run.
3. Exercise sign-in, token refresh, account switching, Google/Dropbox OAuth and refresh, export generation, public shares/images, compression, secrets/bindings, static cache headers, service-worker install/update/offline routing and custom preview domains on both real hosts.
4. Use the [comparison harness](pokedex-implementation.md#instrumentation-and-comparison-harness) for at least 30 warm samples per host × fixture × direct/client navigation. Keep code, Supabase project, fixtures, browser settings and client locations identical. Run additional deliberately idled samples and record the idle duration separately; first-observed is not a cold-start claim.
5. Recommend migration only when overall first-interactive p75 improves by **both 20% and 200 ms**, no fixture/navigation combination regresses by more than 10%, and functional checks pass. Include costs and operating requirements before making the final decision.
## Cost projection and operations
Actual monthly traffic, CPU usage and the account's current Netlify billing arrangement are not available, so no savings claim is justified.
Cloudflare Paid has a $5/month minimum, includes 10 million dynamic requests and 30 million CPU-ms, then charges $0.30/million requests and $0.02/million CPU-ms. Direct static asset requests are free; requests served through Workers Caching have different billing. Illustrative direct-static configuration: 1 million dynamic requests at 20 ms CPU each remains within $5; 10 million at 20 ms is approximately $8.40. These exclude other services and are assumptions, not measured app CPU. [Workers pricing](https://developers.cloudflare.com/workers/platform/pricing/)
For credit-based Netlify plans, estimate credits as `15 × production deploys + 10 × compute GB-hours + 20 × bandwidth GB + 2 × requests/10,000`. Confirm whether this account uses credit-based or legacy billing and apply its actual plan/allowance. Thumbnail byte savings affect bandwidth, while increased first-party sprite requests affect request metering. [Netlify pricing](https://www.netlify.com/pricing/)
Before a qualifying cutover: move database migrations out of host builds into one serialized CI release step; provision secrets and OAuth redirects; validate the custom domain and cookies; monitor error/latency/export metrics; retain the working Netlify deployment and a documented DNS rollback. These production changes remain conditional on completing the gates above.
+115
View File
@@ -0,0 +1,115 @@
# Pokédex performance implementation
Status: application changes implemented; hosting comparison remains gated. Measurements below are local production-build evidence, not deployed latency improvements. See [hosting evaluation](pokedex-hosting-evaluation.md) for the migration decision and remaining work.
## Application changes
- Ownership and saved scope links are read together. Scoped entry retrieval is shared by rows/count consumers; the full grid performs no count query. Catch joins use ID maps. Scope deduplication, named default forms, supplements and ordering remain covered by repository tests.
- The page awaits the entire compact grid and renders initial boxes on the server. Authentication state reaches SSR through the validated layout user. Successful navigation needs no grid API request; failed grid loads expose retry.
- `PokedexGridRow` contains identity, sprite resolution fields and catch flags. The page and authenticated `/api/pokedexes/[id]/grid` endpoint transport named tuples defined in `PokedexGridRow.ts`; `packGrid`/`unpackGrid` keep that wire format out of components. Instructions, notes, origin games and repeated owner/dex IDs are absent. Existing full combined-data consumers retain their contracts.
- The detail endpoint verifies ownership and membership before returning one full `CombinedData` row. The modal opens immediately with identity and full artwork, then loads editable details. Its account/dex/entry cache, abort/sequence checks and pending-patch merge protect rapid selection changes and optimistic edits.
- Status writes send changed fields. Bulk writes group records by supplied columns, preserving omitted notes and flags; explicit empty notes clear them. New records use database defaults. Full-record callers and exports remain supported. Bulk box actions still target all original 30 slots, including dimmed entries.
- Grid placeholders preserve geometry; visible boxes and one row of overscan mount populated cells. Focused boxes remain mounted, keyboard navigation crosses boundaries, modal close restores focus, and an accessible render-all option exposes the complete document. Each Pokémon uses one button with identity/status and a noninteractive tooltip.
- Density is persisted in a cookie for stable SSR geometry and in local storage. Resize/density changes preserve the current box anchor. Existing local-storage-only preferences are replaced by the cookie after choosing a density.
- Automatic snapshot/backup work starts at the interactive/idle boundary with a five-second fallback. Concurrent backup refreshes coalesce. Explicit sync and edit/account/reconnect invalidations retain freshness behavior. Backup-status GET no longer revalidates via `setSession`.
- Complete offline snapshot format 2 is retained. Offline modal details come only from the matching account snapshot; missing copies report unavailable details. Offline details are read-only, as before for offline mutations.
## Artwork and build behavior
`npm run sprites:grid` generates 3,170 first-party WebP thumbnails, at most 128 pixels per side, quality 80. Builds run this automatically. Generated assets live in ignored `static/sprites-grid/v1/`; the generator emits a manifest. Originals remain 512 pixels for details and explicit full-artwork downloads.
The generated catalog is 10,007,504 bytes versus 53,659,230 bytes for the source WebP catalog (81.4% smaller). Shiny, female and named-form resolution uses the existing key/fallback chain. The service worker recognizes versioned grid sprites in the existing artwork cache; neither thumbnail nor original catalogs are blanket precached. Root `_headers` supplies immutable caching on Netlify/Cloudflare. Bump the URL version whenever generation settings or source images change; generation skips existing files within a version.
## Local acceptance evidence
Fixtures: national (1,025 entries), Scarlet/Paldea forms (439 entries), mixed catch flags and nonempty notes. Integration tests additionally cover missing catches and overlapping scopes through repository tests. Browser viewport: 1,350 × 940, comfortable density, Chromium, local Node production build and local seeded Supabase.
The packed grid is approximately 81 KB national and 36 KB scoped, versus the investigation's approximately 593 KB and 255 KB full-data JSON. The same-fixture integration assertion separately verifies at least 60% reduction against full combined rows. These are serialized row sizes, not compressed HTML document sizes.
The local browser checks verify at most 180 populated mounted cells, fewer than 2,500 DOM elements and CLS at most 0.1; observed initial population is 120 cells. Density/mobile checks include all three densities at 1,350 and 390 pixels. Detail artwork is asserted to load at 512 pixels. No redundant grid request is allowed; intentional detail requests are allowed.
Warm results from the corrected harness (30 samples per row; [sanitized summary](pokedex-local-results.json)):
| Fixture | Navigation | First visible p75 | First interactive p75 | Decoded response bytes p75 | Maximum DOM |
| ------------ | ---------- | ----------------: | --------------------: | -------------------------: | ----------: |
| National | Direct | 123.5 ms | 145.4 ms | 248,668 | 2,088 |
| National | Client | 495.6 ms | 494.1 ms | 102,687 | 2,090 |
| Scoped forms | Direct | 114.5 ms | 133.1 ms | 203,601 | 2,073 |
| Scoped forms | Client | 491.7 ms | 490.6 ms | 45,645 | 2,075 |
Every warm sample had 120 populated cells, zero observed CLS, zero redundant grid requests and a measured response size. Direct response bytes include SSR markup and SvelteKit data; client bytes are SvelteKit data responses, not just the packed rows. Interactive marks can precede the next animation-frame visibility observation by a few milliseconds. Client timings include Playwright click overhead, as explained below. This benchmark preceded the final account-switch backup invalidation guard; the final production smoke suite also passed after that guard.
### Validation completed
| Check | Result |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Svelte/TypeScript | 0 errors; one existing `Tooltip.svelte` CSS `@apply` warning |
| Unit tests | 193 passed |
| Data tests | 18 passed |
| Coverage | Existing thresholds passed: 66.81% lines/statements, 88.79% branches, 90.99% functions |
| Local Supabase integration | 16 passed, including same-fixture payload reduction and note preservation |
| Authenticated browser regressions | 53 passed, including mock Google/Dropbox OAuth, exports and service-worker/offline flows |
| Build matrix | Four checks in each of Netlify/Node × generateSW/injectManifest passed |
| Production performance/behavior | Both fixtures, all densities/mobile, resize anchor, focus/keyboard, modal race, full artwork and offline snapshot isolation passed |
| Cloudflare | Final build and Wrangler dry-run passed; local workerd share-image generation failed as documented in the hosting report |
| Formatting/lint | All changed/new implementation files pass Prettier; ESLint and `git diff --check` pass |
Repository-wide `npm run lint` also scans the pre-existing untracked `dex.har` and `POKEDEX_PERFORMANCE_PROMPT.md`; those two files have formatting warnings and were intentionally left untouched. No coverage threshold was lowered. Disposable performance accounts and local test servers were cleaned up.
### Reproduce
```sh
npm ci
npx supabase start
npx playwright install chromium
npm run check
npm run test:unit
npm run test:integration
npm run test:build
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER=true npm run test:bdd
npm run test:performance
PERF_BENCHMARK=true npm run test:performance
```
Run builds sequentially: they share `.svelte-kit` and `build`. Performance tests create a disposable local-only account, use private temporary session files, clean up afterward, and copy sanitized reports/screenshots to ignored `test-results/performance/`. Cleanup failures retain recovery files. Never commit session/configuration files.
## Instrumentation and comparison harness
Set `POKEDEX_PERFORMANCE=true` on a preview to emit fixed-label `Server-Timing` stages: auth, ownership, scopes, entries, catches, preparation and total. Timings do not include IDs, cookies, notes or query text. Authentication includes the request hook's validation. Total measures the page/service span, not total platform request lifetime; stages may therefore not sum to total.
The browser harness measures first visible cells via animation frames and first interactive cells via `pokedex:first-interactive`, independently of response completion. It collects DOM/cells, layout shifts, intentional/redundant API counts and response sizes. For Chromium service-worker responses where Playwright cannot read the body, decoded Resource Timing bytes are used; absent measurements stay null. Decoded, encoded and transferred bytes are distinguished.
`benchmark.mjs` requires at least 30 warm samples per fixture/navigation combination. It records the first observed run separately; that is **not** evidence of a cold start or first-after-idle run. For real-host work, collect deliberately idled runs separately and record the idle interval. Client timing starts before Playwright's click, so includes its actionability overhead; preserve identical tooling/settings between hosts and report this limitation.
Private configuration example (replace all placeholders):
```json
{
"samples": 30,
"revision": "exact-deployed-commit",
"databaseLabel": "same-staging-project",
"clientLocation": "London-fixed-runner",
"environment": "deployed",
"compatibilityPassed": false,
"hosts": [
{
"label": "netlify",
"url": "https://NETLIFY-PREVIEW",
"storageState": "/PRIVATE/netlify-session.json",
"fixtures": [
{ "id": "NATIONAL-ID", "name": "Performance National", "label": "national" },
{ "id": "SCOPED-ID", "name": "Performance Scarlet Forms", "label": "scoped-forms" }
]
}
]
}
```
Add an equivalent `cloudflare` host using the same database and fixtures. Run:
```sh
node scripts/performance/benchmark.mjs /PRIVATE/config.json /PRIVATE/results.json
node scripts/performance/compare.mjs /PRIVATE/results.json
```
The comparison refuses insufficient samples and retains Netlify unless deployed evidence, compatibility and the agreed improvement thresholds all pass. Human review must still establish costs, environment equivalence and deployment prerequisites.
+227
View File
@@ -0,0 +1,227 @@
# Signed-in Pokédex performance investigation
Investigated 1415 September 2026 at commit `31fd959350962c1f1b973a06ecd5cf4eeef86514`.
## Findings
The production capture establishes a server-response bottleneck: **3,506 ms waiting versus 261 ms receiving** the Pokédex data response. The current loading design exposes all entry work to that wait on the installed Netlify adapter. It requests practically the entire dex, and the adapter buffers the response before returning it. Independently, mounting the entire grid causes avoidable browser work.
Local measurements confirm the request sequence, duplicate game-scoped queries, large payload and rendering cost. **They do not explain the exact allocation of production's 3.5 seconds.** Regions, function startup and production query timings remain unverified. At the user's direction, no further production/dashboard access was attempted; subsequent measurements used local Supabase.
No performance fixes, migrations, deployment settings, public APIs or types were changed. Temporary instrumentation and the diagnostic rendering cap were removed. Full-resolution artwork must remain available when a user opens a Pokémon's detail view.
The numerical evidence, including individual runs and sanitized server traces, is in [pokedex-results.json](pokedex-results.json).
## Production evidence and its limits
| Evidence | Result | Interpretation |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| Supplied `dex.har`, data navigation | Wait 3,506.100 ms; receive 260.671 ms; 401,199 uncompressed bytes | Waiting dominates transfer. This includes server and network effects; it is not a database timer. |
| Response headers | Brotli; `private,no-store`; Netlify request ID present | Compression already exists. User-specific content is not served as a public CDN cache hit. |
| HAR content | Response text absent | Cannot measure production field sizes or infer the dex's form/scope configuration from this file. |
| HAR sprites | 36 requests, 531,086 bytes total, `max-age=300` | Visible artwork has a substantial transfer cost independent of entry data. |
| Supplied Lighthouse summary | Root response 3,373 ms; about 386 KB serialized inline data; 10,442 DOM elements; 1.9 s rendering; CLS 0.127 | Corroborates both server wait and browser cost. These are user-supplied findings, not a new run. |
The HAR contains only one application request plus the 36 sprite requests. It does **not** contain the offline-snapshot or backup-status requests; their production sizes/durations come from the supplied Lighthouse summary. Extension findings were excluded.
### Why streaming currently fails to hide the work
[The server load](../../src/routes/pokedex/[id]/+page.server.ts) returns an unresolved `initialCombinedData` promise, but `INITIAL_PAGE_SIZE` is **9,999**, matching the client. Its `.then()` discards the count/pagination metadata after the shared service has calculated it.
[adapter.mjs](../../adapter.mjs) selects standard Netlify functions (`edge: false`), except for Node test builds. Installed `@sveltejs/adapter-netlify` **4.4.2**, in `node_modules/@sveltejs/adapter-netlify/files/esm/serverless.js`, awaits `response.text()` for text responses and `response.arrayBuffer()` for binary responses. Both buffer the body before the handler returns. This proves the behavior of the installed adapter; the exact deployed package/build was not accessible. The HAR's long wait is consistent with it.
[Compression](../../src/lib/server/compression.ts) already skips application compression in Lambda because Netlify handles it. Enabling more compression would not fix this buffering boundary. The page also assigns its entries client-side, so even genuine transport streaming does not mean the grid is server-rendered and interactive immediately.
An isolated local identity-encoding stream probe received first bytes before completion:
| Dex | First-byte median | Complete-body median |
| ------------- | ----------------: | -------------------: |
| National | 48.3 ms | 104.7 ms |
| Scarlet forms | 36.8 ms | 72.5 ms |
These are Vite measurements, not evidence that Netlify streams.
## Server request map and timings
Sources: [session hook](../../src/hooks.server.ts), [ownership repository](../../src/lib/repositories/PokedexRepository.ts), [scope service](../../src/lib/services/PokedexDexScopeService.ts), [combined-data service](../../src/lib/services/CombinedDataService.ts), [combined-data repository](../../src/lib/repositories/CombinedDataRepository.ts).
For an unexpired authenticated session, both measured dexes make **eight Supabase HTTP requests per page/data request**:
| Stage | National: 1,025 entries | Scarlet Paldea forms: 439 entries |
| ---------------------------------------- | ------------------------------------------ | ------------------------------------------ |
| Authentication | 1 `getUser` | 1 `getUser` |
| Ownership, then scope links | 1 `pokedexes`, then 1 `pokedex_dex_scopes` | Same |
| Entry branch | 2 sequential entry pages: 1,000 + 25 | 1 game-dex query, then 1 forms query |
| Count branch, parallel with entry branch | 1 HEAD exact-count query | Repeats the game-dex query and forms query |
| Catches, after entry retrieval | 2 sequential chunks: 1,000 + 25 | 1 chunk: 439 |
| Total / longest chain of requests | **8 / 7** | **8 / 6** |
The game query returns 400 rows. The named-form query returns 45 rows; six are already represented, leaving 39 supplements and 439 unique entries. The count branch repeats both reads, transferring another **277,047 bytes** from Supabase just to count those entries. The two branches run concurrently: eliminating duplication reduces work and traffic, but does not necessarily remove their summed durations from the critical path.
General case:
- National path: `3 + entry-page requests + 1 count + catch chunks`. Pagination continues until a short/empty batch or the requested limit. An exact multiple of 1,000 may require an empty terminal request. Catch chunks use at most 1,000 IDs.
- Explicit game scopes: `3 + 2 × (dex-page requests + applicable form-page requests) + catch chunks`. Counting fetches the full scope even when the requested page is small. Deduplication and slicing happen in JavaScript.
- A game scope without saved dex scopes adds two sequential reads (`games`, then `game_dexes`). National dexes still pay the scope-link query even though scope resolution itself returns immediately.
- Token refresh can add an authentication request. A separate probe using an expired saved cookie produced nine requests; the reported baseline was rerun with a fresh session. Replaying that stale cookie every time was a probe artifact, not normal browser session behavior.
- `safeGetSession` is shared within a request, not across navigation and background requests.
### Isolated local server timings
Five warm requests per dex, one first run excluded. Queries were instrumented at the Supabase fetch boundary, including response-body completion; repository methods were timed separately. The cloned response used for instrumentation adds overhead. All values below are medians, so columns are not additive.
| Measure | National | Scarlet forms |
| --------------------------------------------------- | -------: | ------------: |
| Auth `getUser` HTTP duration | 35.5 ms | 25.3 ms |
| Ownership + scope-link HTTP durations | 8.0 ms | 7.2 ms |
| `findCombinedData`, including entries and catches | 50.7 ms | 33.3 ms |
| `countCombinedData`, concurrent with find | 6.6 ms | 25.6 ms |
| Catch retrieval, included within find | 16.4 ms | 6.5 ms |
| Sum of all query durations | 92.9 ms | 86.0 ms |
| Elapsed request time to final query-body completion | 87.6 ms | 64.1 ms |
| Complete HTTP response | 104.7 ms | 72.5 ms |
| Supabase response-body bytes, summed | 917,728 | 709,996 |
The difference between summed query durations and elapsed completion reflects concurrency. Repository work, serialization, streaming and measurement overhead sit outside or between query timings. Do not subtract these local medians from production TTFB to invent a region/startup estimate.
### Query plans and indexes
`EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)` ran under the local `authenticated` role with the fixture user's JWT subject. These are SQL execution times, excluding HTTP, PostgREST JSON serialization and function/network latency.
| Query shape | Median of five warm executions |
| ------------------------------------------------- | -----------------------------: |
| National ordered entries, first 1,000 | 5.557 ms |
| National ordered entries, offset 1,000 | 5.866 ms |
| National exact count through the view | 2.484 ms |
| Scarlet game-dex detail rows | 10.706 ms |
| Named forms available in Scarlet | 2.934 ms |
| Catch query with the actual first 1,000 entry IDs | 0.476 ms |
The entry view joins and aggregates origin-game data before returning rows. The game-dex plan aggregates 1,390 Pokémon before joining the 400 scoped entries. The offset query repeats aggregation/sorting for the last 25 rows. These are real work amplification, but small absolute local costs.
The game membership index and existing catch-record dex index are used. The exact catch query is already sub-millisecond locally. **No new index is justified by these measurements.** Prefer avoiding duplicate/full-view work before speculative indexing. The evidence JSON also retains an earlier catch-plan probe with an ID subquery; the literal-ID result above is the closer match to the application.
## Payload and browser measurements
### Method and fixtures
- Existing local Supabase seed: 1,390 catalog entries, 1,025 default forms. No reset or migration was run.
- Dedicated disposable account: national living dex with 1,025 catch records; Scarlet/Paldea form dex with 1,390 seeded catch records, of which 439 match this view. Mixed deterministic statuses and empty personal notes. Existing user data was preserved.
- Headless Playwright Chromium, 1,350 × 940 viewport, device scale 1, no extensions, no CPU/network throttling. Vite 5.4.21 development server, Node 24.18.0, same-origin sprites.
- One first run plus five warm runs for each navigation/dex combination. Client navigation clicks the real card's View button from My Pokédexes. Each client sample starts from a loaded list page with a 1.1-second settling period.
- “Visible cells” uses Playwright's first-cell visibility check and includes automation overhead. Response completion is network response completion, not full page idle. Layout/style time is CDP `LayoutDuration + RecalcStyleDuration` over the sample and 1.5-second follow-up; it is not Lighthouse's entire rendering category.
| Dex / navigation | First-run visible | Five warm visible times | Median TTFB | Median response complete | Median visible | DOM |
| ---------------------- | ----------------: | -------------------------- | ----------: | -----------------------: | -------------: | -----: |
| National / direct | 798 ms | 549, 986, 519, 474, 432 ms | 84 ms | 268 ms | **519 ms** | 10,236 |
| National / client | 407 ms | 322, 335, 369, 423, 381 ms | 63 ms | 133 ms | **369 ms** | 10,236 |
| Scarlet forms / direct | 462 ms | 309, 278, 299, 312, 317 ms | 68 ms | 148 ms | **309 ms** | 4,476 |
| Scarlet forms / client | 224 ms | 272, 227, 233, 363, 274 ms | 59 ms | 111 ms | **272 ms** | 4,476 |
These development results must not be equated with optimized production performance. Local full-dataset fixture content, development scripts/styles and serialized session metadata differ from the production capture. The initial Vite dependency-optimization failure was resolved before collecting this matrix. One first-run streamed response could not be read through Chromium's body-capture API; its bytes are recorded as null, not zero.
### What is needed at first paint
At this viewport the national dex mounts 35 boxes and 1,025 populated cells, with only **60 cells visible**. Scarlet mounts 15 boxes and 439 cells, also with 60 visible. The national grid is 10,532 px tall. IntersectionObserver already defers distant sprite downloads; it does not prevent mounting those cells, tooltip components and loading spinners. There were 73 image elements, not 1,025 downloaded sprites.
The box and tooltip need identity/name/form/number/sprite key and catch-status flags. Evolution/catch instructions, origin games, dex notes and personal notes belong to the detail workflow. Repeated catch `userId`/`pokedexId` values are also expensive in ordinary JSON. The page still needs global totals and stable placement, so simply lowering the limit would break existing behavior.
| JSON measurement | National | Scarlet forms |
| ------------------------------------------------- | --------: | ------------: |
| Full combined rows | 592,997 B | 255,319 B |
| Display-only rows for every entry | 170,636 B | 74,154 B |
| Display-only first 60 entries | 9,751 B | 10,757 B |
| Detail-only Pokémon fields, separately serialized | 214,064 B | 91,887 B |
“Display-only” is a sizing experiment, **not a proposed drop-in API**: it excludes identifiers/fields that writes and details currently need. JSON partitions are serialized separately and are not additive. Actual SvelteKit data responses use a different serialization format: warm client response medians were 518,649 B and 222,892 B. Direct development documents were about 686 KB and 375 KB; their largest inline scripts were 545,897 B and 235,175 B.
### Controlled rendering comparison
A temporary diagnostic changed only the rendered box loop to its first two boxes, leaving the fetched full dataset intact. Both comparisons blocked the two background endpoints, used the existing offline worker, and measured five warm direct loads plus 2.5 seconds after visibility. The full loop was restored afterward.
| Measure | All 35 boxes | First 2 boxes only |
| ----------------------------------------------- | -----------: | -----------------: |
| Mounted populated cells | 1,025 | 60 |
| DOM elements | 10,236 | 728 |
| Median time to visible cells | 464 ms | 318 ms |
| Median layout/style work | 63.9 ms | 13.4 ms |
| Median main-thread task time during observation | 1,124 ms | 82.8 ms |
| Median accumulated long-task duration | 147 ms | 0 ms |
This isolates a substantial browser cost from mounting the full view; it does not demonstrate a complete virtualization implementation or guarantee the same production savings. Off-screen spinner components remain mounted in the full view, but this experiment does not separately attribute their cost.
Direct-load layout-shift observations varied (roughly 0.0820.657), with footer/content shifts recorded. Client-click samples recorded zero, partly because recent-input shifts are excluded. These short development observations are not interchangeable with production's Lighthouse CLS of 0.127. Reserve appropriate loading geometry when redesigning rendering.
## Background requests and artwork
[Offline synchronization](../../src/lib/stores/offlineSync.ts) schedules startup after one second and reuses a matching format-2 snapshot younger than 15 minutes. Explicit edits, retry, account changes and reconnect trigger a fresh copy. [The snapshot endpoint](../../src/routes/api/offline-snapshot/+server.ts) loads every owned dex in parallel, including full entry/detail/catch data. For this account that is ten Supabase calls with a fresh token, independent of the page's eight.
A separate local comparison activated the existing offline worker and controlled metadata age in the disposable browser cache. Five warm direct loads per condition:
| Condition | Median visible cells | Snapshot requests per load | Backup requests per load |
| -------------------------------------- | -------------------: | -------------------------: | -----------------------: |
| Fresh snapshot, enabled | 449 ms | 0 | 1 |
| Stale snapshot, enabled | 431 ms | 1 | 1 |
| Stale snapshot, both endpoints blocked | 464 ms | 0 completed | 0 completed |
The stale snapshot was **849,107 B**, typically around 130160 ms locally. It started around 1.2 seconds after navigation, after cells were visible. Backup status began around 0.20.3 seconds, overlapping rendering. Blocking requests did **not** improve time to visible cells consistently in these runs. Thus background work is a secondary bandwidth/CPU/DB contention concern, not a demonstrated explanation of initial local TTFB. An already-running snapshot could overlap a later client navigation; the production HAR cannot establish that.
[Backup status GET](../../src/routes/api/export-integrations/+server.ts) calls `requireAuth`, reads the memoized session, then calls `supabase.auth.setSession(session)`. Instrumentation observed **two `GET /auth/v1/user` requests plus one integration query**. Memoizing `safeGetSession` does not eliminate validation triggered by this separate `setSession` call.
The worker stores snapshot data without automatically fetching all artwork; artwork fetches are cached as viewed, and full artwork download is explicit. The initial dev navigation matrix had no registered worker, so its snapshot requests did not establish cache-reuse behavior; that is why the separate worker-enabled comparison was necessary.
### Preserve detail-image resolution
[Sprite URL resolution](../../src/lib/utils/spriteUrl.ts) selects local assets only when `PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER` is `true`; otherwise it uses GitHub raw URLs. The HAR confirms the latter for production. Local `home/1.webp` and `home/shiny/1.webp` are both 512 × 512. In-memory 128 px WebP experiments at quality 80 reduced 13,530 → 2,726 B and 12,634 → 2,522 B (about 80%). Two samples are not a catalog-wide saving estimate.
**Retain the 512 px originals for the clicked Pokémon detail view.** If pursuing this optimization, introduce separate grid thumbnails and retain full-resolution detail URLs, with fallback coverage for shiny, female and named forms. Update manifest/cache versioning deliberately; replacing assets at existing URLs conflicts with the worker's cache-forever assumption. The sprite build script currently defaults `SPRITE_MAX_SIZE` to zero, so “sprites-small” does not imply smaller dimensions. No sprite files were changed.
## Ranked recommendations
| Priority | Recommended next change | Evidence / confidence | Effort and risk |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1 | Stop computing an unused count in the page preload; share one ordered scoped-entry retrieval when rows and count are both needed. Combine ownership and scope retrieval where practical. | Confirmed redundant work: one national count or two full scoped queries, plus serial metadata reads. High confidence in work reduction; production milliseconds unknown. | Lowmedium. Preserve ownership/RLS, scope deduplication, named default forms and ordering. |
| 2 | Reduce initial data and the number of mounted boxes together. Evaluate viewport rendering with reserved space, lightweight global totals/order, and on-demand detail data. | Only 60/1,025 cells visible; capped rendering reduced visible time 31%, layout/style work 79%, DOM 93%. Display-only JSON is about 71% smaller. | Mediumhigh. Preserve box numbering, scroll/keyboard access, global filters/counts, bulk edits, navigation races and offline details. Do not just change `9999` to `60`. |
| 3 | Resolve the Netlify buffering constraint as part of the loading design. Validate a supported streaming-capable adapter/runtime in a future deployment, or make the initial response intentionally small without relying on deferred promises. | Installed adapter demonstrably buffers. High confidence in the constraint; no deployed streaming alternative verified. | Medium. Keep Netlify as target; test both document and data navigation. A shell alone is not an interactive grid. |
| 4 | Remove redundant backup-session validation if authentication remains guaranteed; schedule nonessential background work after critical page work while preserving snapshot freshness and explicit syncs. | Three backup calls confirmed; stale snapshot 849 KB. No consistent local first-visibility gain when blocked. | Lowmedium. Verify reconnect status and account isolation; do not disable offline support. |
| 5 | Serve separate grid thumbnails, retaining full-resolution detail artwork. Evaluate first-party hosting/cache headers for those assets. | Two samples about 80% smaller; production HAR sprite transfer 531 KB. | Medium. Preserve all variants and offline cache behavior. Requires separate thumbnail URLs, not destructive resizing. |
| 6 | Replace per-entry linear catch lookup with a map when touching repository joins. | `.find()` per row has quadratic scaling, but current local processing is small. | Low. Lower priority than network, payload and DOM work. |
Do not propose a database index or a region move as an established fix from the available evidence. Production-specific stage instrumentation and region verification remain future work requiring access.
### Regression coverage and secondary findings
[Lighthouse CI](../../lighthouserc.cjs) audits only five signed-out pages using the Node adapter. [Signed-in BDD scenarios](../../tests/bdd/features/performance.feature) allow five seconds for direct load and three seconds per switch, assert first-cell visibility and prohibit a separate entry request. Those checks do not exercise Netlify's response buffering, assert authenticated data/DOM sizes, or distinguish shell, first cells and completed loading.
Future checks should use a full national fixture and a scoped form fixture, measure document and client navigation separately, and track response bytes, mounted cells, first useful view and background request counts. Preserve ordering, overlapping dex deduplication, named default forms, missing catches, filters, bulk status updates, modal notes, shiny/female artwork, account changes and fresh/stale offline behavior. A deliberate loading redesign may require replacing the “no separate entry request” assertion with a user-visible timing/data budget. Deployment checks must exercise actual Netlify responses, not infer parity from Node CI.
The nested `<button>` in [Tooltip](../../src/lib/components/Tooltip.svelte) is confirmed by source inside each Pokémon button. Address its accessible name and invalid nesting in follow-up UI work. Contrast, target-size and missing-meta-description findings are secondary to the performance diagnosis; contrast/target size require rendered theme/mobile verification, while the missing page description is visible in source. Preserve detail-view artwork quality as requested.
## Reproduction and cleanup
Raw captures, disposable credentials and diagnostic scripts are local-only under `/tmp/pokedex-perf-investigation` (directory mode 700); they are not included in the repository evidence. The evidence JSON omits sessions, fixture IDs, personal data and full query filters. The original `dex.har` and prompt remain untouched and untracked.
The seeded stack was already running. Instead of resetting it or invoking Tailwind output generation, the investigation used the project's loopback-checked Supabase environment wrapper and the same Vite dev server used by `dev:supabase`:
```sh
# From the repository root; these diagnostic scripts are retained locally, not installed tooling.
node /tmp/pokedex-perf-investigation/setup.mjs
node scripts/run-with-local-supabase.mjs node /tmp/pokedex-perf-investigation/seed.mjs
node scripts/run-with-local-supabase.mjs node /tmp/pokedex-perf-investigation/auth.mjs
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER=true node scripts/run-with-local-supabase.mjs npx vite dev --host 127.0.0.1 --port 4173 > /tmp/pokedex-perf-investigation/dev.log 2>&1
# In another terminal, after Vite dependency optimization has settled:
node /tmp/pokedex-perf-investigation/measure.mjs
node /tmp/pokedex-perf-investigation/background.mjs
node /tmp/pokedex-perf-investigation/server-probe.mjs
node /tmp/pokedex-perf-investigation/analyze-server.mjs
node /tmp/pokedex-perf-investigation/explain.mjs
node /tmp/pokedex-perf-investigation/catch-plan.mjs
# After stopping the dev server and restoring the instrumented files:
node scripts/run-with-local-supabase.mjs node /tmp/pokedex-perf-investigation/cleanup.mjs
```
The rendering-cap experiment temporarily changed `{#each boxNumbers as boxNumber}` to `{#each boxNumbers.slice(0, 2) as boxNumber}`, then ran `PERF_VARIANT=grid-cap node /tmp/pokedex-perf-investigation/grid-cap.mjs` and restored the file. Run comparisons sequentially, discard the first run and keep viewport/cache/fixture settings equal. The full methodology and sanitized per-run evidence above remain usable if the temporary scripts are later removed.
At completion, original application files were restored byte-for-byte, the investigation server was stopped, and only the dedicated fixture account and its cascading test records were deleted. Existing database data and production configuration were unchanged. No commit was created.
@@ -0,0 +1,60 @@
{
"capturedAt": "2026-09-15T16:28:41.386Z",
"environment": "local-node",
"revision": "local-working-tree",
"clientLocation": "local-loopback",
"groups": [
{
"fixture": "national",
"navigation": "direct",
"samples": 30,
"visibleP75": 123.5,
"interactiveP75": 145.40000009536743,
"responseBytesP75": 248668,
"missingBytes": 0,
"maxDOM": 2088,
"maxCells": 120,
"maxCLS": 0,
"gridRequests": 0
},
{
"fixture": "national",
"navigation": "client",
"samples": 30,
"visibleP75": 495.59999990463257,
"interactiveP75": 494.09999990463257,
"responseBytesP75": 102687,
"missingBytes": 0,
"maxDOM": 2090,
"maxCells": 120,
"maxCLS": 0,
"gridRequests": 0
},
{
"fixture": "scoped-forms",
"navigation": "direct",
"samples": 30,
"visibleP75": 114.5,
"interactiveP75": 133.10000014305115,
"responseBytesP75": 203601,
"missingBytes": 0,
"maxDOM": 2073,
"maxCells": 120,
"maxCLS": 0,
"gridRequests": 0
},
{
"fixture": "scoped-forms",
"navigation": "client",
"samples": 30,
"visibleP75": 491.7000000476837,
"interactiveP75": 490.60000014305115,
"responseBytesP75": 45645,
"missingBytes": 0,
"maxDOM": 2075,
"maxCells": 120,
"maxCLS": 0,
"gridRequests": 0
}
]
}
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
// Lighthouse CI: `npm run test:lighthouse` builds the Node adapter output, serves it and audits the
// public pages. Any category below 90 fails the run (and so the PR).
// Set LIGHTHOUSE_FORM_FACTOR=desktop to audit with the desktop profile; the default is Lighthouse's
// mobile profile (slow 4G + CPU throttling), which is the stricter of the two. The variable must not
// start with LHCI_: lhci treats those as CLI flags, so LHCI_PRESET was passed to `lhci assert` as
// an invalid `--preset`.
const preset = process.env.LIGHTHOUSE_FORM_FACTOR === 'desktop' ? 'desktop' : undefined;
module.exports = {
ci: {
collect: {
startServerCommand: 'npm run preview-node',
startServerReadyPattern: 'Listening on',
url: [
'http://localhost:4173/',
'http://localhost:4173/signin',
'http://localhost:4173/welcome',
'http://localhost:4173/offline-guide',
'http://localhost:4173/forgot-password'
],
// Median of three runs smooths out noise from shared CI runners.
numberOfRuns: 3,
settings: {
...(preset ? { preset } : {}),
chromeFlags: '--no-sandbox --headless=new'
}
},
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.9 }],
'categories:accessibility': ['error', { minScore: 0.9 }],
'categories:best-practices': ['error', { minScore: 0.9 }],
'categories:seo': ['error', { minScore: 0.9 }],
// The app compresses its own responses (see src/lib/server/compression.ts and the
// precompressed build), so nothing may be served uncompressed.
'uses-text-compression': ['error', { minScore: 1 }],
// Regression budgets, set a little above what every audited page measured in September
// 2026 (mobile profile: LCP 1.4-2.6 s, TBT 0 ms, CLS 0, ~100 KB script, ~14 KB CSS and
// ~175 KB in total over the wire). A PR that makes pages meaningfully slower or heavier
// fails here even while the category scores stay above 90. When a change legitimately
// needs more, raise the number in the same PR so the cost is reviewed.
'largest-contentful-paint': ['error', { maxNumericValue: 3000 }],
'total-blocking-time': ['error', { maxNumericValue: 200 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.05 }],
'resource-summary:script:size': ['error', { maxNumericValue: 115 * 1024 }],
'resource-summary:stylesheet:size': ['error', { maxNumericValue: 20 * 1024 }],
'resource-summary:total:size': ['error', { maxNumericValue: 220 * 1024 }]
}
},
upload: {
target: 'filesystem',
outputDir: '.lighthouseci/reports'
}
}
};
+7 -1
View File
@@ -1,3 +1,9 @@
[build]
command = "npm run build"
command = "npm ci && ./node_modules/.bin/supabase link --project-ref $SUPABASE_PROJECT_REF && ./node_modules/.bin/supabase db push && npm run build"
publish = "build"
[build.environment]
NODE_VERSION = "22"
[context.deploy-preview]
command = "npm ci && npm run build"
+7013 -1125
View File
File diff suppressed because it is too large Load Diff
+52 -20
View File
@@ -1,16 +1,19 @@
{
"name": "LivingDexTracker",
"name": "livingdextracker",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
"dev-generate": "GENERATE_SW=true npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
"dev-generate-suppress-w": "GENERATE_SW=true SUPPRESS_WARNING=true npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
"build-generate-sw": "GENERATE_SW=true vite build",
"build-generate-sw-node": "NODE_ADAPTER=true GENERATE_SW=true vite build",
"build": "npx tailwindcss -i ./static/input.css -o ./static/output.css && vite build",
"build-inject-manifest-node": "NODE_ADAPTER=true vite build",
"build-self-destroying": "SELF_DESTROYING_SW=true vite build",
"sprites:build": "node scripts/optimize-sprites.mjs",
"sprites:manifest": "node scripts/sprite-manifest.mjs",
"build-generate-sw": "npm run sprites:grid && npm run tailwind && GENERATE_SW=true vite build",
"build-generate-sw-node": "npm run sprites:grid && npm run tailwind && NODE_ADAPTER=true GENERATE_SW=true vite build",
"build": "npm run sprites:grid && npm run tailwind && vite build",
"build-inject-manifest": "npm run sprites:grid && npm run tailwind && vite build",
"build-inject-manifest-node": "npm run sprites:grid && npm run tailwind && NODE_ADAPTER=true vite build",
"build-self-destroying": "npm run sprites:grid && npm run tailwind && SELF_DESTROYING_SW=true vite build",
"preview": "vite preview --port=4173",
"preview-node": "PORT=4173 node build",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
@@ -18,20 +21,45 @@
"lint": "prettier --check . && eslint .",
"lint-fix": "npm run lint --fix",
"format": "prettier --write .",
"tailwind": "npx tailwindcss -i ./static/input.css -o ./static/output.css",
"test-generate-sw": "npm run build-generate-sw && GENERATE_SW=true vitest run && GENERATE_SW=true playwright test",
"test-generate-sw-node": "npm run build-generate-sw-node && NODE_ADAPTER=true GENERATE_SW=true vitest run && NODE_ADAPTER=true GENERATE_SW=true playwright test",
"test-inject-manifest": "npm run build-inject-manifest && vitest run && playwright test",
"test-inject-manifest-node": "npm run build-inject-manifest-node && NODE_ADAPTER=true vitest run && NODE_ADAPTER=true playwright test",
"test": "npm run test-generate-sw && npm run test-generate-sw-node && npm run test-inject-manifest && npm run test-inject-manifest-node"
"tailwind": "npx tailwindcss -i ./static/input.css -o ./static/output.css --minify",
"test:lighthouse": "npm run build-inject-manifest-node && lhci autorun",
"test:unit": "vitest run tests/unit",
"test:data": "vitest run tests/data",
"test:coverage": "vitest run tests/unit --coverage",
"test:fast": "npm run test:coverage && npm run test:data",
"test:integration": "node scripts/run-with-local-supabase.mjs vitest run --config vitest.integration.config.mts",
"test:bdd:generate": "bddgen",
"test:bdd:inner": "npm run build-inject-manifest && npm run test:bdd:generate && playwright test --project=chromium",
"test:bdd": "ALLOW_PROVIDER_ENDPOINT_OVERRIDES=true GOOGLE_OAUTH_CLIENT_ID=mock-google GOOGLE_OAUTH_CLIENT_SECRET=mock-google-secret DROPBOX_OAUTH_CLIENT_ID=mock-dropbox DROPBOX_OAUTH_CLIENT_SECRET=mock-dropbox-secret GOOGLE_OAUTH_AUTHORIZE_URL=http://127.0.0.1:4199/google/authorize GOOGLE_OAUTH_TOKEN_URL=http://127.0.0.1:4199/google/token GOOGLE_DRIVE_API_URL=http://127.0.0.1:4199/google/drive GOOGLE_DRIVE_UPLOAD_URL=http://127.0.0.1:4199/google/upload DROPBOX_OAUTH_AUTHORIZE_URL=http://127.0.0.1:4199/dropbox/authorize DROPBOX_OAUTH_TOKEN_URL=http://127.0.0.1:4199/dropbox/token DROPBOX_UPLOAD_URL=http://127.0.0.1:4199/dropbox/files/upload node scripts/run-with-local-supabase.mjs npm run test:bdd:inner",
"test:build:generate-static": "npm run build-generate-sw && GENERATE_SW=true vitest run --config vitest.build.config.mts",
"test:build:generate-node": "npm run build-generate-sw-node && NODE_ADAPTER=true GENERATE_SW=true vitest run --config vitest.build.config.mts",
"test:build:inject-static": "npm run build-inject-manifest && vitest run --config vitest.build.config.mts",
"test:build:inject-node": "npm run build-inject-manifest-node && NODE_ADAPTER=true vitest run --config vitest.build.config.mts",
"test:build": "npm run test:build:generate-static && npm run test:build:generate-node && npm run test:build:inject-static && npm run test:build:inject-node",
"test:ci": "npm run test:fast && npm run test:integration && npm run test:build && npm run test:bdd && npm run test:performance",
"test": "npm run test:ci",
"supabase:start": "supabase start",
"supabase:stop": "supabase stop",
"supabase:reset": "supabase db reset",
"supabase:studio": "supabase studio",
"migrate:convert-tsv": "node scripts/convert-tsv-to-sql.js",
"dev:local": "./scripts/dev-local.sh && npm run dev",
"dev:supabase": "supabase start && npm run dev",
"sprites:grid": "node scripts/grid-thumbnails.mjs",
"build:cloudflare": "DEPLOY_TARGET=cloudflare npm run build",
"preview:cloudflare": "wrangler dev",
"check:cloudflare": "wrangler deploy --dry-run",
"test:performance": "node scripts/run-with-local-supabase.mjs node scripts/performance/run-local.mjs"
},
"devDependencies": {
"@playwright/test": "^1.37.1",
"@lhci/cli": "^0.15.1",
"@playwright/test": "1.55.1",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-cloudflare": "7.2.9",
"@sveltejs/adapter-netlify": "^4.1.0",
"@sveltejs/adapter-node": "^2.0.0",
"@sveltejs/adapter-static": "^3.0.0",
"@sveltejs/kit": "^2.0.6",
"@sveltejs/kit": "^2.5.3",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@types/cookie": "^0.6.0",
"@types/eslint": "^8.56.0",
@@ -39,29 +67,33 @@
"@typescript-eslint/parser": "^7.0.0",
"@vite-pwa/assets-generator": "^0.2.4",
"@vite-pwa/sveltekit": "^0.4.0",
"@vitest/coverage-v8": "^1.6.1",
"autoprefixer": "^10.4.19",
"daisyui": "^4.10.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1",
"playwright-bdd": "^8.5.1",
"postcss": "^8.4.38",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"supabase": "2.72.7",
"svelte": "^4.2.8",
"svelte-check": "^3.6.2",
"tailwindcss": "^3.4.3",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"vitest": "^1.0.4"
"vitest": "^1.0.4",
"wrangler": "4.131.2"
},
"type": "module",
"dependencies": {
"@supabase/ssr": "^0.1.0",
"@supabase/supabase-js": "^2.42.0",
"mongoose": "^8.0.3",
"nanoid": "^5.0.4"
"@supabase/ssr": "^0.12.7",
"@supabase/supabase-js": "^2.116.0",
"nanoid": "^5.0.4",
"sharp": "^0.33.4"
},
"engines": {
"node": ">=18.13.0"
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
}
}
+33 -16
View File
@@ -1,10 +1,18 @@
import { defineConfig, devices } from '@playwright/test'
import { defineConfig, devices } from '@playwright/test';
import { defineBddConfig } from 'playwright-bdd';
const url = 'http://localhost:4173'
const url = 'http://localhost:4173';
const testDir = defineBddConfig({
features: 'tests/bdd/features/**/*.feature',
steps: ['tests/bdd/steps/**/*.ts', 'tests/bdd/fixtures.ts'],
outputDir: '.features-gen',
missingSteps: 'fail-on-gen'
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { nodeAdapter } from './adapter.mjs'
import { nodeAdapter } from './adapter.mjs';
/**
* Read environment variables from file.
@@ -16,27 +24,28 @@ import { nodeAdapter } from './adapter.mjs'
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './client-test',
testDir,
globalTeardown: './tests/bdd/globalTeardown.ts',
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
outputDir: 'test-results/',
timeout: 5 * 1000,
timeout: 90 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 1000,
timeout: 10 * 1000
},
/* Run tests in files in parallel */
fullyParallel: true,
fullyParallel: false,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
workers: 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'line',
reporter: [['line'], ['./tests/support/no-skips-reporter.ts']],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
@@ -46,15 +55,16 @@ export default defineConfig({
//offline: true,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
trace: 'retain-on-failure',
screenshot: 'only-on-failure'
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
use: { ...devices['Desktop Chrome'] }
}
// {
// name: 'firefox',
@@ -88,9 +98,16 @@ export default defineConfig({
],
/* Run your local dev server before starting the tests */
webServer: {
command: nodeAdapter ? 'pnpm run preview-node' : 'pnpm run preview',
url,
reuseExistingServer: !process.env.CI,
webServer: [
{
command: 'node scripts/mock-provider-server.mjs',
url: 'http://127.0.0.1:4199/__mock/state',
reuseExistingServer: !process.env.CI
},
{
command: nodeAdapter ? 'npm run preview-node' : 'npm run preview',
url,
reuseExistingServer: !process.env.CI
}
]
});
+2 -2
View File
@@ -1,6 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
autoprefixer: {}
}
};
+2 -2
View File
@@ -1,3 +1,3 @@
import process from 'node:process'
import process from 'node:process';
export const generateSW = process.env.GENERATE_SW === 'true'
export const generateSW = process.env.GENERATE_SW === 'true';
+197
View File
@@ -0,0 +1,197 @@
#!/usr/bin/env node
/**
* Generates SQL migration from CSV files
* Usage: node csv-to-migration.js <Region>
* Example: node csv-to-migration.js Kanto
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/**
* Parse CSV file into array of objects
*/
function parseCSV(filePath) {
const content = fs.readFileSync(filePath, 'utf-8');
const lines = content.split('\n').filter((line) => line.trim());
const headers = lines[0].split(',');
return lines.slice(1).map((line) => {
const values = parseCSVLine(line);
const obj = {};
headers.forEach((header, i) => {
obj[header] = values[i] || null;
});
return obj;
});
}
/**
* Parse a single CSV line, handling quoted values
*/
function parseCSVLine(line) {
const values = [];
let current = '';
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const char = line[i];
if (char === '"') {
inQuotes = !inQuotes;
} else if (char === ',' && !inQuotes) {
values.push(current);
current = '';
} else {
current += char;
}
}
values.push(current);
return values;
}
/**
* Generate migration SQL from CSV data
*/
function generateMigration(region) {
console.log(`\nGenerating migration for ${region}...`);
// Determine generation number from region
const regionToGen = {
Kanto: 1,
Johto: 2,
Hoenn: 3,
Sinnoh: 4,
Unova: 5,
Kalos: 6,
Alola: 7,
Galar: 8,
Hisui: 8,
Paldea: 9
};
const gen = regionToGen[region] || 1;
// 1. Load CSV files
const pokemonPath = path.join(
__dirname,
'..',
'data',
'pokemon',
`gen${gen}-${region.toLowerCase()}.csv`
);
const gamesPath = path.join(__dirname, '..', 'data', 'pokemon', 'games.csv');
if (!fs.existsSync(pokemonPath)) {
console.error(`Error: Pokemon CSV not found at ${pokemonPath}`);
process.exit(1);
}
const pokemon = parseCSV(pokemonPath);
const games = parseCSV(gamesPath);
// 2. Filter for this region
const regionGames = games.filter((g) => g.region === region);
if (regionGames.length === 0) {
console.error(`Error: No games found for region ${region} in games.csv`);
process.exit(1);
}
// 3. Generate SQL
let sql = `-- Seed ${region} region Pokémon (Gen ${gen})\n`;
sql += `-- Auto-generated from CSV files\n\n`;
// Region-game mappings
sql += `-- Insert ${region} region-game mappings\n`;
sql += `INSERT INTO region_game_mappings (region, game) VALUES\n`;
sql += regionGames.map((g) => ` ('${region}', '${g.displayName}')`).join(',\n');
sql += `\nON CONFLICT (region, game) DO NOTHING;\n\n`;
// Pokemon entries (without regional dex number)
sql += `-- Insert ${region} Pokémon entries\n`;
sql += `INSERT INTO pokedex_entries (\n`;
sql += ` "pokedexNumber",\n`;
sql += ` pokemon,\n`;
sql += ` form,\n`;
sql += ` "canGigantamax",\n`;
sql += ` "regionToCatchIn",\n`;
sql += ` "gamesToCatchIn"\n`;
sql += `) VALUES\n`;
const rows = pokemon.map((p) => {
const form = p.form ? `'${p.form}'` : 'NULL';
// Use regionalDexGames for the database (regional dex availability)
// originGames column is for future origin dex feature
const gamesField = p.regionalDexGames || p.games; // Fallback to old 'games' column for compatibility
const gamesList = gamesField.split('|');
const gamesArray = `ARRAY[${gamesList.map((g) => `'${g}'`).join(', ')}]`;
return `(${p.pokedexNumber}, '${p.name}', ${form}, false, '${region}', ${gamesArray})`;
});
sql += rows.join(',\n');
sql += '\nON CONFLICT ON CONSTRAINT unique_pokemon_form DO NOTHING;\n\n';
// Regional dex numbers (separate table)
sql += `-- Insert ${region} regional dex numbers\n`;
const dexRows = pokemon
.filter((p) => p.regionalNumber) // Only entries with regional dex numbers
.map((p) => {
const formCondition = p.form ? `form = '${p.form}'` : `form IS NULL`;
return ` ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = ${p.pokedexNumber} AND ${formCondition}), '${region}', ${p.regionalNumber})`;
});
if (dexRows.length > 0) {
sql += `INSERT INTO regional_dex_numbers (\n`;
sql += ` pokedex_entry_id,\n`;
sql += ` region,\n`;
sql += ` dex_number\n`;
sql += `) VALUES\n`;
sql += dexRows.join(',\n');
sql += ';\n\n';
} else {
sql += '-- No regional dex numbers for this region\n\n';
}
// Add metadata
sql += `-- Add metadata\n`;
sql += `INSERT INTO metadata (key, value) VALUES\n`;
sql += ` ('${region.toLowerCase()}_seeded', 'true'),\n`;
sql += ` ('${region.toLowerCase()}_seed_date', NOW()::TEXT),\n`;
sql += ` ('${region.toLowerCase()}_pokemon_count', '${pokemon.filter((p) => !p.form).length}');\n`;
// 4. Write file
const timestamp = new Date()
.toISOString()
.replace(/[-:T.]/g, '')
.slice(0, 14);
const filename = `${timestamp}_seed_${region.toLowerCase()}.sql`;
const outputPath = path.join(__dirname, '..', 'supabase', 'migrations', filename);
fs.writeFileSync(outputPath, sql);
console.log(`✓ Generated ${filename}`);
console.log(` - ${pokemon.length} Pokemon entries`);
console.log(` - ${dexRows.length} regional dex numbers`);
console.log(` - ${regionGames.length} games\n`);
return filename;
}
// Run
const region = process.argv[2];
if (!region) {
console.error('Usage: node csv-to-migration.js <Region>');
console.error('Example: node csv-to-migration.js Kanto');
process.exit(1);
}
generateMigration(region);
+35
View File
@@ -0,0 +1,35 @@
import { readdir, mkdir, stat, writeFile } from 'node:fs/promises';
import path from 'node:path';
import sharp from 'sharp';
// Bump the URL version whenever dimensions, quality or source artwork changes.
const source = 'static/sprites-small/home';
const destination = 'static/sprites-grid/v1/home';
const files = [];
async function walk(relative = '') {
for (const entry of await readdir(path.join(source, relative), { withFileTypes: true })) {
const name = path.join(relative, entry.name);
if (entry.isDirectory()) await walk(name);
else if (entry.name.endsWith('.webp')) files.push(name);
}
}
await walk();
const manifest = [];
for (const relative of files.sort()) {
const target = path.join(destination, relative);
await mkdir(path.dirname(target), { recursive: true });
try {
await stat(target);
} catch {
await sharp(path.join(source, relative))
.resize(128, 128, { fit: 'inside', withoutEnlargement: true })
.webp({ quality: 80 })
.toFile(target);
}
manifest.push({ path: relative.split(path.sep).join('/'), bytes: (await stat(target)).size });
}
await writeFile(
'static/sprites-grid/v1/manifest.json',
JSON.stringify({ version: 1, width: 128, quality: 80, files: manifest })
);
console.log(`Prepared ${files.length} versioned grid thumbnails; originals preserved.`);
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env node
import { createServer } from 'node:http';
const port = Number(process.env.MOCK_PROVIDER_PORT ?? 4199);
const state = { requests: [], failUploads: false, revokeRefresh: false, refreshes: 0 };
function send(response, status, body, headers = {}) {
response.writeHead(status, { 'Content-Type': 'application/json', ...headers });
response.end(typeof body === 'string' ? body : JSON.stringify(body));
}
const server = createServer(async (request, response) => {
const url = new URL(request.url ?? '/', `http://127.0.0.1:${port}`);
let body = '';
for await (const chunk of request) body += chunk;
// Control-plane calls (including Playwright's webServer readiness polling of /__mock/state)
// must not show up as provider traffic the assertions then reason about.
if (!url.pathname.startsWith('/__mock/')) {
state.requests.push({ method: request.method, path: url.pathname, query: url.search, body });
}
if (url.pathname === '/__mock/state') return send(response, 200, state);
if (url.pathname === '/__mock/reset') {
state.requests = [];
state.failUploads = false;
state.revokeRefresh = false;
state.refreshes = 0;
return send(response, 200, { ok: true });
}
if (url.pathname === '/__mock/fail-uploads') {
state.failUploads = true;
return send(response, 200, { ok: true });
}
if (url.pathname === '/__mock/revoke-refresh') {
state.revokeRefresh = true;
return send(response, 200, { ok: true });
}
if (url.pathname.endsWith('/authorize')) {
const redirectUri = url.searchParams.get('redirect_uri');
const oauthState = url.searchParams.get('state');
if (!redirectUri || !oauthState) return send(response, 400, { error: 'missing redirect data' });
const callback = new URL(redirectUri);
callback.searchParams.set('code', 'mock-authorization-code');
callback.searchParams.set('state', oauthState);
response.writeHead(302, { Location: callback.toString() });
return response.end();
}
if (url.pathname.endsWith('/token')) {
if (body.includes('grant_type=refresh_token')) {
state.refreshes++;
// Mirrors Google and Dropbox answering a revoked or expired refresh token.
if (state.revokeRefresh) {
return send(response, 400, { error: 'invalid_grant', error_description: 'Bad Request' });
}
}
return send(response, 200, {
access_token: 'mock-access-token',
refresh_token: 'mock-refresh-token',
expires_in: 3600,
scope: 'files.content.write drive.file'
});
}
if (url.pathname.includes('/upload') || url.pathname.endsWith('/files/upload')) {
if (state.failUploads) return send(response, 503, { error: 'mock upload failure' });
return send(response, 200, { id: 'mock-file-id', name: 'pokedex.csv' });
}
if (url.pathname.endsWith('/drive/files')) {
if (request.method === 'GET') return send(response, 200, { files: [{ id: 'mock-folder-id' }] });
return send(response, 200, { id: 'mock-folder-id' });
}
return send(response, 404, { error: `No mock route for ${url.pathname}` });
});
server.listen(port, '127.0.0.1', () => {
console.log(`Mock provider server listening on http://127.0.0.1:${port}`);
});
for (const signal of ['SIGTERM', 'SIGINT']) {
process.on(signal, () => server.close(() => process.exit(0)));
}
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env node
import path from 'node:path';
import process from 'node:process';
import { mkdir, readdir, rename } from 'node:fs/promises';
import sharp from 'sharp';
import { writeSpriteManifest } from './sprite-manifest.mjs';
const inputDir = process.env.SPRITE_INPUT_DIR ?? path.join(process.cwd(), 'static', 'sprites');
const outputDir =
process.env.SPRITE_OUTPUT_DIR ?? path.join(process.cwd(), 'static', 'sprites-small');
const format = (process.env.SPRITE_FORMAT ?? 'webp').toLowerCase();
const quality = Number(process.env.SPRITE_QUALITY ?? 80);
const maxSize = Number(process.env.SPRITE_MAX_SIZE ?? 0);
if (!['png', 'webp'].includes(format)) {
console.error(`Unsupported SPRITE_FORMAT "${format}". Use "png" or "webp".`);
process.exit(1);
}
async function walk(dir, files = []) {
const entries = await readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
await walk(fullPath, files);
continue;
}
if (entry.isFile() && entry.name.toLowerCase().endsWith('.png')) {
files.push(fullPath);
}
}
return files;
}
const files = await walk(inputDir);
console.log(`Optimizing ${files.length} sprite images from ${inputDir}`);
for (const [index, file] of files.entries()) {
const relative = path.relative(inputDir, file);
const baseName = path.basename(file, path.extname(file));
const targetDir = path.join(outputDir, path.dirname(relative));
await mkdir(targetDir, { recursive: true });
const targetExt = format === 'png' ? '.png' : '.webp';
const targetPath = path.join(targetDir, `${baseName}${targetExt}`);
const tempPath = format === 'png' && outputDir === inputDir ? `${targetPath}.tmp` : targetPath;
const pipeline = sharp(file);
if (maxSize > 0) {
pipeline.resize({
width: maxSize,
height: maxSize,
fit: 'inside',
withoutEnlargement: true
});
}
if (format === 'png') {
await pipeline.png({ compressionLevel: 9, palette: true, quality }).toFile(tempPath);
} else {
await pipeline.webp({ quality }).toFile(tempPath);
}
if (tempPath !== targetPath) {
await rename(tempPath, targetPath);
}
if ((index + 1) % 250 === 0) {
console.log(`Processed ${index + 1}/${files.length}`);
}
}
const manifest = await writeSpriteManifest(outputDir);
console.log(`Sprite optimization complete. Manifest lists ${manifest.files.length} sprites.`);
+181
View File
@@ -0,0 +1,181 @@
import { chromium } from '@playwright/test';
import { readFile, writeFile } from 'node:fs/promises';
// Configuration holds session-file paths, never passwords. Keep it outside the repository.
const [configPath, outputPath] = process.argv.slice(2);
if (!configPath || !outputPath)
throw new Error('Usage: node scripts/performance/benchmark.mjs CONFIG.json RESULTS.json');
const config = JSON.parse(await readFile(configPath, 'utf8'));
const samples = config.samples ?? 30;
if (samples < 30)
throw new Error('Host decisions require at least 30 warm samples per fixture/navigation');
if (!config.revision || !config.databaseLabel || !config.clientLocation)
throw new Error('Record revision, databaseLabel and clientLocation for comparable results');
const browser = await chromium.launch();
const results = [];
try {
for (const host of config.hosts) {
for (const fixture of host.fixtures) {
for (const navigation of ['direct', 'client']) {
const context = await browser.newContext({
baseURL: host.url,
storageState: host.storageState,
viewport: { width: 1350, height: 940 },
deviceScaleFactor: 1
});
await context.addInitScript(() => {
window.__perfShifts = [];
new PerformanceObserver((list) => {
for (const entry of list.getEntries())
if (!entry.hadRecentInput)
window.__perfShifts.push({ value: entry.value, time: entry.startTime });
}).observe({ type: 'layout-shift', buffered: true });
window.__watchGrid = () => {
window.__perfVisible = null;
function check() {
const cell = document.querySelector('[data-entry-index]');
if (
location.pathname.startsWith('/pokedex/') &&
cell &&
cell.getBoundingClientRect().top < innerHeight &&
cell.getBoundingClientRect().height > 0
) {
window.__perfVisible = performance.now();
performance.mark('pokedex:first-visible');
} else requestAnimationFrame(check);
}
requestAnimationFrame(check);
};
window.__watchGrid();
});
const page = await context.newPage();
for (let index = 0; index <= samples; index++) {
if (navigation === 'client') {
await page.goto('/my-pokedexes');
await page.getByText(fixture.name, { exact: true }).first().waitFor();
} else if (index > 0) await page.goto('about:blank');
const bodies = [];
const requests = { grid: 0, details: 0, snapshot: 0, backup: 0 };
const onRequest = (request) => {
const path = new URL(request.url()).pathname;
if (/\/pokedexes\/[^/]+\/(grid|combined-data)$/.test(path)) requests.grid++;
if (/\/pokedexes\/[^/]+\/entries\//.test(path)) requests.details++;
if (path === '/api/offline-snapshot') requests.snapshot++;
if (path === '/api/export-integrations') requests.backup++;
};
const onResponse = (response) => {
const path = new URL(response.url()).pathname;
if (!path.startsWith(`/pokedex/${fixture.id}`)) return;
bodies.push(
(async () => {
// Chromium may not expose bodies routed through a service worker.
const body = await response.body().catch(() => null);
return {
url: response.url(),
bytes: body?.length ?? null,
status: response.status(),
fromServiceWorker: response.fromServiceWorker(),
timings: response.request().timing(),
serverTiming: response.headers()['server-timing'] ?? null
};
})()
);
};
page.on('request', onRequest);
page.on('response', onResponse);
let started = 0;
if (navigation === 'direct')
await page.goto(`/pokedex/${fixture.id}`, { waitUntil: 'domcontentloaded' });
else {
started = await page.evaluate(() => {
performance.clearMarks('pokedex:first-interactive');
window.__watchGrid();
return performance.now();
});
await page
.locator('.card')
.filter({ hasText: fixture.name })
.first()
.getByRole('button', { name: 'View', exact: true })
.click();
}
await page.waitForSelector('[data-grid-interactive]');
await page.waitForFunction(
() =>
window.__perfVisible !== null &&
performance.getEntriesByName('pokedex:first-interactive').length > 0
);
await page.waitForTimeout(1500);
const browserData = await page.evaluate(
(start) => ({
visibleMs: window.__perfVisible - start,
interactiveMs:
performance.getEntriesByName('pokedex:first-interactive').at(-1).startTime - start,
cells: document.querySelectorAll('[data-entry-index]').length,
dom: document.querySelectorAll('*').length,
cls: window.__perfShifts
.filter((entry) => entry.time >= start)
.reduce((total, entry) => total + entry.value, 0)
}),
started
);
page.off('request', onRequest);
page.off('response', onResponse);
const resources = await page.evaluate(() =>
performance.getEntriesByType('resource').map((entry) => ({
url: entry.name,
decodedBytes: entry.decodedBodySize,
encodedBytes: entry.encodedBodySize,
transferBytes: entry.transferSize
}))
);
const responses = (await Promise.all(bodies)).map(({ url, ...response }) => {
const resource = resources.findLast((entry) => entry.url === url);
return {
...response,
bytes: response.bytes ?? (resource?.decodedBytes || null),
byteSource: response.bytes !== null ? 'response-body' : 'resource-timing',
encodedBytes: resource?.encodedBytes ?? null,
transferBytes: resource?.transferBytes ?? null
};
});
results.push({
host: host.label,
fixture: fixture.label,
navigation,
run: index === 0 ? 'first-observed' : 'warm',
...browserData,
requests,
responses
});
}
await context.close();
console.log(
`Completed ${host.label}/${fixture.label}/${navigation}: ${samples} warm samples.`
);
}
}
}
await writeFile(
outputPath,
JSON.stringify(
{
version: 1,
capturedAt: new Date().toISOString(),
revision: config.revision,
databaseLabel: config.databaseLabel,
clientLocation: config.clientLocation,
environment: config.environment ?? 'deployed',
compatibilityPassed: config.compatibilityPassed ?? false,
results
},
null,
2
)
);
console.log(
`Recorded ${results.length} samples; first-observed runs are excluded from warm statistics.`
);
} finally {
await browser.close();
}
+46
View File
@@ -0,0 +1,46 @@
import { readFile } from 'node:fs/promises';
const data = JSON.parse(await readFile(process.argv[2], 'utf8'));
const warm = data.results.filter((row) => row.run === 'warm');
const p75 = (values) => [...values].sort((a, b) => a - b)[Math.ceil(values.length * 0.75) - 1];
const groups = [...new Set(warm.map((row) => `${row.fixture}/${row.navigation}`))];
const paired = groups.map((group) => {
const rows = (host) =>
warm.filter((row) => `${row.fixture}/${row.navigation}` === group && row.host === host);
for (const host of ['netlify', 'cloudflare'])
if (rows(host).length < 30) throw new Error(`Insufficient ${host} warm samples for ${group}`);
return {
group,
netlify: p75(rows('netlify').map((row) => row.interactiveMs)),
cloudflare: p75(rows('cloudflare').map((row) => row.interactiveMs))
};
});
if (groups.length !== 4)
throw new Error(
'Expected national and scoped-form fixtures, each with direct and client navigation'
);
const netlify = p75(warm.filter((row) => row.host === 'netlify').map((row) => row.interactiveMs));
const cloudflare = p75(
warm.filter((row) => row.host === 'cloudflare').map((row) => row.interactiveMs)
);
const improvement = netlify - cloudflare;
const passes =
improvement >= 200 &&
improvement / netlify >= 0.2 &&
paired.every((row) => row.cloudflare <= row.netlify * 1.1);
console.log(
JSON.stringify(
{
overallP75: { netlify, cloudflare },
improvementMs: improvement,
improvementPercent: (100 * improvement) / netlify,
groups: paired,
performanceGatePassed: passes,
recommendation:
passes && data.compatibilityPassed && data.environment === 'deployed'
? 'Cloudflare qualifies for a migration proposal; review operating cost before cutover.'
: 'Retain Netlify: performance, deployed evidence or compatibility gate is unmet.'
},
null,
2
)
);
+113
View File
@@ -0,0 +1,113 @@
import { createClient } from '@supabase/supabase-js';
import { createServerClient } from '@supabase/ssr';
import { mkdir, readFile, writeFile, unlink } from 'node:fs/promises';
import { randomUUID } from 'node:crypto';
const directory = process.env.PERF_FIXTURE_DIR ?? '/tmp/livingdex-grid-performance';
const url = process.env.PUBLIC_SUPABASE_URL;
if (!url || !['localhost', '127.0.0.1', '[::1]'].includes(new URL(url).hostname))
throw new Error('Fixtures require the local Supabase wrapper');
const admin = createClient(url, process.env.SUPABASE_SERVICE_ROLE_KEY, {
auth: { persistSession: false }
});
const check = ({ data, error }) => {
if (error) throw error;
return data;
};
await mkdir(directory, { recursive: true, mode: 0o700 });
const fixturePath = `${directory}/fixture.json`;
if (process.argv.includes('--cleanup')) {
const fixture = JSON.parse(await readFile(fixturePath, 'utf8'));
const { user } = check(await admin.auth.admin.getUserById(fixture.userId));
if (user.email !== fixture.email || !user.email.startsWith('grid-performance-'))
throw new Error('Refusing to remove a non-fixture account');
check(await admin.auth.admin.deleteUser(fixture.userId));
await unlink(fixturePath);
await unlink(`${directory}/storage-state.json`).catch(() => {});
console.log('Removed disposable performance account and session.');
process.exit(0);
}
try {
await readFile(fixturePath);
throw new Error('An existing fixture needs cleanup first');
} catch (error) {
if (error.code !== 'ENOENT') throw error;
}
const email = `grid-performance-${randomUUID()}@example.test`;
const password = randomUUID() + 'aA1!';
const { user } = check(await admin.auth.admin.createUser({ email, password, email_confirm: true }));
const fixture = { userId: user.id, email, password, dexes: [] };
await writeFile(fixturePath, JSON.stringify(fixture), { mode: 0o600 });
fixture.dexes = check(
await admin
.from('pokedexes')
.insert([
{ userId: user.id, name: 'Performance National', isLivingDex: true, isFormDex: false },
{
userId: user.id,
name: 'Performance Scarlet Forms',
isLivingDex: true,
isFormDex: true,
gameScope: 'Scarlet'
}
])
.select()
);
const game = fixture.dexes.find((dex) => dex.gameScope);
check(
await admin.from('pokedex_dex_scopes').insert({ pokedexId: game.id, dexId: 'scarlet-paldea' })
);
const entries = [];
for (let from = 0; ; from += 1000) {
const page = check(
await admin
.from('pokemon')
.select('id,isDefaultForm')
.order('id')
.range(from, from + 999)
);
entries.push(...page);
if (page.length < 1000) break;
}
for (const dex of fixture.dexes) {
const selected = entries.filter((entry) => dex.isFormDex || entry.isDefaultForm);
for (let from = 0; from < selected.length; from += 500) {
check(
await admin.from('catch_records').insert(
selected.slice(from, from + 500).map((entry, index) => ({
userId: user.id,
pokedexId: dex.id,
pokemonId: entry.id,
caught: (from + index) % 3 === 0,
haveToEvolve: (from + index) % 3 === 1,
inHome: (from + index) % 7 === 0,
personalNotes: index === 0 ? 'Performance fixture note: preserve me' : ''
}))
)
);
}
}
await writeFile(fixturePath, JSON.stringify(fixture), { mode: 0o600 });
const cookies = [];
const client = createServerClient(url, process.env.PUBLIC_SUPABASE_ANON_KEY, {
cookies: { getAll: () => [], setAll: (values) => cookies.push(...values) }
});
check(await client.auth.signInWithPassword({ email, password }));
const base = new URL(process.env.PERF_BASE_URL ?? 'http://127.0.0.1:4173');
await writeFile(
`${directory}/storage-state.json`,
JSON.stringify({
cookies: cookies.map(({ name, value }) => ({
name,
value,
domain: base.hostname,
path: '/',
httpOnly: false,
secure: base.protocol === 'https:',
sameSite: 'Lax'
})),
origins: []
}),
{ mode: 0o600 }
);
console.log('Prepared national and scoped-form fixtures and a private browser session.');
+105
View File
@@ -0,0 +1,105 @@
import { spawn } from 'node:child_process';
import { mkdtemp, mkdir, cp, rm, readFile, writeFile } from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
const directory = await mkdtemp(path.join(os.tmpdir(), 'livingdex-grid-tests-'));
const port = process.env.PERF_PORT ?? '4185';
const env = {
...process.env,
NODE_ADAPTER: 'true',
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER: 'true',
POKEDEX_PERFORMANCE: 'true',
PERF_FIXTURE_DIR: directory,
PERF_BASE_URL: `http://127.0.0.1:${port}`,
PORT: port,
HOST: '127.0.0.1'
};
function run(command, args) {
return new Promise((resolve, reject) => {
const process = spawn(command, args, { env, stdio: 'inherit' });
process.once('error', reject);
process.once('exit', (code) =>
code === 0 ? resolve() : reject(new Error(`${command} failed (${code})`))
);
});
}
let server;
let fixture = false;
try {
await run('npm', ['run', 'build-inject-manifest-node']);
fixture = true;
await run('node', ['scripts/performance/fixture.mjs']);
server = spawn('node', ['build'], { env, stdio: 'inherit' });
await new Promise((resolve, reject) => {
const timer = setInterval(async () => {
try {
if ((await fetch(env.PERF_BASE_URL)).ok) {
clearInterval(timer);
clearTimeout(timeout);
resolve();
}
} catch {}
}, 200);
const timeout = setTimeout(() => {
clearInterval(timer);
reject(new Error('Local production server did not start'));
}, 15000);
server.once('error', (error) => {
clearInterval(timer);
clearTimeout(timeout);
reject(error);
});
server.once('exit', (code) => {
clearInterval(timer);
clearTimeout(timeout);
reject(new Error(`Local server exited (${code})`));
});
});
if (process.env.PERF_BENCHMARK === 'true') {
const data = JSON.parse(await readFile(path.join(directory, 'fixture.json'), 'utf8'));
await writeFile(
path.join(directory, 'benchmark-config.json'),
JSON.stringify({
samples: 30,
revision: process.env.PERF_REVISION ?? 'local-working-tree',
databaseLabel: 'local-seeded-supabase',
clientLocation: 'local-loopback',
environment: 'local-node',
hosts: [
{
label: 'node',
url: env.PERF_BASE_URL,
storageState: path.join(directory, 'storage-state.json'),
fixtures: data.dexes.map((dex) => ({
id: dex.id,
name: dex.name,
label: dex.gameScope ? 'scoped-forms' : 'national'
}))
}
]
})
);
await run('node', [
'scripts/performance/benchmark.mjs',
path.join(directory, 'benchmark-config.json'),
path.join(directory, 'benchmark.json')
]);
await mkdir('test-results/performance', { recursive: true });
await cp(path.join(directory, 'benchmark.json'), 'test-results/performance/benchmark.json');
}
await run('node', ['scripts/performance/verify.mjs']);
await run('node', ['scripts/performance/verify-behavior.mjs']);
await mkdir('test-results/performance', { recursive: true });
for (const file of ['verification.json', 'behavior.json', 'national.png', 'scoped.png'])
await cp(path.join(directory, file), path.join('test-results/performance', file));
} finally {
server?.kill('SIGTERM');
if (fixture)
await run('node', ['scripts/performance/fixture.mjs', '--cleanup']).catch((error) => {
throw new Error(`Fixture cleanup failed; retained recovery files in ${directory}`, {
cause: error
});
});
await rm(directory, { recursive: true, force: true });
}
+165
View File
@@ -0,0 +1,165 @@
import { chromium } from '@playwright/test';
import { readFile, writeFile } from 'node:fs/promises';
import assert from 'node:assert/strict';
const dir = process.env.PERF_FIXTURE_DIR ?? '/tmp/livingdex-grid-performance';
const fixture = JSON.parse(await readFile(`${dir}/fixture.json`, 'utf8'));
const browser = await chromium.launch();
const context = await browser.newContext({
baseURL: process.env.PERF_BASE_URL ?? 'http://127.0.0.1:4173',
storageState: `${dir}/storage-state.json`,
viewport: { width: 1350, height: 940 }
});
await context.addInitScript(() => {
window.__cls = 0;
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) if (!entry.hadRecentInput) window.__cls += entry.value;
}).observe({ type: 'layout-shift', buffered: true });
});
const page = await context.newPage();
const errors = [];
page.on('pageerror', (error) => errors.push(error.message));
const national = fixture.dexes.find((dex) => !dex.gameScope);
const scoped = fixture.dexes.find((dex) => dex.gameScope);
const results = [];
try {
await page.goto(`/pokedex/${national.id}`);
await page.waitForSelector('[data-grid-interactive]');
for (const width of [1350, 390]) {
await page.setViewportSize({ width, height: 940 });
for (const density of ['comfortable', 'compact', 'ultra']) {
await page.getByLabel('Choose box view layout density').selectOption(density);
await page.reload();
await page.waitForSelector('[data-grid-interactive]');
await page.waitForTimeout(350);
assert.equal(await page.getByLabel('Choose box view layout density').inputValue(), density);
const geometry = await page.evaluate(() => {
const cell = document.querySelector('[data-entry-index="0"]').getBoundingClientRect();
const shell = document.querySelector('[data-box-number="1"]').getBoundingClientRect();
return {
cellWidth: cell.width,
cellHeight: cell.height,
cls: window.__cls,
horizontalOverflow: document.documentElement.scrollWidth > innerWidth,
shellHeight: shell.height
};
});
assert.ok(Math.abs(geometry.cellWidth - geometry.cellHeight) < 1, JSON.stringify(geometry));
assert.ok(!geometry.horizontalOverflow, `Horizontal overflow at ${width}/${density}`);
assert.ok(geometry.cls <= 0.1, `CLS ${geometry.cls} at ${width}/${density}`);
results.push({ width, density, ...geometry });
}
}
await page.setViewportSize({ width: 1350, height: 940 });
await page.getByLabel('Choose box view layout density').selectOption('comfortable');
await page.getByLabel('Not caught', { exact: true }).check();
assert.equal(await page.locator('[data-entry-index="0"]').getAttribute('aria-disabled'), 'true');
assert.equal(await page.locator('[data-entry-index="0"]').getAttribute('data-entry-id'), '1');
await page.getByLabel('Not caught', { exact: true }).uncheck();
// Resizing across the mobile breakpoint keeps the same box at the scroll anchor.
await page.locator('[data-box-number="15"]').evaluate((node) => node.scrollIntoView());
await page.waitForTimeout(100);
const anchorTop = await page
.locator('[data-box-number="15"]')
.evaluate((node) => node.getBoundingClientRect().top);
await page.setViewportSize({ width: 390, height: 940 });
await page.waitForTimeout(200);
const resizedTop = await page
.locator('[data-box-number="15"]')
.evaluate((node) => node.getBoundingClientRect().top);
assert.ok(
Math.abs(anchorTop - resizedTop) < 2,
`Scroll anchor moved: ${anchorTop} to ${resizedTop}`
);
await page.setViewportSize({ width: 1350, height: 940 });
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForSelector('[data-entry-index="1024"]');
assert.ok((await page.locator('[data-entry-index]').count()) < 300);
await page.locator('[data-entry-index="1024"]').focus();
await page.keyboard.press('ArrowRight');
assert.equal(
await page.evaluate(() => document.activeElement.getAttribute('data-entry-index')),
'1024'
);
await page.evaluate(() => window.scrollTo(0, 0));
await page.waitForSelector('[data-entry-index="0"]');
// Closing an in-flight modal must prevent its response from replacing the next selection.
let release;
const held = new Promise((resolve) => {
release = resolve;
});
await page.route(`**/api/pokedexes/${national.id}/entries/1`, async (route) => {
await held;
await route.continue().catch(() => {});
});
await page.locator('[data-entry-index="0"]').click();
await page.getByRole('dialog').getByRole('button', { name: 'Close', exact: true }).click();
await page.locator('[data-entry-index="1"]').click();
release();
await page.getByRole('dialog').getByLabel('Notes:', { exact: true }).waitFor();
assert.equal(
await page.getByRole('dialog').getByRole('heading', { name: 'Ivysaur', exact: true }).count(),
1
);
assert.equal(
await page.getByRole('dialog').getByRole('heading', { name: 'Bulbasaur', exact: true }).count(),
0
);
await page.getByRole('dialog').getByRole('button', { name: 'Close', exact: true }).click();
await page.unrouteAll({ behavior: 'wait' });
// Navigate through actual list cards, preserving fixture-specific totals and positions.
await page.getByRole('link', { name: 'My Pokédexes' }).click();
await page
.locator('.card')
.filter({ hasText: scoped.name })
.first()
.getByRole('button', { name: 'View', exact: true })
.click();
await page.waitForSelector('[data-grid-interactive]');
assert.ok((await page.locator('body').innerText()).includes('Showing 439 of 439'));
await page.goBack();
await page
.locator('.card')
.filter({ hasText: national.name })
.first()
.getByRole('button', { name: 'View', exact: true })
.click();
await page.waitForSelector('[data-grid-interactive]');
// Wait for the existing worker's full snapshot, then read an uncached detail without a network.
await page.waitForFunction(
async () => {
const meta = await (
await caches.open('livingdex-offline-meta-v1')
).match('/__offline/current');
return !!(await meta?.json())?.dataCache;
},
{ timeout: 15000 }
);
await context.setOffline(true);
await page.locator('[data-entry-index="5"]').click();
await page.waitForFunction(() =>
document.querySelector('[role="dialog"]')?.textContent.includes('Where to catch:')
);
assert.equal(await page.getByRole('dialog').locator('textarea').count(), 0);
await page.getByRole('dialog').getByRole('button', { name: 'Close', exact: true }).click();
// A mismatched cache owner is never used as fallback.
await page.evaluate(async () => {
const cache = await caches.open('livingdex-offline-meta-v1');
const response = await cache.match('/__offline/current');
const meta = await response.json();
await cache.put(
'/__offline/current',
new Response(JSON.stringify({ ...meta, userId: 'other-account' }))
);
});
await page.locator('[data-entry-index="6"]').click();
await page.getByRole('alert').filter({ hasText: 'not saved for offline use' }).waitFor();
await page.getByRole('dialog').getByRole('button', { name: 'Close', exact: true }).click();
assert.deepEqual(errors, []);
await writeFile(`${dir}/behavior.json`, JSON.stringify(results, null, 2));
console.log(
'Passed density/mobile geometry, filtered placement, virtual boundaries, modal races, client navigation and isolated offline details.'
);
console.log(JSON.stringify(results, null, 2));
} finally {
await browser.close();
}
+129
View File
@@ -0,0 +1,129 @@
import { chromium } from '@playwright/test';
import { readFile, writeFile } from 'node:fs/promises';
import assert from 'node:assert/strict';
const directory = process.env.PERF_FIXTURE_DIR ?? '/tmp/livingdex-grid-performance';
const fixture = JSON.parse(await readFile(`${directory}/fixture.json`, 'utf8'));
const baseURL = process.env.PERF_BASE_URL ?? 'http://127.0.0.1:4173';
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
baseURL,
storageState: `${directory}/storage-state.json`,
viewport: { width: 1350, height: 940 }
});
await context.addInitScript(() => {
window.__layoutShifts = [];
window.__firstVisible = null;
new PerformanceObserver((list) => {
for (const entry of list.getEntries())
if (!entry.hadRecentInput) window.__layoutShifts.push(entry.value);
}).observe({ type: 'layout-shift', buffered: true });
function visible() {
const cell = document.querySelector('[data-entry-index]');
if (
cell &&
cell.getBoundingClientRect().height > 0 &&
cell.getBoundingClientRect().top < innerHeight
)
window.__firstVisible ??= performance.now();
if (window.__firstVisible === null) requestAnimationFrame(visible);
}
requestAnimationFrame(visible);
});
const page = await context.newPage();
const readJson = (path) =>
page.evaluate(async (path) => {
const response = await fetch(path);
if (!response.ok) throw new Error(`Fixture API failed: ${response.status}`);
return response.json();
}, path);
const errors = [];
page.on('pageerror', (error) => errors.push(error.message));
const requests = [];
page.on('request', (request) => requests.push(new URL(request.url()).pathname));
const results = [];
try {
for (const dex of fixture.dexes) {
requests.length = 0;
const response = await page.goto(`/pokedex/${dex.id}`);
assert.equal(response.status(), 200);
const html = await response.text();
assert.ok(/data-entry-index=["']?0["'\s>]/.test(html), 'Initial cells must be server rendered');
await page.waitForSelector('[data-grid-interactive]');
await page.waitForTimeout(1000);
const stats = await page.evaluate(() => ({
cells: document.querySelectorAll('[data-entry-index]').length,
dom: document.querySelectorAll('*').length,
cls: window.__layoutShifts.reduce((sum, value) => sum + value, 0),
firstVisible: window.__firstVisible,
interactive: performance.getEntriesByName('pokedex:first-interactive').at(-1)?.startTime
}));
assert.ok(stats.cells <= 180, `Mounted cells: ${stats.cells}`);
assert.ok(stats.dom < 2500, `DOM elements: ${stats.dom}`);
assert.ok(stats.cls <= 0.1, `CLS: ${stats.cls}`);
assert.equal(
requests.filter((path) => /\/api\/pokedexes\/[^/]+\/(grid|combined-data)$/.test(path)).length,
0
);
assert.equal(await page.locator('button button').count(), 0);
await page.screenshot({ path: `${directory}/${dex.gameScope ? 'scoped' : 'national'}.png` });
const first = page.locator('[data-entry-index="0"]');
const entryId = await first.getAttribute('data-entry-id');
const notes = await readJson(`/api/pokedexes/${dex.id}/entries/${entryId}`);
await first.click();
const modal = page.getByRole('dialog', { name: 'Pokémon details' });
await modal.getByLabel('Notes:', { exact: true }).waitFor();
assert.equal(
await modal.getByLabel('Notes:', { exact: true }).inputValue(),
notes.catchRecord.personalNotes
);
const image = modal.locator('img').first();
await image.waitFor();
await page.waitForFunction(
() => document.querySelector('[role="dialog"] img')?.naturalWidth > 0
);
assert.equal(await image.evaluate((node) => node.naturalWidth), 512);
assert.ok(!(await image.getAttribute('src')).includes('sprites-grid'));
await modal.getByRole('button', { name: 'Close', exact: true }).click();
assert.equal(await first.evaluate((node) => document.activeElement === node), true);
// Reopening uses cached details; bulk edits must retain the unloaded personal notes.
const detailCalls = () =>
requests.filter((path) => path.endsWith(`/entries/${entryId}`)).length;
const before = detailCalls();
await first.click();
await modal.getByLabel('Notes:', { exact: true }).waitFor();
assert.equal(detailCalls(), before);
await modal.getByRole('button', { name: 'Close', exact: true }).click();
await page.getByRole('button', { name: 'Open bulk actions menu' }).first().click();
await page.getByRole('button', { name: 'Mark box as In HOME', exact: true }).click();
await page.waitForResponse(
(r) =>
r.url().endsWith(`/pokedexes/${dex.id}/catch-records`) && r.request().method() === 'POST'
);
const after = await readJson(`/api/pokedexes/${dex.id}/entries/${entryId}`);
assert.equal(after.catchRecord.personalNotes, notes.catchRecord.personalNotes);
assert.equal(after.catchRecord.inHome, true);
// Focus navigation must reach entries that were not initially mounted.
await page.locator('[data-entry-index="29"]').focus();
for (let index = 0; index < 22; index++) await page.keyboard.press('ArrowDown');
assert.equal(
await page.evaluate(() => document.activeElement?.getAttribute('data-entry-index')),
'161'
);
await page.getByLabel('Render all boxes').check();
const grid = await readJson(`/api/pokedexes/${dex.id}/grid`);
assert.equal(await page.locator('[data-entry-index]').count(), grid.grid.length);
await page.getByLabel('Render all boxes').uncheck();
results.push({
fixture: dex.gameScope ? 'scoped-forms' : 'national',
...stats,
documentBytes: Buffer.byteLength(html),
gridBytes: Buffer.byteLength(JSON.stringify(grid))
});
}
assert.deepEqual(errors, [], 'Browser errors');
await writeFile(`${directory}/verification.json`, JSON.stringify(results, null, 2));
console.log(JSON.stringify(results, null, 2));
} finally {
await browser.close();
}
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env node
import { spawnSync } from 'node:child_process';
const [, , command, ...args] = process.argv;
if (!command) {
console.error('Usage: node scripts/run-with-local-supabase.mjs <command> [...args]');
process.exit(2);
}
const SETUP_HINT = 'Run "npm run supabase:start" followed by "npm run supabase:reset".';
// npx is a shell script on Windows, where spawn needs a shell to find it.
const useShell = process.platform === 'win32';
function fail(message, detail) {
console.error(message);
if (detail) console.error(String(detail).trim());
process.exit(1);
}
const status = spawnSync('npx', ['supabase', 'status', '--output', 'json'], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
shell: useShell
});
if (status.error) {
fail(
'Unable to run "npx supabase status" - is the supabase CLI installed?',
status.error.message
);
}
if (status.status !== 0) {
const stderr = status.stderr ?? '';
// Distinguish a stopped stack from a genuinely broken CLI invocation, so the hint is only
// printed when it is actually the advice the reader needs.
if (/not running|supabase start/i.test(stderr)) {
fail(`Local Supabase is required but is not running.\n${SETUP_HINT}`, stderr);
}
fail(`"supabase status" failed with exit code ${status.status}.`, stderr);
}
let values;
try {
values = JSON.parse(status.stdout);
} catch (error) {
fail('Unable to parse "supabase status --output json".', error);
}
const apiUrl = values.API_URL ?? values.api_url ?? 'http://127.0.0.1:54321';
const anonKey = values.ANON_KEY ?? values.PUBLISHABLE_KEY ?? values.anon_key;
const serviceRoleKey = values.SERVICE_ROLE_KEY ?? values.SECRET_KEY ?? values.service_role_key;
if (!anonKey || !serviceRoleKey) {
fail(`Supabase status did not return an anonymous and service-role key.\n${SETUP_HINT}`);
}
function isLoopbackUrl(value) {
try {
return ['127.0.0.1', 'localhost', '[::1]'].includes(new URL(value).hostname);
} catch {
return false;
}
}
if (!isLoopbackUrl(apiUrl)) {
fail(`Refusing to run local-stack tests against non-loopback Supabase URL: ${apiUrl}`);
}
const providerUrlVariables = [
'MOCK_PROVIDER_URL',
'GOOGLE_OAUTH_AUTHORIZE_URL',
'GOOGLE_OAUTH_TOKEN_URL',
'GOOGLE_DRIVE_API_URL',
'GOOGLE_DRIVE_UPLOAD_URL',
'DROPBOX_OAUTH_AUTHORIZE_URL',
'DROPBOX_OAUTH_TOKEN_URL',
'DROPBOX_UPLOAD_URL'
];
for (const name of providerUrlVariables) {
const value = process.env[name];
if (value && !isLoopbackUrl(value)) {
fail(`Refusing to run provider tests with non-loopback ${name}: ${value}`);
}
}
// A running-but-unseeded database is the most common broken state, and it surfaces downstream as
// a confusing assertion failure. Check it here instead.
const probe = await fetch(`${apiUrl}/rest/v1/pokedex_entries?select=id&limit=1`, {
headers: { apikey: anonKey, Authorization: `Bearer ${anonKey}` }
}).catch((error) => {
fail(`Unable to reach the local Supabase REST API at ${apiUrl}.\n${SETUP_HINT}`, error);
});
if (!probe.ok) {
fail(
`The local Supabase database has no readable pokedex_entries (HTTP ${probe.status}).\n${SETUP_HINT}`,
await probe.text()
);
}
if (((await probe.json()) ?? []).length === 0) {
fail(`The local Supabase database is empty - migrations or seeds have not run.\n${SETUP_HINT}`);
}
const child = spawnSync(command, args, {
stdio: 'inherit',
shell: useShell,
env: {
...process.env,
// Never allow an exported production value to redirect a local integration run.
PUBLIC_SUPABASE_URL: apiUrl,
PUBLIC_SUPABASE_ANON_KEY: anonKey,
SUPABASE_SERVICE_ROLE_KEY: serviceRoleKey,
TEST_SUPABASE_URL: apiUrl,
TEST_SUPABASE_ANON_KEY: anonKey,
E2E_SERVICE_ROLE_KEY: serviceRoleKey
}
});
if (child.error) fail(`Unable to run "${command}".`, child.error.message);
// A signalled child reports status === null; exiting 0 there would hide the failure.
process.exit(child.signal ? 1 : child.status ?? 1);
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env node
// Lists every sprite (all forms, shiny and female variants) with its size, so the offline worker can
// save the complete set on request and tell whether anything is still missing.
import path from 'node:path';
import process from 'node:process';
import { readdir, stat, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
export const SPRITE_MANIFEST_NAME = 'manifest.json';
async function walk(dir, files = []) {
for (const entry of await readdir(dir, { withFileTypes: true })) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) await walk(fullPath, files);
else if (entry.isFile() && entry.name.endsWith('.webp')) files.push(fullPath);
}
return files;
}
/** Builds the manifest for `<spritesDir>/home`, with paths relative to that folder. */
export async function buildSpriteManifest(spritesDir) {
const homeDir = path.join(spritesDir, 'home');
const files = await walk(homeDir);
const entries = await Promise.all(
files.map(async (file) => [
path.relative(homeDir, file).split(path.sep).join('/'),
(await stat(file)).size
])
);
entries.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
return { version: 1, files: entries };
}
export async function writeSpriteManifest(spritesDir) {
const manifest = await buildSpriteManifest(spritesDir);
await writeFile(path.join(spritesDir, SPRITE_MANIFEST_NAME), `${JSON.stringify(manifest)}\n`);
return manifest;
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const spritesDir =
process.env.SPRITE_OUTPUT_DIR ?? path.join(process.cwd(), 'static', 'sprites-small');
const manifest = await writeSpriteManifest(spritesDir);
const bytes = manifest.files.reduce((total, [, size]) => total + size, 0);
console.log(
`Wrote ${manifest.files.length} sprites (${(bytes / 1048576).toFixed(1)} MB) to ${SPRITE_MANIFEST_NAME}`
);
}
+3
View File
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+7 -1
View File
@@ -1,6 +1,7 @@
import 'vite-plugin-pwa/svelte';
import 'vite-plugin-pwa/info';
import 'vite-plugin-pwa/pwa-assets';
import { SupabaseClient, Session, User } from '@supabase/supabase-js';
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
@@ -11,12 +12,17 @@ declare global {
namespace App {
// interface Error {}
interface Locals {
supabase: SupabaseClient;
pokedexAuthMs?: number;
safeGetSession(): Promise<{ session: Session | null; user: User | null }>;
userid: string;
buildDate: string;
periodicUpdates: boolean;
}
// interface PageData {}
interface PageData {
session: Session | null;
}
// interface PageState {}
// interface Platform {}
}
+14 -2
View File
@@ -1,11 +1,23 @@
<!doctype html>
<html lang="en" data-theme="pokeball">
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
(function () {
try {
const storedTheme = localStorage.getItem('theme');
const allowed = ['pokeball', 'dark'];
const theme = storedTheme && allowed.includes(storedTheme) ? storedTheme : 'pokeball';
document.documentElement.setAttribute('data-theme', theme);
} catch (e) {
// Fallback to default theme if localStorage is not accessible
document.documentElement.setAttribute('data-theme', 'pokeball');
}
})();
</script>
%sveltekit.head%
<link rel="stylesheet" href="%sveltekit.assets%/output.css" />
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
+21 -12
View File
@@ -1,22 +1,21 @@
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
import { createServerClient } from '@supabase/ssr';
import type { Handle } from '@sveltejs/kit';
import { compressResponse } from '$lib/server/compression';
export const handle: Handle = async ({ event, resolve }) => {
event.locals.supabase = createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
cookies: {
get: (key) => event.cookies.get(key),
getAll: () => event.cookies.getAll(),
/**
* Note: You have to add the `path` variable to the
* set and remove method due to sveltekit's cookie API
* requiring this to be set, setting the path to an empty string
* will replicate previous/standard behaviour (https://kit.svelte.dev/docs/types#public-types-cookies)
* Note: You have to add the `path` variable to the set method due to sveltekit's cookie
* API requiring this to be set, setting the path to '/' will replicate previous/standard
* behaviour (https://kit.svelte.dev/docs/types#public-types-cookies)
*/
set: (key, value, options) => {
event.cookies.set(key, value, { ...options, path: '/' });
},
remove: (key, options) => {
event.cookies.delete(key, { ...options, path: '/' });
setAll: (cookiesToSet) => {
cookiesToSet.forEach(({ name, value, options }) => {
event.cookies.set(name, value, { ...options, path: '/' });
});
}
}
});
@@ -26,24 +25,34 @@ export const handle: Handle = async ({ event, resolve }) => {
* doesn't validate the JWT, this function validates the JWT by first calling
* `getUser` and aborts early if the JWT signature is invalid.
*/
event.locals.safeGetSession = async () => {
// getUser is a network round trip to Supabase Auth. Layout and page loads (and API routes) all
// ask for the session, so validate once per request and share the result.
let sessionPromise: ReturnType<App.Locals['safeGetSession']> | null = null;
event.locals.safeGetSession = () => {
sessionPromise ??= (async () => {
const authStarted = performance.now();
const {
data: { user },
error
} = await event.locals.supabase.auth.getUser();
if (error) {
event.locals.pokedexAuthMs = performance.now() - authStarted;
return { session: null, user: null };
}
const {
data: { session }
} = await event.locals.supabase.auth.getSession();
event.locals.pokedexAuthMs = performance.now() - authStarted;
return { session, user };
})();
return sessionPromise;
};
return resolve(event, {
const response = await resolve(event, {
filterSerializedResponseHeaders(name) {
return name === 'content-range';
}
});
return compressResponse(event.request, response);
};
+106
View File
@@ -0,0 +1,106 @@
type InViewParams = {
rootMargin?: string;
threshold?: number | number[];
once?: boolean;
enabled?: boolean;
onChange?: (inView: boolean, entry: IntersectionObserverEntry) => void;
};
const observers = new Map<string, IntersectionObserver>();
const callbacks = new WeakMap<Element, (entry: IntersectionObserverEntry) => void>();
function normalizeThreshold(threshold: number | number[] | undefined) {
if (threshold === undefined) return [0];
return Array.isArray(threshold) ? threshold : [threshold];
}
function buildObserverKey(rootMargin: string, threshold: number | number[]) {
return `${rootMargin}|${JSON.stringify(normalizeThreshold(threshold))}`;
}
function getObserver(rootMargin: string, threshold: number | number[]) {
const key = buildObserverKey(rootMargin, threshold);
const existing = observers.get(key);
if (existing) return existing;
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
const callback = callbacks.get(entry.target);
if (callback) {
callback(entry);
}
}
},
{ rootMargin, threshold }
);
observers.set(key, observer);
return observer;
}
export function inView(node: Element, params: InViewParams = {}) {
let options: Required<InViewParams> = {
rootMargin: '200px 0px',
threshold: 0,
once: true,
enabled: true,
onChange: () => undefined,
...params
};
let observer = getObserver(options.rootMargin, options.threshold);
const handleEntry = (entry: IntersectionObserverEntry) => {
const isIntersecting = entry.isIntersecting || entry.intersectionRatio > 0;
options.onChange(isIntersecting, entry);
if (isIntersecting && options.once) {
observer.unobserve(node);
callbacks.delete(node);
}
};
const startObserving = () => {
callbacks.set(node, handleEntry);
observer.observe(node);
};
const stopObserving = () => {
observer.unobserve(node);
callbacks.delete(node);
};
if (options.enabled) {
startObserving();
}
return {
update(next: InViewParams = {}) {
const nextOptions: Required<InViewParams> = {
...options,
...next,
onChange: next.onChange ?? options.onChange
};
const observerKeyChanged =
buildObserverKey(options.rootMargin, options.threshold) !==
buildObserverKey(nextOptions.rootMargin, nextOptions.threshold);
const enabledChanged = options.enabled !== nextOptions.enabled;
if (observerKeyChanged || enabledChanged) {
stopObserving();
}
options = nextOptions;
if (observerKeyChanged) {
observer = getObserver(options.rootMargin, options.threshold);
}
if (options.enabled) {
startObserving();
}
},
destroy() {
stopObserving();
}
};
}
+2 -2
View File
@@ -11,8 +11,8 @@
currentPage = Math.max(currentPage - 1, 1);
}
function setItemsPerPage(event: any) {
itemsPerPage = parseInt(event.target.value, 10);
function setItemsPerPage(event: Event) {
itemsPerPage = parseInt((event.target as HTMLSelectElement).value, 10);
}
</script>
+73 -79
View File
@@ -1,100 +1,94 @@
<script lang="ts">
import { onMount } from 'svelte';
import pokeApiPokemon from '$lib/helpers/pokeapi-pokemon.json';
import { PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER } from '$env/static/public';
import { inView } from '$lib/actions/inView';
import { resolveSpriteUrl, resolveGridSpriteUrl } from '$lib/utils/spriteUrl';
export let variant: 'detail' | 'grid' = 'detail';
let failedPaths = new Set<string>();
let fallbackIndex = 0;
let candidates: string[] = [];
$: {
const entry = { pokedexNumber: Number(pokedexNumber), form, spriteKey };
const full = resolveSpriteUrl(
entry,
!!shiny,
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER === 'true'
);
candidates = [
...new Set([
...(variant === 'grid' ? [resolveGridSpriteUrl(entry, !!shiny)] : []),
full,
resolveSpriteUrl(
{ ...entry, form: form?.replace(/^female[-\s]*/i, '') },
!!shiny,
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER === 'true'
),
resolveSpriteUrl(
{ pokedexNumber: Number(pokedexNumber) },
!!shiny,
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER === 'true'
)
])
];
fallbackIndex = candidates.findIndex((url) => !failedPaths.has(url));
}
function imageFailed() {
failedPaths = new Set([...failedPaths, imagePath!]);
}
export let pokemonName: string;
export let pokedexNumber: string | number;
export let form: string | undefined;
export let spriteKey: string | undefined;
export let shiny: boolean | undefined = false;
export let loadingStrategy: 'eager' | 'lazy' | 'inView' = 'inView';
let imagePath = null as string | null;
let blah = '';
let isInView = false;
function setImagePath() {
let rootFolder =
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER === 'true'
? '/sprites/home'
: 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/home';
if (form === 'Female') {
rootFolder += '/female';
$: {
if (!spriteKey?.trim()) {
console.warn('Missing sprite key for pokemon entry', {
pokemonName,
pokedexNumber,
form
});
}
}
if (shiny) {
rootFolder += '/shiny';
$: imagePath = candidates[fallbackIndex] ?? null;
$: if (loadingStrategy !== 'inView') {
isInView = true;
}
// Remove leading zeros
const strippedPokedexNumber = pokedexNumber.toString().replace(/^0+/, '');
// Sanitise the pokemon name by making it all lowercase and replacing any spaces with hyphens and removing other characters
let sanitisedPokemonName = pokemonName.toLowerCase().replace(/[^a-z]/g, '');
// Get the PokeApi id for the pokemon
let pokeApiId;
if (form && form.length > 0 && form !== 'Female') {
// Sanitise the form by making it all lowercase and replacing spaces with hyphens
let sanitisedForm = form
.toLowerCase()
.replaceAll(' ', '-')
.replaceAll('2', 'two')
.replaceAll('3', 'three')
.replaceAll('4', 'four');
switch (sanitisedForm) {
case 'alolan':
sanitisedForm = 'alola';
break;
case 'galarian':
sanitisedForm = 'galar';
break;
case 'hisuian':
sanitisedForm = 'hisui';
break;
// case 'rainbow-ribbon':
// sanitisedForm = 'rainbow-swirl-ribbon-sweet';
// break;
default:
break;
function handleInView(inView: boolean) {
if (inView) {
isInView = true;
}
// if (strippedPokedexNumber == '869') {
// console.log(sanitisedPokemonName, sanitisedForm);
// }
// If the form is contained in the identifier, use that
if (
pokeApiPokemon.find(
(pokemon) => pokemon.identifier === sanitisedPokemonName + '-' + sanitisedForm
)
) {
pokeApiId = pokeApiPokemon.find(
(pokemon) => pokemon.identifier === sanitisedPokemonName + '-' + sanitisedForm
)?.id;
} else {
// If the form is not contained in the identifier, use the species_id
pokeApiId = pokeApiPokemon.find(
(pokemon) => pokemon.species_id.toString() === strippedPokedexNumber
)?.id;
}
} else {
pokeApiId = pokeApiPokemon.find(
(pokemon) => pokemon.species_id.toString() === strippedPokedexNumber
)?.id;
}
imagePath = `${rootFolder}/${pokeApiId}.png`;
blah = `${pokeApiId}.png`;
// blah = `${strippedPokedexNumber}${form?.length && form !== 'Female' ? '-' + form : ''}.png`;
}
onMount(setImagePath);
</script>
{#if imagePath}
<!-- {blah} -->
<img src={imagePath} alt="sprite" />
<span
use:inView={{
enabled: loadingStrategy === 'inView',
once: true,
rootMargin: '200px 0px',
onChange: handleInView
}}
>
{#if loadingStrategy === 'inView' && !isInView}
<span class="inline-block w-full h-full" aria-hidden="true"></span>
{:else}
<span class="loading loading-spinner loading-xs"></span>
<img
src={imagePath}
alt=""
on:error={imageFailed}
loading={loadingStrategy === 'lazy' ? 'lazy' : 'eager'}
decoding="async"
/>
{/if}
</span>
{:else}
<span class="inline-block w-full h-full" aria-hidden="true"></span>
{/if}
+117 -24
View File
@@ -1,4 +1,5 @@
<script lang="ts">
import type { SupabaseClient } from '@supabase/supabase-js';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
@@ -8,49 +9,141 @@
let email = '';
let password = '';
let isLoading = false;
let errorMessage = '';
// Access the supabase client from the layout data
export let supabase: any;
export let supabase: SupabaseClient;
async function signInWithEmail() {
// TODO use the data and error from the response
const { data, error } = await supabase.auth
.signInWithPassword({
isLoading = true;
errorMessage = '';
try {
const { data, error } = await supabase.auth.signInWithPassword({
email: email,
password: password
})
.then(() => {
emitSignedInEvent();
});
if (error) {
console.error('Sign in error:', error);
errorMessage = error.message;
return;
}
if (data) {
emitSignedInEvent();
}
} catch (err) {
console.error('Sign in error:', err);
errorMessage = 'An unexpected error occurred. Please try again.';
} finally {
isLoading = false;
}
}
function handleKeyPress(event: KeyboardEvent) {
if (event.key === 'Enter') {
signInWithEmail();
}
}
</script>
<label class="input input-bordered flex items-center gap-2">
<div class="space-y-4">
<!-- Error Message -->
{#if errorMessage}
<div class="alert alert-error text-sm">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4 opacity-70"
><path
d="M2.5 3A1.5 1.5 0 0 0 1 4.5v.793c.026.009.051.02.076.032L7.674 8.51c.206.1.446.1.652 0l6.598-3.185A.755.755 0 0 1 15 5.293V4.5A1.5 1.5 0 0 0 13.5 3h-11Z"
/><path
d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z"
/></svg
class="h-5 w-5 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<input type="text" class="grow" placeholder="Email" bind:value={email} />
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{errorMessage}</span>
</div>
{/if}
<!-- Email Input -->
<div class="form-control">
<label class="label" for="signin-email">
<span class="label-text font-medium">Email</span>
</label>
<label class="input input-bordered flex items-center gap-2">
<div class="relative">
<input
id="signin-email"
type="email"
placeholder="your@email.com"
class="input input-bordered w-full pl-10"
bind:value={email}
on:keypress={handleKeyPress}
disabled={isLoading}
/>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4 opacity-70"
><path
class="h-4 w-4 opacity-70 absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none"
>
<path
d="M2.5 3A1.5 1.5 0 0 0 1 4.5v.793c.026.009.051.02.076.032L7.674 8.51c.206.1.446.1.652 0l6.598-3.185A.755.755 0 0 1 15 5.293V4.5A1.5 1.5 0 0 0 13.5 3h-11Z"
/>
<path
d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z"
/>
</svg>
</div>
</div>
<!-- Password Input -->
<div class="form-control">
<label class="label" for="signin-password">
<span class="label-text font-medium">Password</span>
</label>
<div class="relative">
<input
id="signin-password"
type="password"
placeholder="••••••••"
class="input input-bordered w-full pl-10"
bind:value={password}
on:keypress={handleKeyPress}
disabled={isLoading}
/>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="h-4 w-4 opacity-70 absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none"
>
<path
fill-rule="evenodd"
d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2.293a.5.5 0 0 1 .146-.353l3.955-3.955A4 4 0 1 1 14 6Zm-4-2a.75.75 0 0 0 0 1.5.5.5 0 0 1 .5.5.75.75 0 0 0 1.5 0 2 2 0 0 0-2-2Z"
clip-rule="evenodd"
/></svg
/>
</svg>
</div>
</div>
<!-- Sign In Button -->
<div class="form-control mt-6">
<button
class="btn btn-primary w-full"
on:click={signInWithEmail}
disabled={isLoading || !email || !password}
>
<input type="password" class="grow" placeholder="Password" bind:value={password} />
</label>
<button class="btn btn-active btn-primary" on:click={signInWithEmail}>Sign In</button>
{#if isLoading}
<span class="loading loading-spinner loading-sm"></span>
Signing in...
{:else}
Sign In
{/if}
</button>
</div>
</div>
+31 -5
View File
@@ -1,20 +1,46 @@
<script lang="ts">
import type { SupabaseClient } from '@supabase/supabase-js';
import { createEventDispatcher } from 'svelte';
import { goto } from '$app/navigation';
import { clearOfflineData } from '$lib/stores/offlineSync';
const dispatch = createEventDispatcher();
let errorMessage = '';
let isSigningOut = false;
function emitSignedOutEvent() {
dispatch('signedOut', {});
}
// Access the supabase client from the layout data
export let supabase: any;
export let supabase: SupabaseClient;
async function signOut() {
// TODO use the error from the response
const { error } = await supabase.auth.signOut().then(() => {
errorMessage = '';
isSigningOut = true;
try {
const { error } = await supabase.auth.signOut();
if (error) {
errorMessage = `Sign out failed: ${error.message || 'Please try again.'}`;
dispatch('signOutFailed', { message: errorMessage });
return;
}
try {
await clearOfflineData();
} catch (cacheError) {
console.error('Signed out, but failed to clear offline data', cacheError);
}
emitSignedOutEvent();
});
await goto('/', { invalidateAll: true });
} catch (error) {
console.error('Sign out failed', error);
errorMessage = 'Sign out failed. Please try again.';
dispatch('signOutFailed', { message: errorMessage });
} finally {
isSigningOut = false;
}
}
</script>
<button on:click={signOut}>Sign Out</button>
<button on:click={signOut} disabled={isSigningOut}>
{isSigningOut ? 'Signing Out…' : 'Sign Out'}
</button>
+30 -14
View File
@@ -1,39 +1,48 @@
<script lang="ts">
import type { SupabaseClient } from '@supabase/supabase-js';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
let email = '';
let password = '';
// Access the supabase client from the layout data
export let supabase: any;
export let supabase: SupabaseClient;
async function signUpNewUser() {
try {
// `redirectTo` is not a signUp option - it was silently ignored, so the confirmation
// link has always used Supabase's configured site URL. Sending the user to /welcome
// would need `emailRedirectTo` with an absolute, allow-listed URL.
const { data, error } = await supabase.auth.signUp({
email: email,
password: password,
options: {
// Redirect URL after successful sign-up
redirectTo: '/welcome'
}
password: password
});
if (error) {
throw error;
console.error('Sign up error:', error);
alert(`Sign up failed: ${error.message}`);
return;
}
// Handle success (optional)
} catch (error) {
console.error('Sign up error:', error.message);
// Handle error
if (data) {
// Emit signedUp event to notify parent component
dispatch('signedUp', {});
}
} catch (err) {
console.error('Sign up error:', err);
alert('Sign up failed');
}
}
</script>
<form class="card-body">
<div class="form-control">
<label class="label">
<label class="label" for="signup-email">
<span class="label-text">Email</span>
</label>
<input
id="signup-email"
type="email"
placeholder="email"
class="input input-bordered"
@@ -42,10 +51,11 @@
/>
</div>
<div class="form-control">
<label class="label">
<label class="label" for="signup-password">
<span class="label-text">Password</span>
</label>
<input
id="signup-password"
type="password"
placeholder="password"
class="input input-bordered"
@@ -54,6 +64,12 @@
/>
</div>
<div class="form-control mt-6">
<button class="btn btn btn-primary" on:click={signUpNewUser}>Sign Up</button>
<button class="btn btn-primary" on:click={signUpNewUser}>Sign Up</button>
</div>
</form>
<style>
.card-body {
padding: 0.5rem;
}
</style>
+59
View File
@@ -0,0 +1,59 @@
<script lang="ts">
import { theme, applyTheme } from '$lib/stores/theme.js';
import { onMount } from 'svelte';
let currentTheme: 'pokeball' | 'dark' = 'pokeball';
// Subscribe to theme changes
$: (currentTheme = $theme), applyTheme($theme);
onMount(() => {
// Initialize theme from localStorage
theme.init();
});
function toggleTheme() {
theme.toggle();
}
</script>
<button
class="btn btn-ghost btn-circle"
on:click={toggleTheme}
aria-label="Toggle dark mode"
title="Toggle dark mode"
>
{#if currentTheme === 'pokeball'}
<!-- Sun icon for light mode (clicking will switch to dark) -->
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
{:else}
<!-- Moon icon for dark mode (clicking will switch to light) -->
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
/>
</svg>
{/if}
</button>
+5 -3
View File
@@ -7,14 +7,16 @@
</script>
<div class="relative inline-block">
<div
class="tooltip-trigger cursor-pointer"
<button
type="button"
class="tooltip-trigger cursor-pointer bg-transparent border-0 p-0 appearance-none"
aria-expanded={show}
on:click={handleClick}
on:mouseenter={() => (show = true)}
on:mouseleave={() => (show = false)}
>
<slot name="hover-target" />
</div>
</button>
{#if show}
<div class="tooltip-content absolute z-10 mt-2 w-52">
@@ -0,0 +1,57 @@
<script lang="ts">
import type { Pokedex } from '$lib/models/Pokedex';
export let pokedex: Pokedex;
export let onEdit: () => void;
export let onDelete: () => void;
export let onView: () => void;
// Get active type badges
$: typeBadges = [
pokedex.isLivingDex && 'Living',
pokedex.isShinyDex && 'Shiny',
pokedex.isOriginDex && 'Origin',
pokedex.isFormDex && 'Form'
].filter(Boolean);
</script>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">
{pokedex.name}
</h2>
{#if pokedex.description}
<p class="text-sm">{pokedex.description}</p>
{/if}
<div class="flex flex-wrap gap-2 my-2">
{#each typeBadges as badge}
<span class="badge badge-primary">{badge}</span>
{/each}
</div>
{#if pokedex.gameScope}
<div class="text-sm text-base-content/70">
<span class="font-semibold">Game:</span>
{pokedex.gameScope}
</div>
{#if pokedex.dexScopes?.length}
<div class="text-sm text-base-content/70">
<span class="font-semibold">Dexes:</span>
{pokedex.dexScopes.length}
</div>
{/if}
{:else}
<div class="text-sm text-base-content/70">
<span class="font-semibold">Scope:</span> All Games
</div>
{/if}
<div class="card-actions justify-end mt-4">
<button class="btn btn-sm btn-ghost" on:click={onEdit}>Edit</button>
<button class="btn btn-sm btn-error btn-outline" on:click={onDelete}>Delete</button>
<button class="btn btn-sm btn-primary" on:click={onView}>View</button>
</div>
</div>
</div>
@@ -1,19 +1,72 @@
<script lang="ts">
import type { CatchRecord } from '$lib/models/CatchRecord';
import type { PokedexEntry } from '$lib/models/PokedexEntry';
import type { SharedCatchStatus } from '$lib/models/SharedPokedex';
import type { CatchInformationItem, PokedexEntry } from '$lib/models/PokedexEntry';
import PokemonSprite from '../PokemonSprite.svelte';
import { createEventDispatcher } from 'svelte';
export let pokedexEntry: PokedexEntry;
export let catchRecord: CatchRecord;
export let catchRecord: CatchRecord | null;
export let showOrigins: boolean;
export let showForms: boolean;
export let showShiny: boolean;
export let userId: string | null = null;
export let pokedexId: string;
export let readOnly = false;
export let sharedCatchStatus: SharedCatchStatus | null = null;
// Create a default catch record if none exists
$: if (!readOnly && !catchRecord) {
catchRecord = {
_id: '', // Empty string, not temp ID - will be created by server
userId: userId || '',
pokemonId: pokedexEntry._id,
pokedexId: pokedexId,
haveToEvolve: false,
caught: false,
inHome: false,
hasGigantamaxed: false,
personalNotes: ''
};
}
const dispatch = createEventDispatcher();
function updateCatchRecord() {
dispatch('updateCatch', { pokedexEntry, catchRecord });
type UpdateCatchSource = 'toggle' | 'notes' | 'notes-blur';
const isCatchInformationItem = (
value: string | CatchInformationItem
): value is CatchInformationItem => typeof value !== 'string';
function updateCatchRecord(source: UpdateCatchSource, changes?: Partial<CatchRecord>) {
if (readOnly) return;
dispatch('updateCatch', { pokedexEntry, catchRecord, source, changes });
}
function onCaughtChange() {
if (readOnly) return;
if (!catchRecord) return;
// Mutually exclusive with "needs to evolve"
if (catchRecord.caught) {
catchRecord.haveToEvolve = false;
}
updateCatchRecord('toggle', {
caught: catchRecord.caught,
haveToEvolve: catchRecord.haveToEvolve
});
}
function onNeedsToEvolveChange() {
if (readOnly) return;
if (!catchRecord) return;
// Mutually exclusive with "caught"
if (catchRecord.haveToEvolve) {
catchRecord.caught = false;
}
updateCatchRecord('toggle', {
caught: catchRecord.caught,
haveToEvolve: catchRecord.haveToEvolve
});
}
</script>
@@ -22,53 +75,57 @@
>
<div class="dex-column pokedex-entry-container">
<div class="flex mb-2">
<div class="sprite-container flex justify-center items-center bg-white rounded-lg p-2">
<div class="pl-2">
<h3 class="text-xl font-bold pt-1">{pokedexEntry.pokemon}</h3>
<sub class="text-primary-content/80"
>#{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</sub
>
</div>
</div>
<div class="flex mb-2">
<div class="sprite-container flex justify-center items-center bg-base-100 rounded-lg p-2">
<PokemonSprite
pokemonName={pokedexEntry.pokemon}
pokedexNumber={pokedexEntry.pokedexNumber}
form={pokedexEntry.form}
spriteKey={pokedexEntry.spriteKey}
shiny={showShiny}
/>
</div>
<div class="pl-2">
<h3 class="text-xl font-bold pt-1 text-secondary">{pokedexEntry.pokemon}</h3>
<sub class="text-gray-200">#{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</sub>
</div>
</div>
{#if showForms}
<div class="bg-white text-black rounded-lg p-4 mb-2">
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
<p><strong>Form:</strong> {pokedexEntry.form ? pokedexEntry.form : '-'}</p>
</div>
{/if}
<div class="bg-white text-black rounded-lg p-4">
{#if showForms}
<p><strong>Box:</strong> {pokedexEntry.boxPlacementForms.box}</p>
<p><strong>Row:</strong> {pokedexEntry.boxPlacementForms.row}</p>
<p><strong>Column:</strong> {pokedexEntry.boxPlacementForms.column}</p>
<p><strong>Can Gigantamax:</strong> {pokedexEntry.canGigantamax ? 'Yes' : 'No'}</p>
{:else}
<p><strong>Box:</strong> {pokedexEntry.boxPlacement.box}</p>
<p><strong>Row:</strong> {pokedexEntry.boxPlacement.row}</p>
<p><strong>Column:</strong> {pokedexEntry.boxPlacement.column}</p>
{/if}
{#if pokedexEntry.evolutionInformation}
{#if pokedexEntry.evolutionInformation.trim().length > 0}
<div class="bg-base-100 text-base-content rounded-lg p-4">
<p><strong>How to evolve: </strong>{pokedexEntry.evolutionInformation}</p>
{:else}
<p>
<strong>How to evolve: </strong>Currently missing - can you
<a
href="https://github.com/jcreek/LivingDexTracker"
class="underline text-primary hover:text-secondary">help contribute</a
>?
</p>
</div>
{/if}
</div>
</div>
<div class="dex-column catch-record-container bg-white text-black rounded-lg p-4 mb-4 md:mb-0">
{#if readOnly || catchRecord}
<div
class="dex-column catch-record-container bg-base-100 text-base-content rounded-lg p-4 mb-4 md:mb-0"
>
{#if readOnly}
<h3 class="text-lg font-semibold mb-2">Progress</h3>
<dl class="grid grid-cols-2 gap-x-4 gap-y-2">
<dt>Caught</dt>
<dd class="font-semibold">{sharedCatchStatus?.caught ? 'Yes' : 'No'}</dd>
<dt>Needs to evolve</dt>
<dd class="font-semibold">{sharedCatchStatus?.haveToEvolve ? 'Yes' : 'No'}</dd>
<dt>In HOME</dt>
<dd class="font-semibold">{sharedCatchStatus?.inHome ? 'Yes' : 'No'}</dd>
{#if pokedexEntry.canGigantamax && showForms}
<dt>Has Gigantamaxed</dt>
<dd class="font-semibold">{sharedCatchStatus?.hasGigantamaxed ? 'Yes' : 'No'}</dd>
{/if}
</dl>
{:else if catchRecord}
<div class="flex items-center">
<div class="form-control">
<label class="cursor-pointer label">
@@ -76,8 +133,8 @@
<input
type="checkbox"
bind:checked={catchRecord.caught}
class="checkbox checkbox-primary border-black"
on:change={updateCatchRecord}
class="checkbox checkbox-primary"
on:change={onCaughtChange}
/>
</label>
</div>
@@ -89,8 +146,8 @@
<input
type="checkbox"
bind:checked={catchRecord.haveToEvolve}
class="checkbox checkbox-primary border-black"
on:change={updateCatchRecord}
class="checkbox checkbox-primary"
on:change={onNeedsToEvolveChange}
/>
</label>
</div>
@@ -98,12 +155,12 @@
<div class="flex items-center">
<div class="form-control">
<label class="cursor-pointer label">
<span class="block font-bold mr-2">In home:</span>
<span class="block font-bold mr-2">In Home:</span>
<input
type="checkbox"
bind:checked={catchRecord.inHome}
class="checkbox checkbox-primary border-black"
on:change={updateCatchRecord}
class="checkbox checkbox-primary"
on:change={() => updateCatchRecord('toggle', { inHome: catchRecord?.inHome })}
/>
</label>
</div>
@@ -116,29 +173,35 @@
<input
type="checkbox"
bind:checked={catchRecord.hasGigantamaxed}
class="checkbox checkbox-primary border-black"
on:change={updateCatchRecord}
class="checkbox checkbox-primary"
on:change={() =>
updateCatchRecord('toggle', { hasGigantamaxed: catchRecord?.hasGigantamaxed })}
/>
</label>
</div>
</div>
{/if}
<p>
<label class="block font-bold mb-1" for={`personalNotesInput-${catchRecord._id}`}
>Notes:</label
<label
class="block font-bold mb-1"
for={`personalNotesInput-${catchRecord._id || pokedexEntry._id}`}>Notes:</label
>
<textarea
bind:value={catchRecord.personalNotes}
id={`personalNotesInput-${catchRecord._id}`}
class="form-textarea w-full p-2 border rounded"
on:change={updateCatchRecord}
id={`personalNotesInput-${catchRecord._id || pokedexEntry._id}`}
class="textarea textarea-bordered w-full"
style="min-height: 120px;"
on:input={() => updateCatchRecord('notes')}
on:change={() => updateCatchRecord('notes-blur')}
></textarea>
</p>
{/if}
</div>
{/if}
<div class="dex-column additional-details-container">
{#if showOrigins}
<div class="bg-white text-black rounded-lg p-4 mb-2">
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
<h3 class="text-xl font-semibold mb-4">Origin Dex Requirements</h3>
<p><strong>Region to Catch In:</strong> {pokedexEntry.regionToCatchIn}</p>
<p><strong>Games to catch in:</strong></p>
@@ -153,16 +216,20 @@
</div>
{/if}
{#if pokedexEntry.catchInformation.length > 0}
<div class="bg-white text-black rounded-lg p-4 mb-2">
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
<p><strong>Where to catch: </strong></p>
<ul class="list-disc list-inside">
{#each pokedexEntry.catchInformation as info}
<li>
{#if isCatchInformationItem(info)}
<ul>
<li><strong>Game:</strong> {info.game}</li>
<li><strong>Location:</strong> {info.location}</li>
<li><strong>Notes:</strong> {info.notes}</li>
</ul>
{:else}
{info}
{/if}
</li>
{/each}
</ul>
@@ -175,7 +242,7 @@
</p>
</div>
{:else}
<div class="bg-white text-black rounded-lg p-4 mb-2">
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
<p>
<strong>Where to catch: </strong>Currently missing - can you
<a
@@ -185,39 +252,22 @@
</p>
</div>
{/if}
{#if pokedexEntry.notes}
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
<p><strong>Dex Notes:</strong> {pokedexEntry.notes}</p>
</div>
{/if}
</div>
</div>
<style>
.dex-column {
width: 300px;
flex: 1;
min-width: 250px;
}
.sprite-container {
width: 68px;
height: 68px;
}
.form-checkbox {
appearance: none;
background-color: #fff;
border: 2px solid #000;
border-radius: 0.25rem;
width: 1.5rem;
height: 1.5rem;
display: inline-block;
position: relative;
}
.form-checkbox:checked {
background-color: #00bfff;
background-size: 100% 100%;
background-position: center center;
background-repeat: no-repeat;
}
.form-textarea {
min-height: 3rem;
background-color: #fff;
width: 100%;
aspect-ratio: 1;
}
</style>
@@ -0,0 +1,210 @@
<script lang="ts">
import { onMount } from 'svelte';
import type { Pokedex } from '$lib/models/Pokedex';
export let pokedex: Partial<Pokedex> = {
name: '',
description: '',
isLivingDex: false,
isShinyDex: false,
isOriginDex: false,
isFormDex: false,
gameScope: null,
dexScopes: []
};
export let mode: 'create' | 'edit' = 'create';
export let onSubmit: () => void;
export let onCancel: () => void;
type GameDex = {
id: string;
displayName: string;
sortOrder: number;
isDlc: boolean;
parentDexId: string | null;
};
type GameSummary = {
displayName: string;
releaseYear: number;
};
let gameDexes: Record<string, GameDex[]> = {};
let gameOrder: string[] = [];
let gameList: GameSummary[] = [];
let availableDexes: GameDex[] = [];
let loadingDexes = true;
let lastGameScope: string | null = null;
let dexScopesInitialized = false;
let hasSeenGameScope = false;
// Fetch available game dexes from the database
onMount(async () => {
try {
const response = await fetch('/api/game-dexes');
if (response.ok) {
const data = await response.json();
gameDexes = data.gameDexes || {};
gameOrder = data.gameOrder || Object.keys(gameDexes);
gameList = data.games || [];
} else {
console.error('Failed to fetch game dexes');
}
} catch (error) {
console.error('Error fetching game dexes:', error);
} finally {
loadingDexes = false;
}
});
// Validation
$: hasAtLeastOneType =
pokedex.isLivingDex || pokedex.isShinyDex || pokedex.isOriginDex || pokedex.isFormDex;
$: hasDexScope = !pokedex.gameScope || (pokedex.dexScopes && pokedex.dexScopes.length > 0);
$: canSubmit = pokedex.name && pokedex.name.trim() !== '' && hasAtLeastOneType && hasDexScope;
$: if (pokedex.gameScope !== lastGameScope) {
const shouldResetDexes = mode === 'create' || hasSeenGameScope;
lastGameScope = pokedex.gameScope || null;
dexScopesInitialized = false;
if (shouldResetDexes) {
pokedex.dexScopes = [];
}
if (!pokedex.gameScope) {
availableDexes = [];
}
hasSeenGameScope = true;
}
$: if (!loadingDexes && pokedex.gameScope) {
availableDexes = gameDexes[pokedex.gameScope] || [];
if (!dexScopesInitialized) {
if (!pokedex.dexScopes || pokedex.dexScopes.length === 0) {
pokedex.dexScopes = availableDexes.map((dex) => dex.id);
}
dexScopesInitialized = true;
}
}
function handleSubmit() {
if (canSubmit) {
onSubmit();
}
}
</script>
<div class="form-control w-full">
<label class="label" for="pokedex-name">
<span class="label-text">Name</span>
</label>
<input
id="pokedex-name"
type="text"
placeholder="My Living Dex"
class="input input-bordered w-full"
bind:value={pokedex.name}
required
/>
</div>
<div class="form-control w-full">
<label class="label" for="pokedex-description">
<span class="label-text">Description (optional)</span>
</label>
<textarea
id="pokedex-description"
class="textarea textarea-bordered h-24"
placeholder="Describe your pokédex..."
bind:value={pokedex.description}
></textarea>
</div>
<div class="form-control w-full">
<fieldset class="w-full">
<legend class="label">
<span class="label-text">Type(s)</span>
<span class="label-text-alt text-error"
>{!hasAtLeastOneType ? 'At least one type required' : ''}</span
>
</legend>
<div class="flex flex-col gap-2">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox" class="checkbox" bind:checked={pokedex.isLivingDex} />
<span class="label-text">Living Dex (one of each Pokémon)</span>
</label>
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox" class="checkbox" bind:checked={pokedex.isShinyDex} />
<span class="label-text">Shiny Dex (shiny variants only)</span>
</label>
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox" class="checkbox" bind:checked={pokedex.isOriginDex} />
<span class="label-text">Origin Dex (caught in native regions)</span>
</label>
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox" class="checkbox" bind:checked={pokedex.isFormDex} />
<span class="label-text">Form Dex (all forms included)</span>
</label>
</div>
</fieldset>
</div>
<div class="form-control w-full">
<label class="label" for="game-scope">
<span class="label-text">Game Scope</span>
</label>
<select
id="game-scope"
class="select select-bordered"
bind:value={pokedex.gameScope}
disabled={loadingDexes}
>
<option value={null}>All Games</option>
{#if loadingDexes}
<option disabled>Loading games...</option>
{:else if gameList.length > 0}
{#each gameList as game}
<option value={game.displayName}>{game.displayName}</option>
{/each}
{:else}
{#each gameOrder.length > 0 ? gameOrder : Object.keys(gameDexes) as game}
<option value={game}>{game}</option>
{/each}
{/if}
</select>
</div>
{#if pokedex.gameScope}
<div class="form-control w-full">
<fieldset class="w-full">
<legend class="label">
<span class="label-text">Dex Scope</span>
<span class="label-text-alt text-error"
>{!hasDexScope ? 'Select at least one dex' : ''}</span
>
</legend>
{#if availableDexes.length === 0}
<p class="text-sm text-error">No dexes found for this game.</p>
{:else}
<div class="flex flex-col gap-2">
{#each availableDexes as dex}
<label class="label cursor-pointer justify-start gap-3">
<input
type="checkbox"
class="checkbox"
value={dex.id}
bind:group={pokedex.dexScopes}
/>
<span class="label-text">{dex.displayName}</span>
</label>
{/each}
</div>
{/if}
</fieldset>
</div>
{/if}
<div class="modal-action">
<button class="btn btn-ghost" type="button" on:click={onCancel}>Cancel</button>
<button class="btn btn-primary" type="button" on:click={handleSubmit} disabled={!canSubmit}>
{mode === 'create' ? 'Create' : 'Save'}
</button>
</div>
@@ -0,0 +1,142 @@
<script lang="ts">
import { onMount } from 'svelte';
export let isOpen: boolean;
export let onClose: () => void;
function handleBackdropClick() {
onClose();
}
function handleKeyDown(event: KeyboardEvent) {
if (event.key === 'Escape' && isOpen) {
onClose();
}
}
let dialog: HTMLDivElement;
onMount(() => {
const previous = document.activeElement as HTMLElement | null;
const close = dialog.querySelector<HTMLButtonElement>('.close-button');
close?.focus();
const trapFocus = (event: KeyboardEvent) => {
handleKeyDown(event);
if (event.key !== 'Tab') return;
const nodes = Array.from(
dialog.querySelectorAll<HTMLElement>(
'button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), a[href]'
)
).filter((node) => node.getClientRects().length);
const first = nodes[0],
last = nodes.at(-1);
if (event.shiftKey && document.activeElement === first) {
event.preventDefault();
last?.focus();
} else if (!event.shiftKey && document.activeElement === last) {
event.preventDefault();
first?.focus();
}
};
window.addEventListener('keydown', trapFocus);
return () => {
window.removeEventListener('keydown', trapFocus);
if (previous?.isConnected) previous.focus();
};
});
</script>
{#if isOpen}
<div
bind:this={dialog}
class="modal modal-open"
role="dialog"
aria-label="Pokémon details"
aria-modal="true"
>
<div class="modal-box-custom bg-primary text-primary-content">
<button data-offline-action class="close-button" on:click={onClose} aria-label="Close">
</button>
<div class="modal-content">
<slot />
</div>
</div>
<button
data-offline-action
type="button"
class="modal-backdrop bg-black/50"
aria-label="Close modal"
on:click={handleBackdropClick}
></button>
</div>
{/if}
<style>
.modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
padding: 0;
}
.modal-box-custom {
max-width: 72rem;
width: 100%;
max-height: 90vh;
border: none;
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
outline: none;
position: relative;
border-radius: 1rem;
padding: 0.5rem;
overflow-y: auto;
box-sizing: border-box;
}
.close-button {
position: absolute;
right: 1rem;
top: 1rem;
width: 2.5rem;
height: 2.5rem;
border-radius: 50%;
background-color: rgba(0, 0, 0, 0.3);
color: white;
border: 2px solid rgba(255, 255, 255, 0.3);
font-size: 1.5rem;
font-weight: bold;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
z-index: 10;
line-height: 1;
}
.close-button:hover {
background-color: rgba(0, 0, 0, 0.5);
border-color: rgba(255, 255, 255, 0.5);
transform: scale(1.1);
}
.modal-content {
width: 100%;
}
/* Remove margin and background from card inside modal */
.modal-content :global(.dex-entry) {
margin-bottom: 0;
background-color: transparent !important;
box-shadow: none;
}
@media (min-width: 768px) {
.modal-box-custom {
width: 91.666667%;
}
}
</style>
@@ -1,129 +0,0 @@
<script lang="ts">
import Pagination from '$lib/components/Pagination.svelte';
export let viewAsBoxes = false;
export let currentPage = 1;
export let itemsPerPage = 20;
export let totalPages = 0;
export let showForms = true;
export let showOrigins = true;
export let showShiny = false;
export let catchRegion = '';
export let catchGame = '';
export let toggleForms = () => {};
export let toggleOrigins = () => {};
export let toggleShiny = () => {};
export let getData = () => {};
export let toggleViewAsBoxes = () => {};
</script>
<aside
class="menu bg-gray-800 text-white min-h-full w-64 p-4 lg:fixed xs:top-0 lg:left-0 h-full lg:h-5/6"
>
<h2 class="text-2xl font-semibold mb-4">Views</h2>
<ul>
<li class="mb-2">
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleViewAsBoxes}>
{viewAsBoxes ? 'Switch to List View' : 'Switch to Box View'}
</button>
</li>
</ul>
<h2 class="text-2xl font-semibold mb-4">Filters</h2>
<ul>
<li class="mb-2">
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleForms}>
Toggle Forms (Currently {showForms ? 'On' : 'Off'})
</button>
</li>
<li class="mb-2">
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleOrigins}>
Toggle Origins (Currently {showOrigins ? 'On' : 'Off'})
</button>
</li>
<li class="mb-2">
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleShiny}>
Toggle Shiny (Currently {showShiny ? 'On' : 'Off'})
</button>
</li>
</ul>
<div class="mb-4">
<label for="catchRegionSelect">Region to catch in:</label>
<select
id="catchRegionSelect"
class="select select-bordered w-full max-w-xs text-black"
bind:value={catchRegion}
on:change={getData}
>
<option value="">All</option>
<option value="Kanto">Kanto (Red, Blue, Yellow, LG: Pikachu, LG: Eevee)</option>
<option value="Johto">Johto (Gold, Silver, Crystal, HG, SS)</option>
<option value="Hoenn">Hoenn (Ruby, Sapphire, Emerald, OR, AS)</option>
<option value="Sinnoh">Sinnoh (Diamond, Pearl, Platinum, BD, SP)</option>
<option value="Unova">Unova (Black, White, Black2, White2, Dream Radar)</option>
<option value="Kalos">Kalos (X, Y)</option>
<option value="Alola">Alola (Sun, Moon, Moon Demo, US, UM)</option>
<option value="Galar">Galar (Sword, Shield)</option>
<option value="Hisui">Hisui (PLA)</option>
<option value="Paldea">Paldea (Scarlet, Violet)</option>
<option value="Unknown">Unknown (Home, Go)</option>
</select>
</div>
<div class="mb-4">
<label for="catchGameSelect">Game to catch in: {catchGame}</label>
<select
id="catchGameSelect"
class="select select-bordered w-full max-w-xs text-black"
bind:value={catchGame}
on:change={getData}
>
<option value="">All</option>
<option value="Red">Red (Kanto)</option>
<option value="Blue">Blue (Kanto)</option>
<option value="Yellow">Yellow (Kanto)</option>
<option value="LG: Pikachu">LG: Pikachu (Kanto)</option>
<option value="LG: Eevee">LG: Eevee (Kanto)</option>
<option value="Gold">Gold (Johto)</option>
<option value="Silver">Silver (Johto)</option>
<option value="Crystal">Crystal (Johto)</option>
<option value="HG">HG (Johto)</option>
<option value="SS">SS (Johto)</option>
<option value="Ruby">Ruby (Hoenn)</option>
<option value="Sapphire">Sapphire (Hoenn)</option>
<option value="Emerald">Emerald (Hoenn)</option>
<option value="OR">OR (Hoenn)</option>
<option value="AS">AS (Hoenn)</option>
<option value="Diamond">Diamond (Sinnoh)</option>
<option value="Pearl">Pearl (Sinnoh)</option>
<option value="Platinum">Platinum (Sinnoh)</option>
<option value="BD">BD (Sinnoh)</option>
<option value="SP">SP (Sinnoh)</option>
<option value="Black">Black (Unova)</option>
<option value="White">White (Unova)</option>
<option value="Black2">Black2 (Unova)</option>
<option value="White2">White2 (Unova)</option>
<option value="Dream Radar">Dream Radar (Unova)</option>
<option value="X">X (Kalos)</option>
<option value="Y">Y (Kalos)</option>
<option value="Sun">Sun (Alola)</option>
<option value="Moon">Moon (Alola)</option>
<option value="Moon Demo">Moon Demo (Alola)</option>
<option value="US">US (Alola)</option>
<option value="UM">UM (Alola)</option>
<option value="Sword">Sword (Galar)</option>
<option value="Shield">Shield (Galar)</option>
<option value="PLA">PLA (Hisui)</option>
<option value="Scarlet">Scarlet (Paldea)</option>
<option value="Violet">Violet (Paldea)</option>
<option value="Home">Home (Unknown)</option>
<option value="Go">Go (Unknown)</option>
</select>
</div>
{#if !viewAsBoxes}
<h2 class="text-2xl font-semibold mb-4">Paging</h2>
<div>
<Pagination bind:currentPage bind:itemsPerPage bind:totalPages />
</div>
{/if}
</aside>
@@ -1,118 +1,710 @@
<script lang="ts">
import type { CatchRecord } from '$lib/models/CatchRecord';
import type { CombinedData } from '$lib/models/CombinedData';
import type { PokedexEntry } from '$lib/models/PokedexEntry';
import { onMount, tick } from 'svelte';
import { calculateBoxPlacement } from '$lib/utils/boxPlacement';
import PokemonSprite from '$lib/components/PokemonSprite.svelte';
import Tooltip from '$lib/components/Tooltip.svelte';
import type { SharedCombinedData } from '$lib/models/SharedPokedex';
import type { PokedexGridRow } from '$lib/models/PokedexGridRow';
import { markGridInteractive } from '$lib/utils/criticalPageWork';
export let virtualize = false;
export let retryLoad: (() => void) | null = null;
let renderAll = false;
let visibleBoxes = new Set([1, 2, 3, 4]);
let focusedBox: number | null = null;
let grid: HTMLDivElement;
const shells = new Map<number, HTMLElement>();
let viewportFrame = 0;
let mounted = false;
export let gridKey = '';
let markedKey: string | null = null;
let scrollAnchor: { number: number; top: number } | null = null;
function measureViewport() {
viewportFrame = 0;
const next = new Set<number>();
scrollAnchor = null;
for (const [number, node] of shells) {
const rect = node.getBoundingClientRect();
if (!scrollAnchor && rect.bottom > 0) scrollAnchor = { number, top: rect.top };
const overscan = rect.height + 16;
if (rect.bottom >= -overscan && rect.top <= window.innerHeight + overscan) next.add(number);
}
visibleBoxes = next;
}
function resizeViewport() {
if (scrollAnchor && window.scrollY > 0) {
const node = shells.get(scrollAnchor.number);
if (node) window.scrollBy(0, node.getBoundingClientRect().top - scrollAnchor.top);
}
scheduleViewport();
}
function trackFocus(event: FocusEvent) {
const target = event.target instanceof Element ? event.target : null;
if (!target?.closest('[data-box-number], [role="dialog"]')) focusedBox = null;
}
function scheduleViewport() {
if (!viewportFrame) viewportFrame = requestAnimationFrame(measureViewport);
}
function boxShell(node: HTMLElement, number: number) {
shells.set(number, node);
scheduleViewport();
return {
destroy() {
shells.delete(number);
}
};
}
async function focusEntry(index: number) {
if (!combinedData || index < 0 || index >= combinedData.length) return;
focusedBox = Math.floor(index / 30) + 1;
await tick();
grid.querySelector<HTMLElement>(`[data-entry-index="${index}"]`)?.focus();
}
function navigateEntry(event: KeyboardEvent, index: number) {
const offset = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -6, ArrowDown: 6 }[event.key];
if (offset !== undefined) {
event.preventDefault();
void focusEntry(index + offset);
} else if (event.key === 'Tab') {
const next = index + (event.shiftKey ? -1 : 1);
if (
next >= 0 &&
next < (combinedData?.length ?? 0) &&
!grid.querySelector(`[data-entry-index="${next}"]`)
) {
event.preventDefault();
void focusEntry(next);
}
}
}
$: if (mounted && combinedData && gridKey !== markedKey) {
markedKey = gridKey;
grid?.removeAttribute('data-grid-interactive');
void tick().then(() => {
if (virtualize) markGridInteractive();
});
}
onMount(() => {
mounted = true;
const observer = new ResizeObserver(resizeViewport);
if (grid) observer.observe(grid);
window.addEventListener('scroll', scheduleViewport, { passive: true });
window.addEventListener('resize', resizeViewport);
window.addEventListener('focusin', trackFocus);
measureViewport();
return () => {
observer.disconnect();
cancelAnimationFrame(viewportFrame);
window.removeEventListener('scroll', scheduleViewport);
window.removeEventListener('resize', resizeViewport);
window.removeEventListener('focusin', trackFocus);
};
});
export let showShiny = false;
export let combinedData: CombinedData[] | null;
export let boxNumbers = Array<number>;
export let currentPlacement = 'boxPlacementForms';
type DisplayData = PokedexGridRow | SharedCombinedData;
type DisplayStatus = DisplayData['catchRecord'];
export let combinedData: DisplayData[] | null;
export let readOnly = false;
export let boxNumbers: number[] = [];
export let creatingRecords = false;
export let totalRecordsCreated = 0;
export let failedToLoad = false;
export let markBoxAsNotCaught = (boxNumber: number) => {};
export let markBoxAsCaught = (boxNumber: number) => {};
export let markBoxAsNeedsToEvolve = (boxNumber: number) => {};
export let markBoxAsInHome = (boxNumber: number) => {};
export let markBoxAsNotInHome = (boxNumber: number) => {};
export let markBoxAsNotCaught: (boxNumber: number) => void = () => {};
export let markBoxAsCaught: (boxNumber: number) => void = () => {};
export let markBoxAsNeedsToEvolve: (boxNumber: number) => void = () => {};
export let markBoxAsInHome: (boxNumber: number) => void = () => {};
export let markBoxAsNotInHome: (boxNumber: number) => void = () => {};
export let createCatchRecords = () => {};
export let onPokemonClick: (pokemon: DisplayData) => void = () => {};
function cellBackgroundColourClass(catchRecord: CatchRecord) {
if (catchRecord.caught) {
return 'bg-green-100/50';
} else if (catchRecord.haveToEvolve) {
return 'bg-yellow-100/50';
} else {
return '';
let filterNotCaught = false;
let filterNeedsToEvolve = false;
let filterInHome = false;
let filterNotInHome = false;
// Bulk actions menu state (one open menu at a time)
let openBulkMenuForBox: number | null = null;
onMount(() => {
const close = () => {
openBulkMenuForBox = null;
};
window.addEventListener('click', close);
return () => window.removeEventListener('click', close);
});
let filteredCombinedData: DisplayData[] = [];
let filteredTotal = 0;
let overallTotal = 0;
let overallCaughtCount = 0;
let overallNotCaughtCount = 0;
let overallNeedsToEvolveCount = 0;
let overallInHomeCount = 0;
let overallNotInHomeCount = 0;
let filtersActive = false;
let filtersKey = '';
function normalizedStatus(catchRecord: DisplayStatus) {
return {
caught: !!catchRecord?.caught,
needsToEvolve: !!catchRecord?.haveToEvolve,
inHome: !!catchRecord?.inHome
};
}
function matchesFilters(catchRecord: DisplayStatus) {
const status = normalizedStatus(catchRecord);
if (!filtersActive) return true;
const isCaught = status.caught || status.needsToEvolve;
const isNotCaught = !isCaught;
const isNeedsToEvolve = status.needsToEvolve;
const isInHome = status.inHome;
const isNotInHome = !status.inHome;
// OR within each group, AND between groups.
const progressGroupActive = filterNotCaught || filterNeedsToEvolve;
const homeGroupActive = filterInHome || filterNotInHome;
const progressMatch =
!progressGroupActive ||
(filterNotCaught && isNotCaught) ||
(filterNeedsToEvolve && isNeedsToEvolve);
const homeMatch =
!homeGroupActive || (filterInHome && isInHome) || (filterNotInHome && isNotInHome);
return progressMatch && homeMatch;
}
$: filtersActive = filterNotCaught || filterNeedsToEvolve || filterInHome || filterNotInHome;
$: filtersKey = `${filterNotCaught}-${filterNeedsToEvolve}-${filterInHome}-${filterNotInHome}`;
$: {
// Ensure this recalculates when any filter changes (Svelte doesn't track function internals).
filtersKey;
filteredCombinedData = combinedData
? combinedData.filter(({ catchRecord }) => matchesFilters(catchRecord))
: [];
}
$: filteredTotal = filteredCombinedData.length;
$: overallTotal = combinedData?.length ?? 0;
$: overallCaughtCount = (combinedData ?? []).reduce((acc, { catchRecord }) => {
const status = normalizedStatus(catchRecord);
// Treat "needs to evolve" as a subset of "caught" (it is caught, just not finished).
return acc + (status.caught || status.needsToEvolve ? 1 : 0);
}, 0);
$: overallNotCaughtCount = overallTotal - overallCaughtCount;
$: overallNeedsToEvolveCount = (combinedData ?? []).reduce((acc, { catchRecord }) => {
return acc + (normalizedStatus(catchRecord).needsToEvolve ? 1 : 0);
}, 0);
$: overallInHomeCount = (combinedData ?? []).reduce((acc, { catchRecord }) => {
return acc + (normalizedStatus(catchRecord).inHome ? 1 : 0);
}, 0);
$: overallNotInHomeCount = overallTotal - overallInHomeCount;
const BOX_VIEW_LAYOUT_STORAGE_KEY = 'livingdex:boxViewLayout:v1';
type BoxViewLayout = 'comfortable' | 'compact' | 'ultra';
export let initialLayout: BoxViewLayout = 'comfortable';
let boxViewLayout: BoxViewLayout = initialLayout;
function persistBoxViewLayout(next: BoxViewLayout) {
const anchor = [...shells.entries()].find(
([, node]) => node.getBoundingClientRect().bottom > 0
);
const top = anchor?.[1].getBoundingClientRect().top;
boxViewLayout = next;
document.cookie = `boxViewLayout=${next};path=/;max-age=31536000;SameSite=Lax`;
void tick().then(() => {
if (anchor && top !== undefined && window.scrollY > 0)
window.scrollBy(0, anchor[1].getBoundingClientRect().top - top);
measureViewport();
});
try {
localStorage.setItem(BOX_VIEW_LAYOUT_STORAGE_KEY, next);
} catch {
// ignore
}
}
function cellBackgroundColourStyle(pokedexEntry: PokedexEntry, catchRecord: CatchRecord) {
if (catchRecord.caught || catchRecord.haveToEvolve) {
function onBoxViewLayoutChange(event: Event) {
const next = (event.currentTarget as HTMLSelectElement).value;
if (next === 'comfortable' || next === 'compact' || next === 'ultra') {
persistBoxViewLayout(next);
}
}
$: boxesPerRow = boxViewLayout === 'comfortable' ? 2 : boxViewLayout === 'compact' ? 3 : 4;
$: cellPaddingRem =
boxViewLayout === 'comfortable' ? 1 : boxViewLayout === 'compact' ? 0.6 : 0.45;
$: spriteSizePx = boxViewLayout === 'comfortable' ? 64 : boxViewLayout === 'compact' ? 52 : 44;
function cellStatusClasses(catchRecord: DisplayStatus) {
// Keep borders/layout unchanged; rely on clearer fills + badges instead.
if (catchRecord?.caught) {
// Match legend (green-600) while keeping sprites readable.
return 'bg-green-600/15';
}
if (catchRecord?.haveToEvolve) {
// Match legend (yellow-500) while keeping sprites readable.
return 'bg-yellow-500/20';
}
return '';
}
function statusLabel(catchRecord: DisplayStatus) {
const parts: string[] = [];
if (catchRecord?.caught) parts.push('Caught');
if (catchRecord?.haveToEvolve) parts.push('Needs to evolve');
if (catchRecord?.inHome) parts.push('In HOME');
return parts.length ? parts.join(', ') : 'Not caught';
}
function cellBackgroundColourStyle(index: number, catchRecord: DisplayStatus) {
if (catchRecord?.caught || catchRecord?.haveToEvolve) {
return '';
} else {
if (pokedexEntry[currentPlacement].column % 2 === 0) {
return 'background-color: #ffffff';
const placement = calculateBoxPlacement(index);
if (placement.column % 2 === 0) {
return 'background-color: var(--ld-box-bg-even);';
} else {
return 'background-color: #f9f9f9;';
return 'background-color: var(--ld-box-bg-odd);';
}
}
}
function onInHomeFilterChange(event: Event) {
const checked = (event.currentTarget as HTMLInputElement).checked;
if (checked) filterNotInHome = false;
}
function onNotInHomeFilterChange(event: Event) {
const checked = (event.currentTarget as HTMLInputElement).checked;
if (checked) filterInHome = false;
}
const POKEMON_PER_BOX = 30;
const BOX_POSITIONS = Array.from({ length: POKEMON_PER_BOX }, (_, i) => i);
</script>
<main class="flex-1 p-4 w-full">
<div class="max-w-fit mx-auto">
<div class="max-w-[1440px] w-full mx-auto">
{#if combinedData && combinedData.length > 0}
<div class="container mx-auto">
<div class="flex flex-wrap -mx-2">
{#each boxNumbers as boxNumber}
<div class="mb-8 md:w-1/2 px-2">
<h2 class="text-xl font-bold mb-4">Box {boxNumber}</h2>
<button class="btn" on:click={markBoxAsNotCaught(boxNumber)}>
Mark box as not 'caught'
</button>
<button class="btn" on:click={markBoxAsCaught(boxNumber)}>
Mark box as 'caught'
</button>
<button class="btn" on:click={markBoxAsNeedsToEvolve(boxNumber)}
>Mark box as 'needs to evolve'</button
<div class="card bg-base-100 shadow mb-4">
<div class="card-body p-4 flex flex-col gap-3">
<div class="flex flex-wrap items-center gap-3">
<label class="label p-0" for="box-view-layout">
<span class="label-text font-semibold">Box view layout</span>
</label>
<select
data-offline-action
id="box-view-layout"
class="select select-bordered select-sm"
bind:value={boxViewLayout}
on:change={onBoxViewLayoutChange}
aria-label="Choose box view layout density"
>
<button class="btn" on:click={markBoxAsInHome(boxNumber)}
>Mark box as 'in Home'</button
>
<button class="btn" on:click={markBoxAsNotInHome(boxNumber)}
>Mark box as not 'in Home'</button
>
<div class="grid grid-cols-6">
{#each combinedData as { pokedexEntry, catchRecord }}
{#if pokedexEntry[currentPlacement].box === boxNumber}
<div
class="pokemon-box {cellBackgroundColourClass(catchRecord)}"
style="grid-column-start: {pokedexEntry[currentPlacement]
.column}; grid-row-start: {pokedexEntry[currentPlacement].row};
{cellBackgroundColourStyle(pokedexEntry, catchRecord)}"
>
<Tooltip>
<div slot="hover-target">
{#if catchRecord.inHome}
<span
class="absolute -top-5 -right-4 z-2 p-1 text-secondary text-lg font-extrabold"
>&#10003;</span
<option value="comfortable">Comfortable (2 boxes/row)</option>
<option value="compact">Compact (3 boxes/row)</option>
<option value="ultra">Ultra (4 boxes/row)</option>
</select>
{#if virtualize}
<label class="label cursor-pointer gap-2"
><input
data-offline-action
type="checkbox"
class="checkbox checkbox-sm"
bind:checked={renderAll}
/>Render all boxes</label
>
{/if}
<div class="flex flex-wrap items-center gap-2 text-sm">
<span class="font-semibold">Legend:</span>
<span
class="inline-flex items-center gap-1 rounded-full border border-green-700 bg-green-600 px-2 py-0.5 text-white"
>
<span class="status-badge status-badge--caught" aria-hidden="true">
<svg
class="status-icon"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M5 13l4 4L19 7" />
</svg>
</span>
<span>Caught</span>
</span>
<span
class="inline-flex items-center gap-1 rounded-full border border-yellow-700 bg-yellow-500 px-2 py-0.5 text-white"
>
<span class="status-badge status-badge--evolve" aria-hidden="true">
<svg
class="status-icon"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 19V5" />
<path d="M5 12l7-7 7 7" />
</svg>
</span>
<span>Caught but needs to evolve</span>
</span>
<span
class="inline-flex items-center gap-1 rounded-full border border-sky-700 bg-sky-600 px-2 py-0.5 text-white"
>
<span class="status-badge status-badge--home" aria-hidden="true">
<svg
class="status-icon"
viewBox="0 0 24 24"
fill="#ffffff"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 3 3 10.5V21a1 1 0 0 0 1 1h5v-6h6v6h5a1 1 0 0 0 1-1V10.5L12 3Z" />
</svg>
</span>
<span>In Home</span>
</span>
</div>
</div>
<div class="flex flex-col gap-3">
<div class="flex flex-wrap items-center gap-4">
<span class="font-semibold">Filters:</span>
<label class="label cursor-pointer gap-2 p-0">
<input
data-offline-action
type="checkbox"
class="checkbox checkbox-sm"
bind:checked={filterNotCaught}
/>
<span class="label-text">Not caught</span>
</label>
<label class="label cursor-pointer gap-2 p-0">
<input
data-offline-action
type="checkbox"
class="checkbox checkbox-sm"
bind:checked={filterNeedsToEvolve}
/>
<span class="label-text">Needs to evolve</span>
</label>
<label class="label cursor-pointer gap-2 p-0">
<input
data-offline-action
type="checkbox"
class="checkbox checkbox-sm"
bind:checked={filterInHome}
on:change={onInHomeFilterChange}
/>
<span class="label-text">In HOME</span>
</label>
<label class="label cursor-pointer gap-2 p-0">
<input
data-offline-action
type="checkbox"
class="checkbox checkbox-sm"
bind:checked={filterNotInHome}
on:change={onNotInHomeFilterChange}
/>
<span class="label-text">Not in HOME</span>
</label>
</div>
<div
class="flex flex-wrap items-center justify-between gap-2 rounded-box bg-base-200/60 px-3 py-2"
>
<div class="text-sm text-base-content/70">
<span class="font-semibold text-base-content">Caught</span>
{overallCaughtCount}
<span class="mx-2"></span>
<span class="font-semibold text-base-content">Not caught</span>
{overallNotCaughtCount}
<span class="mx-2"></span>
<span class="font-semibold text-base-content">Needs to evolve</span>
{overallNeedsToEvolveCount}
<span class="mx-2"></span>
<span class="font-semibold text-base-content">In HOME</span>
{overallInHomeCount}
<span class="mx-2"></span>
<span class="font-semibold text-base-content">Not in HOME</span>
{overallNotInHomeCount}
</div>
<div class="badge badge-outline">
Showing {filteredTotal} of {overallTotal}
</div>
</div>
</div>
</div>
</div>
<div
bind:this={grid}
class="boxes-grid"
style="--boxes-per-row: {boxesPerRow}; --cell-padding: {cellPaddingRem}rem; --sprite-size: {spriteSizePx}px;"
>
{#each boxNumbers as boxNumber (boxNumber)}
{@const bulkMenuId = `box-${boxNumber}-bulk-menu`}
<div class="box-shell" use:boxShell={boxNumber} data-box-number={boxNumber}>
{#if !virtualize || renderAll || visibleBoxes.has(boxNumber) || focusedBox === boxNumber}
<div class="box-content">
<div
class="box-heading flex items-center justify-between gap-3 mb-4 relative z-20"
>
<h2 class="text-xl font-bold">Box {boxNumber}</h2>
{#if !readOnly}<div class="relative">
<button
type="button"
class="btn btn-sm btn-outline relative z-[210]"
aria-label="Open bulk actions menu"
aria-haspopup="menu"
aria-controls={bulkMenuId}
aria-expanded={openBulkMenuForBox === boxNumber}
on:click={(event) => {
event.stopPropagation();
openBulkMenuForBox =
openBulkMenuForBox === boxNumber ? null : boxNumber;
}}
on:keydown={(event) => {
if (event.key === 'Escape') openBulkMenuForBox = null;
}}
>
</button>
{#if openBulkMenuForBox === boxNumber}
<ul
id={bulkMenuId}
class="menu bg-base-100 rounded-box absolute right-0 mt-2 z-[220] w-56 p-2 shadow border border-base-300"
>
<li>
<button
type="button"
on:click|stopPropagation={() => {
markBoxAsNotCaught(boxNumber);
openBulkMenuForBox = null;
}}
>
Mark box as Not caught
</button>
</li>
<li>
<button
type="button"
on:click|stopPropagation={() => {
markBoxAsCaught(boxNumber);
openBulkMenuForBox = null;
}}
>
Mark box as Caught
</button>
</li>
<li>
<button
type="button"
on:click|stopPropagation={() => {
markBoxAsNeedsToEvolve(boxNumber);
openBulkMenuForBox = null;
}}
>
Mark box as Needs to evolve
</button>
</li>
<li>
<button
type="button"
on:click|stopPropagation={() => {
markBoxAsInHome(boxNumber);
openBulkMenuForBox = null;
}}
>
Mark box as In HOME
</button>
</li>
<li>
<button
type="button"
on:click|stopPropagation={() => {
markBoxAsNotInHome(boxNumber);
openBulkMenuForBox = null;
}}
>
Mark box as Not in HOME
</button>
</li>
</ul>
{/if}
</div>{/if}
</div>
<div class="grid grid-cols-6">
{#each BOX_POSITIONS as positionInBox}
{@const globalIndex = (boxNumber - 1) * POKEMON_PER_BOX + positionInBox}
{@const placement = calculateBoxPlacement(globalIndex)}
{@const entry = combinedData?.[globalIndex]}
{@const pokedexEntry = entry?.pokedexEntry}
{@const catchRecord = entry?.catchRecord ?? null}
{@const isFilteredOut =
!!entry && filtersActive && !!filtersKey && !matchesFilters(catchRecord)}
{#if entry && pokedexEntry}
<button
type="button"
class="pokemon-box {cellStatusClasses(catchRecord)} {isFilteredOut
? 'pokemon-box--filtered-out'
: 'hover:scale-105 hover:shadow-lg hover:z-50'} transition-all cursor-pointer relative"
style="grid-column-start: {placement.column}; grid-row-start: {placement.row};
{cellBackgroundColourStyle(globalIndex, catchRecord)}"
data-offline-action
data-entry-index={globalIndex}
data-entry-id={pokedexEntry._id}
on:focus={() => (focusedBox = boxNumber)}
on:keydown={(event) => navigateEntry(event, globalIndex)}
aria-disabled={isFilteredOut}
on:click={() => {
if (!isFilteredOut) onPokemonClick(entry);
}}
aria-label="View details for {pokedexEntry.pokemon}{pokedexEntry.form
? ` (${pokedexEntry.form})`
: ''}. Status: {statusLabel(catchRecord)}"
>
<span class="cell-tooltip">
<span class="block w-full h-full">
{#if catchRecord?.caught}
<span
class="status-badge status-badge--caught absolute left-0.5 status-badge-top z-10"
title="Caught"
>
<svg
class="status-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M5 13l4 4L19 7" />
</svg>
<span class="sr-only">Caught</span>
</span>
{:else if catchRecord?.haveToEvolve}
<span
class="status-badge status-badge--evolve absolute left-0.5 status-badge-top z-10"
title="Caught but needs to evolve"
>
<svg
class="status-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M12 19V5" />
<path d="M5 12l7-7 7 7" />
</svg>
<span class="sr-only">Caught but needs to evolve</span>
</span>
{/if}
{#if catchRecord?.inHome}
<span
class="status-badge status-badge--home absolute right-0.5 status-badge-top z-10"
title="In Pokémon HOME"
>
<svg
class="status-icon"
viewBox="0 0 24 24"
fill="currentColor"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M12 3 3 10.5V21a1 1 0 0 0 1 1h5v-6h6v6h5a1 1 0 0 0 1-1V10.5L12 3Z"
/>
</svg>
<span class="sr-only">In HOME</span>
</span>
{/if}
<div class="pokemon-box-inner">
<PokemonSprite
pokemonName={pokedexEntry.pokemon}
pokedexNumber={pokedexEntry.pokedexNumber}
form={pokedexEntry.form}
spriteKey={pokedexEntry.spriteKey}
shiny={showShiny}
variant="grid"
/>
<span class="md:hidden">&#9432;</span>
</div>
<div slot="tooltip">
</span>
<span class="cell-tooltip-text" role="tooltip">
<div class="font-bold">
{pokedexEntry.pokemon}
{pokedexEntry.form ? `(${pokedexEntry.form})` : ''}
</div>
<div>{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</div>
<div>
Caught: {catchRecord.caught ? 'Yes' : 'No'} <br />
Needs to Evolve: {catchRecord.haveToEvolve ? 'Yes' : 'No'} <br />
In Home: {catchRecord.inHome ? 'Yes' : 'No'}
Caught: {catchRecord?.caught ? 'Yes' : 'No'} <br />
Caught but needs to Evolve: {catchRecord?.haveToEvolve
? 'Yes'
: 'No'}
<br />
In Home: {catchRecord?.inHome ? 'Yes' : 'No'}
</div>
</span>
</span>
</button>
{:else}
<button
type="button"
class="pokemon-box pokemon-box--empty"
disabled
style="grid-column-start: {placement.column}; grid-row-start: {placement.row};
{cellBackgroundColourStyle(globalIndex, null)}"
aria-label="Empty box slot"
>
<div class="pokemon-box-inner" aria-hidden="true">
<span class="sprite-placeholder" />
</div>
</Tooltip>
</div>
</button>
{/if}
{/each}
</div>
</div>
{/if}
</div>
{/each}
</div>
</div>
{:else if failedToLoad}
{#if creatingRecords && totalRecordsCreated > 0}
{#if retryLoad}
<p role="alert">Unable to load Pokédex.</p>
<button class="btn" on:click={retryLoad}>Retry loading Pokédex</button>
{:else if creatingRecords && totalRecordsCreated > 0}
<p>Processed {totalRecordsCreated} Pokédex entries so far...</p>
<p>Please be patient, this may take some time.</p>
{:else if creatingRecords}
@@ -124,8 +716,12 @@
If you're seeing this, you probably haven't created your Pokédex data yet. Please do so by
clicking this button.
</p>
{#if !readOnly}
<button class="btn" on:click={createCatchRecords}>Create Pokédex data</button>
{/if}
{/if}
{:else if combinedData}
<p>No entries match this Pokédex.</p>
{:else}
<div class="min-w-max mx-auto">
<h1>Loading Pokédex</h1>
@@ -136,8 +732,187 @@
</main>
<style>
.box-shell {
position: relative;
min-width: 0;
}
.box-shell::before {
content: '';
display: block;
padding-top: calc(83.333333% + 80px);
}
.box-content {
position: absolute;
inset: 0 0 32px;
}
.box-heading {
height: 32px;
}
.cell-tooltip {
display: block;
width: 100%;
height: 100%;
}
.cell-tooltip-text {
display: none;
position: absolute;
z-index: 100;
pointer-events: none;
background: #1f2937;
color: white;
border-radius: 4px;
padding: 8px;
width: 13rem;
}
.pokemon-box:hover .cell-tooltip-text,
.pokemon-box:focus-visible .cell-tooltip-text {
display: block;
}
/*
Theme-aware backgrounds for non-caught box slots.
- Light mode (`pokeball`) keeps the original exact colors.
- Dark mode maps to DaisyUI theme base tokens so it stays consistent with the active theme.
*/
:global(:root) {
--ld-box-bg-even: var(--fallback-b1, oklch(var(--b1) / 1));
--ld-box-bg-odd: var(--fallback-b3, oklch(var(--b3) / 1));
}
:global([data-theme='pokeball']) {
--ld-box-bg-even: #ffffff;
--ld-box-bg-odd: #f9f9f9;
}
.boxes-grid {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 1rem;
}
@media (min-width: 768px) {
.boxes-grid {
grid-template-columns: repeat(var(--boxes-per-row), minmax(0, 1fr));
}
}
.pokemon-box {
border: 1px solid #ddd;
padding: 1rem;
padding: 0;
border-radius: 0;
/*
On small screens the grid columns get narrow; without an explicit ratio,
the button height becomes content-driven (padding + sprite) and you end up
with rectangular cells. Force each slot to be square.
*/
aspect-ratio: 1 / 1;
width: 100%;
}
.pokemon-box--filtered-out {
opacity: 0.25;
filter: grayscale(1);
cursor: default;
}
.pokemon-box--empty {
opacity: 0.55;
cursor: default;
}
.pokemon-box-inner {
padding: var(--cell-padding, 1rem);
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.pokemon-box :global(img) {
width: var(--sprite-size, 64px);
height: var(--sprite-size, 64px);
max-width: 100%;
max-height: 100%;
display: block;
object-fit: contain;
}
.sprite-placeholder {
width: var(--sprite-size, 64px);
height: var(--sprite-size, 64px);
max-width: 100%;
max-height: 100%;
display: block;
}
/* Mobile: keep 6 columns but prevent sprite/padding from forcing tall cells */
@media (max-width: 767px) {
.pokemon-box-inner {
/* cap padding so the sprite can fit inside small squares */
padding: min(var(--cell-padding, 1rem), 0.35rem);
}
.pokemon-box :global(img) {
/* allow the sprite to shrink with the square cell */
width: min(var(--sprite-size, 64px), 100%);
height: min(var(--sprite-size, 64px), 100%);
}
.sprite-placeholder {
width: min(var(--sprite-size, 64px), 100%);
height: min(var(--sprite-size, 64px), 100%);
}
.status-badge {
width: 0.95rem;
height: 0.95rem;
}
.status-badge-top {
top: 0.35rem;
}
.status-icon {
width: 0.85rem;
height: 0.85rem;
}
}
.status-badge {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.15rem;
height: 1.15rem;
border-radius: 0.35rem;
font-weight: 900;
font-size: 0.8rem;
line-height: 1;
border: none;
background: transparent;
}
.status-badge-top {
top: 0.7rem;
}
.status-icon {
width: 1rem;
height: 1rem;
display: block;
}
.status-badge--caught {
color: #16a34a; /* green-600 */
}
.status-badge--evolve {
color: #eab308; /* yellow-500 */
}
.status-badge--home {
color: #0284c7; /* sky-600 */
}
</style>
@@ -1,51 +0,0 @@
<script lang="ts">
import PokedexEntryCatchRecord from './PokedexEntryCatchRecord.svelte';
import type { CombinedData } from '$lib/models/CombinedData';
export let showOrigins = true;
export let showForms = true;
export let showShiny = false;
export let combinedData: CombinedData[] | null;
export let creatingRecords = false;
export let totalRecordsCreated = 0;
export let failedToLoad = false;
export let updateACatch = (event: any) => {};
export let createCatchRecords = () => {};
</script>
<main class="flex-1 p-4 w-full">
<div class="max-w-min mx-auto">
{#if combinedData && combinedData.length > 0}
{#each combinedData as { pokedexEntry, catchRecord }}
<PokedexEntryCatchRecord
{pokedexEntry}
{showOrigins}
{showForms}
{showShiny}
bind:catchRecord
on:updateCatch={updateACatch}
/>
{/each}
{:else if failedToLoad}
{#if creatingRecords && totalRecordsCreated > 0}
<p>Processed {totalRecordsCreated} Pokédex entries so far...</p>
<p>Please be patient, this may take some time.</p>
{:else if creatingRecords}
<p>Processing...</p>
<p>Please be patient, this may take some time.</p>
{:else}
<h1>Failed to load</h1>
<p>
If you're seeing this, you probably haven't created your Pokédex data yet. Please do so by
clicking this button.
</p>
<button class="btn" on:click={createCatchRecords}>Create Pokédex data</button>
{/if}
{:else}
<div class="min-w-max mx-auto">
<h1>Loading Pokédex</h1>
<span class="loading loading-spinner loading-xl"></span>
</div>
{/if}
</div>
</main>
+20 -16
View File
@@ -1,8 +1,9 @@
import mongoose, { Schema, Document, Types } from 'mongoose';
export interface CatchRecord extends Document {
// Supabase-based CatchRecord interface
export interface CatchRecord {
_id: string; // Maps to Supabase 'id' field for frontend compatibility
userId: string;
pokedexEntryId: Types.ObjectId;
pokemonId: string;
pokedexId: string;
haveToEvolve: boolean;
caught: boolean;
inHome: boolean;
@@ -10,15 +11,18 @@ export interface CatchRecord extends Document {
personalNotes: string;
}
const catchRecordSchema = new Schema<CatchRecord>({
userId: String,
pokedexEntryId: { type: Schema.Types.ObjectId, ref: 'PokedexEntry', required: true },
haveToEvolve: { type: Boolean, default: false },
caught: { type: Boolean, default: false },
inHome: { type: Boolean, default: false },
hasGigantamaxed: { type: Boolean, default: false },
personalNotes: String
});
const CatchRecordModel = mongoose.model<CatchRecord>('CatchRecord', catchRecordSchema);
export default CatchRecordModel;
// Database record type for Supabase
export interface CatchRecordDB {
id: string;
userId: string;
/** Numeric foreign key in database (references `pokemon.id`) */
pokemonId: number;
pokedexId: string; // NEW: Foreign key to pokedexes table
haveToEvolve: boolean;
caught: boolean;
inHome: boolean;
hasGigantamaxed: boolean;
personalNotes: string;
createdAt: string;
updatedAt: string;
}
+1 -1
View File
@@ -3,5 +3,5 @@ import { type CatchRecord } from './CatchRecord';
export interface CombinedData {
pokedexEntry: PokedexEntry;
catchRecord: CatchRecord;
catchRecord: CatchRecord | null;
}
+16
View File
@@ -0,0 +1,16 @@
import type { CombinedData } from './CombinedData';
import type { Pokedex } from './Pokedex';
export const OFFLINE_SNAPSHOT_VERSION = 1;
export type OfflinePokedexSnapshot = {
pokedex: Pokedex;
entries: CombinedData[];
};
export type OfflineSnapshot = {
version: typeof OFFLINE_SNAPSHOT_VERSION;
generatedAt: string;
userId: string;
pokedexes: OfflinePokedexSnapshot[];
};
+28
View File
@@ -0,0 +1,28 @@
export interface Pokedex {
_id: string;
shareToken: string;
userId: string;
name: string;
description: string;
isLivingDex: boolean;
isShinyDex: boolean;
isOriginDex: boolean;
isFormDex: boolean;
gameScope: string | null;
dexScopes: string[];
}
export interface PokedexDB {
id: string;
shareToken: string;
userId: string;
name: string;
description: string;
isLivingDex: boolean;
isShinyDex: boolean;
isOriginDex: boolean;
isFormDex: boolean;
gameScope: string | null;
createdAt: string;
updatedAt: string;
}
+29 -38
View File
@@ -1,51 +1,42 @@
import mongoose, { Schema, Document } from 'mongoose';
// Supabase-based PokedexEntry interface
export type CatchInformationItem = {
game: string;
location: string;
notes: string;
};
export interface PokedexEntry extends Document {
export interface PokedexEntry {
_id: string; // Maps to Supabase 'id' field for frontend compatibility
pokedexNumber: number;
boxPlacement: { box: number; row: number; column: number };
boxPlacementForms: { box: number; row: number; column: number };
pokemon: string;
form: string;
spriteKey: string;
canGigantamax: boolean;
regionToCatchIn: string;
gamesToCatchIn: string[];
regionToEvolveIn: string;
evolutionInformation: string;
catchInformation: [
{
game: string;
location: string;
catchInformation: Array<string | CatchInformationItem>;
notes: string;
}
];
// Note: Regional dex numbers stored in separate regional_dex_numbers table
}
const pokedexEntrySchema = new Schema<PokedexEntry>({
pokedexNumber: Number,
boxPlacement: {
box: Number,
row: Number,
column: Number
},
boxPlacementForms: {
box: Number,
row: Number,
column: Number
},
pokemon: String,
form: String,
canGigantamax: Boolean,
regionToCatchIn: String,
gamesToCatchIn: Array<string>,
regionToEvolveIn: String,
evolutionInformation: String,
catchInformation: [
{
game: String,
location: String,
notes: String
// Database record type for Supabase
export interface PokedexEntryDB {
id: number;
pokedexNumber: number;
pokemon: string;
form: string | null;
spriteKey: string | null;
canGigantamax: boolean;
isDefaultForm: boolean;
regionToCatchIn: string | null;
gamesToCatchIn: string[] | null;
regionToEvolveIn: string | null;
evolutionInformation: string | null;
catchInformation: string[] | null;
notes: string | null;
// Note: Regional dex numbers stored in separate regional_dex_numbers table
createdAt: string;
updatedAt: string;
}
]
});
export default mongoose.model<PokedexEntry>('PokedexEntry', pokedexEntrySchema);
@@ -0,0 +1,38 @@
export type ExportProvider = 'google_drive' | 'dropbox';
export interface PokedexExportIntegration {
_id: string;
userId: string;
pokedexId: string | null;
provider: ExportProvider;
enabled: boolean;
fileName: string | null;
folderId: string | null;
path: string | null;
accessToken: string;
refreshToken: string | null;
accessTokenExpiresAt: string | null;
metadata: Record<string, unknown> | null;
lastExportedAt: string | null;
lastError: string | null;
/** Set by a database trigger on every write, so it doubles as the row's version. */
updatedAt: string | null;
}
export interface PokedexExportIntegrationDB {
id: string;
userId: string;
pokedexId: string | null;
provider: ExportProvider;
enabled: boolean;
fileName: string | null;
folderId: string | null;
path: string | null;
accessToken: string;
refreshToken: string | null;
accessTokenExpiresAt: string | null;
metadata: Record<string, unknown> | null;
lastExportedAt: string | null;
lastError: string | null;
updatedAt: string | null;
}
+58
View File
@@ -0,0 +1,58 @@
import type { PokedexEntry } from './PokedexEntry';
import type { CatchRecord } from './CatchRecord';
/** Complete ordering/status data, without detail text or repeated ownership fields. */
export type PokedexGridRow = {
pokedexEntry: Pick<
PokedexEntry,
'_id' | 'pokemon' | 'pokedexNumber' | 'form' | 'spriteKey' | 'canGigantamax'
>;
catchRecord: Pick<
CatchRecord,
'_id' | 'caught' | 'haveToEvolve' | 'inHome' | 'hasGigantamaxed'
> | null;
};
export type CatchRecordPatch = Partial<CatchRecord> &
Pick<CatchRecord, 'userId' | 'pokedexId' | 'pokemonId'>;
/** Version 1 transport rows: avoid repeating field names 1,000+ times. IDs remain available. */
export type PackedGridRow = [
entryId: string,
number: number,
name: string,
form: string,
spriteKey: string,
canGigantamax: boolean,
catchId: string | null,
status: number
];
export function packGrid(rows: PokedexGridRow[]): PackedGridRow[] {
return rows.map(({ pokedexEntry: e, catchRecord: c }) => [
e._id,
e.pokedexNumber,
e.pokemon,
e.form,
e.spriteKey,
e.canGigantamax,
c?._id ?? null,
(c?.caught ? 1 : 0) |
(c?.haveToEvolve ? 2 : 0) |
(c?.inHome ? 4 : 0) |
(c?.hasGigantamaxed ? 8 : 0)
]);
}
export function unpackGrid(rows: PackedGridRow[]): PokedexGridRow[] {
return rows.map(([id, number, name, form, spriteKey, canGigantamax, catchId, status]) => ({
pokedexEntry: { _id: id, pokedexNumber: number, pokemon: name, form, spriteKey, canGigantamax },
catchRecord:
catchId === null
? null
: {
_id: catchId,
caught: !!(status & 1),
haveToEvolve: !!(status & 2),
inHome: !!(status & 4),
hasGigantamaxed: !!(status & 8)
}
}));
}
-14
View File
@@ -1,14 +0,0 @@
import mongoose, { Schema, Document } from 'mongoose';
export interface PokedexMetadata extends Document {
lastModified: Date;
}
const pokedexMetadataSchema = new Schema<PokedexMetadata>({
lastModified: {
type: Date,
default: Date.now
}
});
export default mongoose.model<PokedexMetadata>('PokedexMetadata', pokedexMetadataSchema);
+10 -10
View File
@@ -1,13 +1,13 @@
import mongoose, { Schema, Document } from 'mongoose';
export interface RegionGameMapping extends Document {
// Supabase-based RegionGameMapping interface
export interface RegionGameMapping {
id?: number;
region: string;
games: string[];
game: string; // Note: Different from MongoDB version which had 'games' array
}
const regionGameMappingSchema = new Schema<RegionGameMapping>({
region: String,
games: Array<string>
});
export default mongoose.model<RegionGameMapping>('RegionGameMapping', regionGameMappingSchema);
// Database record type for Supabase
export interface RegionGameMappingDB {
id: number;
region: string;
game: string;
}

Some files were not shown because too many files have changed in this diff Show More