Upgrade 2026-07: P0 fixes, BNB Chain config, SEO/RSC refactor - #1
AmazingAng wants to merge 4 commits into
Conversation
Fixes: - SBT mint waits for the transaction receipt (a revert now surfaces an error instead of showing success) - GitHub OAuth popup: closed-popup rejection, opener guard, no code logs - Image fallback precedence bug; invalid blurDataURL removed - Prev/next chapter links no longer emit /undefined - Error boundaries: app/[lang]/error.tsx, not-found.tsx, course/error.tsx - Token cookie: secure + sameSite=lax; .env removed from the git index BNB Chain readiness: - Chain, contract and subgraph endpoints are env-driven (NEXT_PUBLIC_SBT_CHAIN_ID / ADDRESS / MINTER_ADDRESS / GRAPH_URL); a missing chain id now fails loudly instead of falling back to sepolia - bsc and bscTestnet added to the wagmi network list - Reown metadata set to WTF Academy (was the appkit-example template) - images.remotePatterns narrowed to an allowlist; dead deps removed SEO/RSC refactor: - Chapter and course pages are server components (parallel fetch, React cache() dedup, force-dynamic) - Server-side markdown with shiki dual-theme highlighting, visually identical to the previous client rendering - rehype-sanitize allowlist closes the stored-XSS vector in contributor markdown while keeping YouTube/Bilibili embeds and KaTeX - Per-chapter generateMetadata, sitemap.xml, robots.txt, hreflang and a site-wide title template; middleware no longer localizes sitemap/robots - Client shiki: singleton highlighter, lazy grammars, stable query keys Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Founder decision: minting is free, with 0.01 BNB suggested as an opt-in
donation. The signed mint_price is a minimum enforced by the contract, so
the console sets it to 0 and the UI suggests the amount.
- Fix: the transaction sent the typed donation amount even when the
donation checkbox was unchecked, so a user opting out still paid.
Validation consulted the checkbox but the value did not; both now read
one source, and unchecking keeps the typed amount instead of wiping it
- Fix: the claim page pre-filled a hardcoded 6900000000000000 wei
(0.0069 ETH) instead of the course's configured price, which would have
overridden the new zero price. It now reads sbt_token.price and falls
back to the 0.01 suggestion when the price is 0
- Fix: the success screen thanked users for "donating 0 BNB" after a free
mint; that line now only renders when a donation was actually made
- Suggested donation default 0.1 to 0.01
- Currency symbol now comes from SBT_CHAIN.nativeCurrency.symbol
everywhere; the hardcoded "ETH" in both dictionaries becomes {symbol}
interpolation, so copy follows the configured chain
- Share-on-X copy uses the chain's handle (BNB Chain instead of @base)
- Donation input rejects negative and NaN values
- Document that the address previously hardcoded as the SBT contract is
actually the minter (the real Base ERC1155 is 0xB05D4249...5E8c5c)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Update: BNB pricing — free mint with a suggested 0.01 BNB donation (acf493e)Founder decision: minting is free, with 0.01 BNB suggested as an opt-in donation. Since the signed Three real bugs surfaced while implementing this:
Also: currency symbol comes from Behaviour matrix (checkbox × typed amount × signed price) was walked through for all 8 combinations: unchecked always sends 0, checked sends the typed amount, and a course with a non-zero price still blocks an under-payment. Before launch
|
The repo had no CI at all. Runs tsc --noEmit, pnpm lint and pnpm build on PRs and pushes to main/upgrade/**. The build step sets NEXT_PUBLIC_SBT_* placeholders because the SBT constants now fail fast on a missing chain id rather than silently falling back to Sepolia; without them the build cannot compile. No backend is contacted (all API-dependent routes are request-dynamic). Also pins pnpm via packageManager so CI and local installs agree instead of inferring the version from the lockfile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pnpm/action-setup errors when a version is given both in the workflow and in package.json packageManager. Drop the workflow copy so the manifest is the single source. Node 20 is deprecated on GitHub runners.
Review branch for the 2026-07 upgrade. Three groups of changes: correctness fixes, BNB Chain configuration, and the SEO/RSC refactor. No visual changes — the rendered output is intentionally identical.
1. Fixes
useWaitForTransactionReceipt; success only on a confirmed receipt, reverts surface the existing error statepopup.closed, rejects and cleans up<Link href="/course/x/undefined">error.tsxanywhere, so one API 500 produced Next's default error pagerehype-rawwith no sanitization, while the JWT sat in a JS-readable cookierehype-sanitizeallowlist (below) plussecureandsameSite=laxon the cookie.envwas committed to the repository.gitignore(contents wereNEXT_PUBLIC_*only, no secrets)images.remotePatterns: "**"turned the image optimizer into an open proxy2. BNB Chain readiness
Chain id, both contract addresses and the subgraph endpoint are now environment-driven (
NEXT_PUBLIC_SBT_CHAIN_ID,NEXT_PUBLIC_SBT_ADDRESS,NEXT_PUBLIC_SBT_MINTER_ADDRESS,NEXT_PUBLIC_SBT_GRAPH_URL,NEXT_PUBLIC_SBT_OPENSEA_URL) and documented in.env.sample. A missing chain id now throws instead of silently falling back to Sepolia — the previous behaviour paired a Sepolia chain with a Base mainnet minter address.bscandbscTestnetare added to the wagmi network list.Reown metadata was still the template default (
appkit-example/appkitexampleapp.com), which is the name users saw in their wallet signing prompt; it now reads WTF Academy with the real domain.3. SEO/RSC refactor
The chapter page was
"use client"with two serialuseSuspenseQuerycalls, so course content — the site's entire organic-search surface — was invisible to crawlers. There was nositemap, norobots, no hreflang, and the chapter layout hardcoded the title "WTF Solidity课程" for every course.cache()-deduped (metadata and body share one API call),force-dynamicfor the same data freshness as before.generateMetadata(title, description, OG, canonical, hreflang),app/sitemap.ts(both locales, falls back to static routes if the API is down),app/robots.ts, and a site-wide title template.middleware.tslocale-redirectingsitemap.xmlandrobots.txtinto 404s.Sanitize schema: default rehype-sanitize rules (drops
script,on*handlers,javascript:URLs) extended to keepclassName/style, images, video,details/summary, the full KaTeX MathML tag set, and iframes restricted to YouTube and Bilibili embed URLs. Verified against hostile input — script tags,onerrorand non-allowlisted iframes are stripped while legitimate embeds and math survive.Verification
tsc --noEmitclean;pnpm buildsucceeds with no backend running. Chapter and course-list SSR output was checked against a mock API: full highlighted content, correct per-chapter metadata, and sitemap output for both locales.Note for reviewers
The SBT contract addresses are placeholders until the BNB Chain deployment lands (see WTFAcademy/WTF-SBT#8). The claim page will fail until they are filled in.
🤖 Generated with Claude Code