尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Learn to count cards at blackjack — six-deck shoe, Hi-Lo, basic strategy, deviations, and a full casino table. React 19 + TypeScript, Supabase, Stripe. ~2200 tests.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A web app for learning to count cards at blackjack — properly, in the order the skill is actually built, rather than as a pile of disconnected drills.
Live: black-jack-training.com
It runs a realistic six-deck shoe, teaches the Hi-Lo count, basic strategy and the Illustrious 18 / Fab 4 deviations, and finishes at a full multi-seat casino table with bots, splits, insurance and payouts. A placement test puts a learner on a curriculum, and the plan answers "what do I do next" on every visit. Seven languages. Free tier and a paid tier, with real Stripe subscriptions behind it.
The theory is public and needs no account:
Most of the difficulty in this project is not the blackjack. It is that the app handles money, syncs across devices, has to stay usable offline, and is read by people in seven languages — and any one of those can quietly corrupt the others.
The engine is pure TypeScript with no React in it. src/engine/ holds the
shoe, the counting systems, basic strategy, the deviation tables and the betting
maths. It has no side effects and no framework, which is why it can be tested
exhaustively and reused by the bots, the drills and the analytics without three
copies of the rules drifting apart.
Local-first, cloud-authoritative. The app works offline against
localStorage and reconciles with Supabase on sign-in — union-merging what only
ever grows and taking the max of the counters. Sign-out wipes the device, which
is a security boundary rather than a convenience: without it, the sync layer
would push the previous user's training history into whoever signs in next.
See ADR-001.
Entitlement is written by exactly one thing. The Stripe webhook, verified by
signature, running as service_role. Row-Level Security is default-deny and a
trigger reverts any other write to the entitlement columns, so a client cannot
grant itself the paid tier even if everything in front of it is compromised.
See ADR-002.
Prices come from Stripe at runtime. They used to be literals kept in step by a comment, and on 10 August 2026 they went out of step — the page advertised one amount while the configured price charged another. A comment is not a mechanism.
Two audit documents, written to be read by someone who was not there:
docs/PAYMENT-PATH-AUDIT-2026-08-18.md
— what on the money path was checked and found sound, as well as what was
not, so a later reader can tell "never examined" from "examined and fine".
The common cause of five defects: supabase-js neither throws nor reports a
write that matched nothing.docs/AUDIT-2026-07-31.md — a pass over the whole
app along four axes, including what was deliberately left alone.CLAUDE.md carries a Known gaps section listing live risks with an owner
each, and records closed items as closed rather than deleting them — the next
reader needs to tell "never an issue" from "was an issue and was dealt with".
React 19 · TypeScript (strict) · Vite 7 · Tailwind 4 · Zustand · Framer Motion · Recharts · three.js · i18next
Supabase — Auth, Postgres with RLS, Edge Functions (Deno) · Stripe subscriptions
Vitest + Testing Library · Docker via Dokploy on a Hetzner VPS
npm install
npm run dev # http://localhost:5173
Supabase and Stripe are optional for local work. With neither configured the
app falls back to localStorage, and every gated mode is open — there is no
billing backend to ask, so refusing would only make the app untestable. Pro is
otherwise derived from the subscription status and period end rather than
stored, so it cannot drift out of step with Stripe. Copy .env.example to
.env to wire the real thing up. No secret belongs in the repository, and none
is in it.
npm run test:run # 2400+ tests across 160+ files, the SQL migrations included (PGlite)
npm run typecheck # app and test projects
npm run lint # includes type-aware no-floating-promises
npm run build
src/engine/ Pure TypeScript. No React, no side effects. The rules.
src/store/ Zustand stores. The only thing components talk to.
src/services/ Supabase, Stripe, storage, achievements, curriculum, XP.
src/components/ UI, grouped by feature.
src/i18n/ Seven locales, with a parity test over the message trees.
supabase/ Migrations and Edge Functions; `_shared` holds the tested rules,
`tests/` runs the migrations for real in PGlite.
docs/ ADRs, audits, the Stripe setup guide, the decisions log.
Every module has a test file beside it. Roughly 26,000 lines of tests against 40,000 lines of source — the payment path, the shoe, the counting systems and the strategy tables carry the most.