Three monolithic hooks became 21 focused modules
Deposit uses six hooks, withdrawal five, swap seven, and tip three. Together, the 21 hooks span 4,845 lines and can be debugged independently.
major system
Large-Scale Refactor - 54+ Providers, 9 EVM Chains, 8-Branch Zustand Tree, Runtime Theming, ~75K Lines
I inherited a 75K-line crypto casino with 1,500-line transaction hooks and inconsistent boundaries. The refactor split that work into 21 focused hooks, a 32-slice Zustand tree, six singleton services, an OKLCh theme system with 22 variants, and a backend-driven SEO setup using Prisma and JSON-LD. The work happened while memewin.bet remained in production.
memewin.bet is a crypto casino that aggregates 54+ game providers across nine EVM chains. Users connect EVM wallets through Dynamic Labs, deposit, withdraw, and swap on-chain with WebSocket transaction updates, and launch games in iframes. They can choose from 11 themes and custom fonts. A separate admin system manages blog posts and SEO landing pages.
The original 1,500-line hooks mixed form state, gas estimation, API calls, and transaction execution, which made a failed transaction hard to trace. The two WebSocket connections needed their own retry state, and the theme system needed 22 rule sets without a flash during a switch. The leaf, branch, and tree Zustand structure gave the 75K-line codebase smaller state boundaries. Each change answered a specific problem in the inherited code.
Next.js 15 (App Router, Turbopack) / React 19 / TypeScript (strict) / Tailwind CSS v4 (OKLCh color space) / Zustand 5 + Immer + DevTools / reselect (memoized selectors) / Wagmi 2.15 + viem 2.31 + ethers 6 / Dynamic Labs SDK 4.25 (Web3 auth) / Socket.IO (dual connections) / Prisma 5 + MySQL / jose + bcryptjs (admin JWT auth) / next-intl (20 locales) / DiceBear (avatar generation) / Farcaster miniapp-sdk
WS: transaction connected - userId: 12345 Deposit flow: `approve()` confirmed, `transfer()` sent, the API recorded it, then the transaction WebSocket reported the status. Theme: 'midnight-ocean' applied - CSS vars swapped, zero flash (class injected before hydration) Search: `pg soft` ran through `selectFilteredGames` and `selectVisibleGames`, then used the memoized selector chain. Cross-tab logout: received the broadcast, cleared Zustand, and removed the cookie.
01 / 01Production trace
Deposit uses six hooks, withdrawal five, swap seven, and tip three. Together, the 21 hooks span 4,845 lines and can be debugged independently.
Thirty-two slices feed eight branches through Immer and reselect across 4,522 lines. The `selectVisibleGames` chain alone contains 360 lines of memoized selectors with keyword expansion.
The theme system includes 2,365 lines in `globals.css`, an 883-line `theme-toggle.tsx`, and a 569-line font system. Applying the theme class before hydration prevents Tailwind v4 JIT from flashing unstyled content.
`global-seo.config.json`, `seo-config-loader.ts`, and `schema-generator.ts` supply JSON-LD for Organization, Website, BreadcrumbList, and Article. The admin CMS uses ISR revalidation.
結論Breaking stateful transaction logic into focused hooks made failures easier to isolate. The service layer provided explicit connect, disconnect, and retry lifecycles across consumers. The leaf, branch, and tree store structure kept selector and state boundaries clear as the frontend grew.
Make it hold together
Architecture, interface, production constraints. Together.