TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Free NBME score calculator and USMLE Step score predictor with confidence intervals.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Use the free NBME Score Calculator →
NBMEcalc is a free USMLE Step score predictor for combining NBME, UWSA, Free 120, and AMBOSS results. It returns an independent planning estimate with a model-generated planning range instead of presenting a single score as certain.
NBMEcalc is an independent educational tool and is not affiliated with or endorsed by NBME, FSMB, or USMLE.
@cloudflare/next-on-pages)lib/**)Public calculator results, selected homepage content, and indexed blog posts have low-density AdSense placements. Ads are disabled unless a valid publisher id and placement-specific slot ids are provided at build time:
NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT=ca-pub-1234567890123456
NEXT_PUBLIC_GOOGLE_ADSENSE_SLOT_CALCULATOR_RESULT=1234567890
NEXT_PUBLIC_GOOGLE_ADSENSE_SLOT_HOME_CONTENT=2345678901
NEXT_PUBLIC_GOOGLE_ADSENSE_SLOT_BLOG_INLINE=3456789012
Configure Google Privacy & messaging (or another Google-certified CMP) before
serving ads in regions where consent is required. The public /ads.txt route
is generated from the configured publisher id. Keep ads out of forms, result
controls, account pages, checkout, and paid reports.
# 1. Install dependencies
npm install
# 2. Run dev server
npm run dev
# 3. Open browser
http://localhost:3000
nbmecalc/
├── app/
│ ├── layout.tsx # Root layout with fonts + metadata
│ ├── page.tsx # Homepage (composes all sections)
│ └── globals.css # Tailwind + design tokens
├── components/
│ ├── ui/ # shadcn primitives (Button, Input, Accordion, Badge)
│ ├── logo.tsx # Bell-curve SVG logo (Logo + LogoMark)
│ ├── iphone-mockup.tsx # iPhone 17 Pro CSS mockup
│ └── sections/
│ ├── nav.tsx # 1. Top navigation
│ ├── hero.tsx # 2. Hero with iPhone mockup
│ ├── value-props.tsx # Product evidence and limitations
│ ├── calculator.tsx # Live predictor (CORE)
│ ├── reviews.tsx # 6. Reddit quotes
│ ├── stats.tsx # 7. Stats with count-up
│ ├── how-it-works.tsx# 8. 3-step explainer
│ ├── comparison.tsx # 9. Predictor comparison table
│ ├── resource-hub.tsx# 10. Featured guides
│ ├── reviewers.tsx # 11. Physician reviewers
│ ├── faq.tsx # 12. FAQ accordion
│ ├── blog-grid.tsx # 13. 6 blog cards
│ ├── footer.tsx # 14. Footer + legal
│ └── cookie-banner.tsx # First-visit disclaimer
├── lib/
│ ├── utils.ts # cn() helper
│ ├── data.ts # NBME conversion logic + types
│ └── email.ts # Postal HTTP email delivery
├── workers/
│ └── pdf-renderer/ # Cloudflare Browser Rendering PDF Worker
├── public/
│ └── placeholders/ # AI image placeholders + prompts
├── tailwind.config.ts # Mint color scale + animations
└── package.json
| Token | Value |
|---|---|
| Brand color | #34D399 (mint-500) |
| Font | Plus Jakarta Sans |
| Radius | rounded-full (buttons), rounded-3xl (cards) |
| CTA | Black button, white text |
All real-photo locations use <Image src="/images/[name].jpg" /> pointing at AI-generated files. The pictures are generated by the npm run gen:images script which calls the Evolink.ai Z Image Turbo API.
# 1. Get an API key at: https://evolink.ai/dashboard/keys
# 2. Copy the template and fill in your key
cp .env.example .env.local
# Then open .env.local and set EVOLINK_API_KEY=sk-xxxxx
npm run gen:images # only missing ones
npm run gen:images:force # regenerate everything
# Or one specific image:
node scripts/gen-images.mjs reviewer-1
node scripts/gen-images.mjs --force blog-cover-nbme
Output: /public/images/*.jpg (already wired to all components).
Prompts live in /public/placeholders/*.prompt.txt — edit them to tweak style, then re-run with --force.
| Component | File | Aspect | Prompt file |
|---|---|---|---|
| Reviewers (×3) | reviewer-1/2/3.jpg | 1:1 | reviewer-1/2/3.prompt.txt |
| Resource Hub (×3) | blog-cover-nbme/ci/cram.jpg | 4:3 | blog-cover-*.prompt.txt |
| Blog Grid (×6) | blog-cram/most-tested/...jpg | 16:9 | blog-*.prompt.txt |
All sales are final. No refunds (digital product, delivered immediately).
The app degrades gracefully without D1 (next dev: predictions still compute, just aren't persisted), so you can do most UI work without touching Cloudflare. Wire up D1 when you need to test the funnel or the rate limiter end-to-end.
# 1. Apply the committed migrations against a local SQLite shadow DB.
npx wrangler d1 migrations apply nbmecalc-prod --local
# 2. Optionally peek at the schema.
npx wrangler d1 execute nbmecalc-prod --local --command "SELECT name FROM sqlite_schema WHERE type='table';"
wrangler keeps the local SQLite under .wrangler/state/v3/d1/ — it's git-ignored. To exercise the real edge runtime + D1 binding locally, use npm run preview instead of npm run dev.
# 1. Create the database. Wrangler prints a database_id.
npx wrangler d1 create nbmecalc-prod
# 2. Paste the returned id into wrangler.toml (replaces REPLACE_ME_AFTER_FIRST_D1_CREATE).
# 3. Apply migrations to the remote DB.
npx wrangler d1 migrations apply nbmecalc-prod --remote
# 1. Edit lib/db/schema.ts.
# 2. Generate a migration. Pick a descriptive --name.
npx drizzle-kit generate --name add_users_table
# 3. Apply locally (and later remote).
npx wrangler d1 migrations apply nbmecalc-prod --local
Migrations are committed to lib/db/migrations/ so production deploys don't need drizzle-kit on the server — they just wrangler d1 migrations apply --remote.
Migration 0006_lifetime.sql creates the durable Lifetime entitlement table.
The Founding offer is controlled by one deployment setting rather than a
counter or timer:
# 1. Create two one-time Stripe Prices and configure them in Pages.
STRIPE_PRICE_LIFETIME_FOUNDING=price_... # $19.99
STRIPE_PRICE_LIFETIME_REGULAR=price_... # $34.99
NEXT_PUBLIC_LIFETIME_FOUNDING_OFFER_ENABLED=true
# 2. Apply the entitlement migration and deploy.
npx wrangler d1 migrations apply nbmecalc-prod --remote
npm run deploy
To end the Founding offer for future purchases, set
NEXT_PUBLIC_LIFETIME_FOUNDING_OFFER_ENABLED=false and redeploy. Checkout then
selects and verifies the $34.99 Stripe Price server-side. Existing Lifetime
entitlements are never changed by this switch.
For the GitHub Actions deployment, create or update the repository variable at
Settings > Secrets and variables > Actions > Variables. If the variable is
absent, the workflow intentionally defaults to true.
The buyer count remains available internally without appearing on the page:
npx wrangler d1 execute nbmecalc-prod --remote --command "SELECT COUNT(*) AS founding_members FROM lifetime_entitlements WHERE status = 'active' AND promotion_applied = 1;"
The Stripe webhook endpoint must receive checkout.session.completed,
checkout.session.async_payment_succeeded, charge.refunded, and
charge.dispute.created.
charge.refunded is retained as an entitlement-safety event: it revokes access
if an operator or payment network records a full refund despite the no-refund
policy. It does not advertise or create a customer refund right.
Premium report downloads use a separate Cloudflare Worker at workers/pdf-renderer. The Worker is routed at /api/_pdf-renderer/* and uses Cloudflare Browser Rendering (@cloudflare/puppeteer) to open the styled report page and export a color PDF with printBackground: true.
GitHub Actions deploys the Worker and the Pages app from this repository. It derives a shared PDF_RENDERER_SECRET from the existing CLOUDFLARE_API_TOKEN and writes it to both Cloudflare targets during deployment. If the Worker is unavailable at runtime, /api/report/[session_id]/pdf falls back to the edge-safe text PDF generator instead of failing the purchase flow.
The Cloudflare API token used by GitHub Actions needs permissions for:
nbmecalc.com/api/_pdf-renderernpm test # one-shot
npm run test:watch # watch mode
Vitest covers lib/data.ts (prediction + personalized analytics) and lib/rate-limit.ts (fail-open + bucket counting). The DB and Next route handlers are exercised end-to-end via npm run preview (wrangler) — there are no jsdom/React-side unit tests yet.
Magic-link login emails are sent through Postal's HTTP API. Configure these variables in local .env.local and in Cloudflare Pages environment variables for production.
POSTAL_API_URL=https://mail.removexif.com/api/v1/send/message
POSTAL_API_KEY=your-postal-api-key
[email protected]
Use Cloudflare secret variables for POSTAL_API_KEY. Keep SMTP_FROM aligned with the current project domain.
| Keyword | Volume/mo | Status |
|---|---|---|
| nbme score converter | 880 | /nbme-score-conversion |
| nbme score conversion | 880 | /nbme-score-conversion |
| nbme score calculator | 480 | / |
| step 2 score predictor | 480 | /step-2-predictor |
| free 120 step 2 score conversion | 480 | /free-120-predictor |
| step 3 score predictor | 320 | /step-3-predictor |
| nbme cms forms | 320 | /cms-converter |
Volumes are US monthly averages and close variants may share Google Ads volume. Do not sum variants as independent demand.
nbmecalc is not affiliated with NBME, FSMB, USMLE, USMLE-Rx, AMBOSS, UWorld, or Kaplan. Predictions are statistical estimates for educational purposes only.
/api/predict, predictions / reports / rate_limits / events)@react-pdf/renderer on edge)/dashboard with saved predictions timeline/compare/vs-predictmystepscore, ...)Reddit: u/nbmecalc · Email: [email protected]