尚未偵測到更新。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.