Be extremely concise. Sacrifice grammar for concision. Terse responses preferred. No fluff.
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Hyperlane Warp UI Template is a Next.js web application for cross-chain token transfers using Hyperlane Warp Routes. It enables permissionless bridging of tokens between any supported blockchain.
- Make the plan extremely concise. Sacrifice grammar for the sake of concision.
- At the end of each plan, give me a list of unresolved questions to answer, if any.
pnpm install # Install dependencies
pnpm dev # Start development server
pnpm build # Production build
pnpm test # Run tests (vitest)
pnpm lint # ESLint check
pnpm typecheck # TypeScript type checking
pnpm prettier # Format code with Prettier
pnpm clean # Remove build artifacts (dist, cache, .next)- Framework: Next.js 15 with React 18
- Styling: Tailwind CSS + Chakra UI
- State: Zustand with persist middleware (
src/features/store.ts) - Queries: TanStack Query
- Wallets: Each blockchain uses distinct, composable wallet providers (EVM/RainbowKit, Solana, Cosmos, Starknet, Radix)
- Core Libraries:
@hyperlane-xyz/sdk,@hyperlane-xyz/registry,@hyperlane-xyz/widgets,@hyperlane-xyz/utils
-
src/features/- Core domain logic organized by feature:transfer/- Token transfer flow (form, validation, execution viauseTokenTransfer)tokens/- Token selection, balances, approvalschains/- Chain metadata, selection UIwallet/- Multi-protocol wallet context providerswarpCore/- WarpCore configuration assemblystore.ts- Global Zustand store managing WarpContext, transfers, UI state
-
src/consts/- Configuration files:config.ts- App configuration (feature flags, registry settings)warpRoutes.yaml- Warp route token definitionschains.yaml/chains.ts- Custom chain metadataapp.ts- App branding (name, colors, fonts)
-
src/components/- Reusable UI components -
src/pages/- Next.js pages (main UI atindex.tsx)
- Initialization:
WarpContextInitGateloads registry and assemblesWarpCorefrom warp route configs - State Hydration: Zustand store rehydrates persisted state (chain overrides, transfer history)
- Transfer Flow:
TransferTokenForm→useTokenTransfer→WarpCore.getTransferRemoteTxs()→ wallet transaction
Environment variables (see .env.example):
NEXT_PUBLIC_WALLET_CONNECT_ID- Required for wallet connectionsNEXT_PUBLIC_REGISTRY_URL- Optional custom Hyperlane registry URLNEXT_PUBLIC_RPC_OVERRIDES- Optional JSON map of chain RPC overrides
See CUSTOMIZE.md for detailed customization instructions:
- Warp Routes:
src/consts/warpRoutes.yaml+warpRouteWhitelist.ts - Chains:
src/consts/chains.yamlorchains.ts - Branding:
src/consts/app.ts,tailwind.config.js, logo files insrc/images/logos/ - Feature Flags:
src/consts/config.ts(showTipBox, showAddRouteButton, etc.)
Tests use Vitest and are co-located with source files using the *.test.ts naming convention. Vitest automatically discovers and runs all matching test files.
# Run all tests
pnpm test
# Run a single test file
pnpm vitest src/features/transfer/fees.test.ts
# Run tests in watch mode
pnpm vitest --watchWe handle ONLY the most important cases. Don't add functionality unless it's small or absolutely necessary.
- Expected issues (external systems, user input): Use explicit error handling, try/catch at boundaries
- Unexpected issues (invalid state, broken invariants): Fail loudly with
throworconsole.error - NEVER add silent fallbacks for unexpected issues - they mask bugs
| Change Location | Backwards-Compat? | Rationale |
|---|---|---|
| Local/uncommitted | No | Iteration speed; no external impact |
| In main unreleased | Preferred | Minimize friction for other developers |
| Released | Required | Prevent breaking downstream integrations |
- Run tests incrementally -
pnpm vitest <file>for specific test files - Check existing patterns - Search codebase for similar implementations
- Use SDK types - Import from
@hyperlane-xyz/sdk, don't redefine - Zustand for state - Global state in
src/features/store.ts - Keep changes minimal - Only modify what's necessary; avoid scope creep
- Feature folders - Domain logic in
src/features/, not scattered - Chain-aware addresses - Only lowercase EVM addresses; Solana/Cosmos are case-sensitive
- Check src/utils/ - Functions like
normalizeAddress,isNullishalready exist - CSP updates - New external scripts need
next.config.jsCSP header updates - useQuery patterns - Use built-in
refetch, don't create custom refresh state - Flatten conditionals - Use early returns instead of nested if/else in JSX
Always search the codebase before assuming. Don't hallucinate file paths, function names, or patterns.
grepor search before claiming "X doesn't exist"- Read the actual file before suggesting changes to it
- Check
git logor blame before assuming why code exists - Verify imports exist in
package.jsonbefore using them
If output seems wrong, check:
- Did I read the actual file? Or did I assume its contents?
- Did I search for existing patterns? The codebase likely has examples
- Am I using stale context? Re-read files that may have changed
- Did I verify the error message? Run the command and read actual output