尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Pokemon card collection tracker for a group of collectors. Each person signs up, marks what they own, records condition, edition and price paid, and flags cards they want or will trade. Groups join through an invite link and get trade matches and a completion board. Anyone can share a read-only binder link.
Every English WotC-era set - 18 sets, 1,789 cards - grouped by era in the switcher:查看完整 README ↗Pokemon card collection tracker for a group of collectors. Each person signs up, marks what they own, records condition, edition and price paid, and flags cards they want or will trade. Groups join through an invite link and get trade matches and a completion board. Anyone can share a read-only binder link.
Every English WotC-era set - 18 sets, 1,789 cards - grouped by era in the switcher:
The card lists are hardcoded in index.html - no catalog API at runtime. The first seven sets were entered by hand; the other eleven were generated from the PokemonTCG/pokemon-tcg-data dataset in September 2026. Aquapolis and Skyridge print their holos as H1-H32; those are stored as numbers 151-182 so keys and sorting stay numeric, and keep the printed number in label.
To add a set: one card array, one SETS entry, and its id in ERAS.
Every card has two copies in img/<set>/, named by zero-padded card number: AVIF [quality 55] for browsers that support it and WebP [quality 80] as the fallback, served through a <picture> element. Both are 400px wide [Gym Heroes, Gym Challenge and Neo Genesis stay at their native 240px, never upscaled]. The AVIF set is 38.4MB against 62.5MB for WebP - 38% less, with no visible difference at card size.
Only the set on screen loads, and within it only the cards near the viewport. Opening the site on a phone pulls about 16 card images.
base/, jungle/, ...] as the source of truth. .vercelignore keeps them out of the deploy.images.pokemontcg.io/<set>/<number>_hires.png]. No originals are kept - that URL is the source.img/ folder: WebP quality=80, method=6, AVIF quality=55, speed=6.img/ with a one-year immutable cache [vercel.json], and the service worker caches viewed images the same way. If an image ever changes, write the new files under a new folder name and repoint imgPath - overwriting in place leaves browsers on the old copy for a year.Single static index.html - no build step. Supabase for auth and cloud sync. server.js is a small local dev server.
vendor/supabase-js-2.116.0.js [the UMD build from npm], loaded at the end of <body>. A new release can't reach the live app untested. To upgrade, download the new version under its own file name, change the <script> tag, and change LIBRARY in sw.js.sw.js makes the app work offline. The page is served from cache and refreshed in the background, so a deploy shows up on the open after next. Images and the library are cache-first, and only what someone has viewed is cached. Supabase requests are never cached - the app's own sync queue handles offline edits. Offline with an expired token, the app opens from the session stored on the device. To switch the worker off, deploy a sw.js that calls self.registration.unregister().preconnect hint in <head> opens the Supabase connection while the page loads.manifest.webmanifest and icons/ let phones add it to the home screen and open it full screen. The icon and favicon are Crystamber's own mark - a faceted amber gem drawn with Pillow - with no Pokemon branding. A fan-made disclaimer sits at the bottom of every page, shared binders included.node server.js
Serves on port 3000, including /?u= binder and /?join= invite links.
Email and password through Supabase Auth. The username is passed as signup metadata and a trigger on auth.users copies it into profiles. "Confirm email" must stay off in the Supabase dashboard - the built-in mailer only sends a few emails an hour, so a group signing up together would stall.
Schema lives in supabase/migrations/.
profiles - username, whether the binder is public, and my_sets [the sets they collect - null until they choose, which is when the app asks]. Usernames are readable by anyone so binder links resolve. The only columns a user can change are binder_public and my_sets.user_sets - one row per (user_id, set_id): owned, conditions, prices, card_editions, wants, for_trade. Owner-only RLS.groups, group_members - created only through the create_group and join_group functions.user_sets directly - get_binder and group_collections are security definer functions that never select the prices column.collection_sets is the old single-user table, kept as a frozen backup. The Supabase keepalive workflow still pings it.The Supabase URL and publishable key are inline in index.html. Publishable keys are client-side by design - RLS and the function grants are what protect the data.
One row per set, not one blob for everything. Editing Jungle writes the Jungle row and nothing else, so a failed or half-built write can't take the other sets down with it.
rev and updated_at are server-managed by a before update trigger, so the client can't forge them.localStorage keys are namespaced by user [u:<userId>:<key>], so two people on one phone never see each other's cards.crystamberRevs_v1. On load it adopts a cloud row only when cloud.rev > seen.rev. Equal rev means this device wrote the current state, so it leaves it alone.Hosted on Vercel as the crystamber project. .vercelignore keeps server.js, collection.json, the migrations and the original scans out of the deploy. .vercel/ is gitignored, so run vercel link to reconnect a fresh clone.
vercel.json sets the cache headers: img/ and vendor/ are immutable for a year, and sw.js is no-cache so a new worker is picked up on the next visit.