Guidance for AI agents (and humans) working with code in this repository.
The MultiversX dApp Template: a React 18 + TypeScript + Vite reference app demonstrating @multiversx/sdk-dapp v5 — wallet authentication, transaction signing, batch transactions, and native auth. It doubles as the canonical example that other dApps are scaffolded from, so code here is meant to be copied and adapted.
This directory may live inside the sdk-dapp-workspace monorepo (../../packages), in which case local versions of the SDK packages may be linked during development.
Package manager is pnpm (there is a pnpm-lock.yaml; do not use npm/yarn).
pnpm install
# Dev server (HTTPS on :3000). The network is selected by copying a config file — see Network configuration.
pnpm start-devnet # also: start-testnet, start-mainnet
# Production build to ./build
pnpm build-devnet # also: build-testnet, build-mainnet (runs tsc, copies config, vite build)
pnpm lint # eslint --fix over src
# Unit tests (Jest + SWC, jsdom)
pnpm test
pnpm test -- path/to/File.test.tsx # single file
pnpm test -- -t "test name substring" # single test by name
# E2E tests (Playwright — auto-starts the devnet dev server via webServer)
pnpm run-playwright-test
pnpm run-playwright-test-ui # interactive UI modeNote: jest.config.js sets bail: 1, so the unit suite stops at the first failure.
There is no .env. The active network is chosen at build/dev time by physically copying one of src/config/config.{devnet,testnet,mainnet}.ts over src/config/index.ts. This is what the copy-*-config scripts do, and every start-*/build-* script runs one first.
src/config/index.tsis a generated file — edits to it are overwritten on the nextstart-*/build-*. Change the per-networkconfig.<env>.tsfiles instead.src/config/sharedConfig.tsholds values common to all networks (contract addresses for batch tx demos,walletConnectV2ProjectId,transactionSize, etc.).- App entry
src/index.tsxcallsinitApp(config)(fromsrc/initConfig.ts) before rendering<App />.initConfig.tsconfigures the dApp: nativeAuth, theme, providers (including the customInMemoryProvider), and importsenvironmentfrom the activeconfig— so the copy mechanism is the single source of truth for the network.
src/lib/— the key indirection. Rather than importing from@multiversx/sdk-*directly, app code imports everything throughlib(sdkCore,sdkDapp,sdkDappUI,sdkDappUtils). Each re-export module (e.g.sdkDapp.hooks.ts,sdkDapp.helpers.ts,sdkDapp.types.ts) curates the SDK's deepout/...paths into a flat surface. When you need an SDK hook/helper/type, add it to the relevantlib/sdkDapp/*.tsre-export and import fromlib— keep the deep@multiversx/sdk-dapp/out/...paths confined tosrc/lib.- Routing —
src/routes/routes.tsis a declarative array (path, title, component, optionalauthenticatedRoute, nestedchildren).App.tsxmaps it into React Router.wrappers/AuthRedirectWrapperreads the same array viamatchPathto redirect based onuseGetIsLoggedIn(). src/wrappers/— app-wide context providers composed inApp.tsx:AxiosInterceptors(network auth),BatchTransactionsContextProvider,AuthRedirectWrapper.src/provider/inMemoryProvider.ts— a custom login provider registered onwindow.multiversx.providersininitConfig.ts; used for testing/demo signing without an external wallet.src/pages/— top-level screens (Home,Dashboard,Unlock,Disclaimer,PageNotFound). Dashboard hosts the featurewidgets/(NativeAuth, BatchTransactions, Transactions) and democontracts/interactions (ping-pong).- Path aliases —
baseUrl: src(tsconfig), resolved at build byvite-tsconfig-pathsand by Jest'smodulePaths. Import aslib,config,pages/..., etc., not relative../../.
Tailwind CSS v4 (via @tailwindcss/vite + PostCSS). Themes are driven by CSS variables and a data-mvx-theme attribute. Three built-in themes (mvx:dark-theme, mvx:vibe-theme, mvx:light-theme). Adding a theme touches several files — see the "Configure Theme" walkthrough in README.md (tailwind.css, useHandleThemeManagement.ts, ThemeTooltip.tsx, HomeHero.tsx, initConfig.ts).
- Unit (
*.test.ts(x)/*.spec.ts(x)undersrc/**): Jest, transformed by@swc/jest, jsdom env, setup insrc/setupTests.ts. CSS imports are stubbed viaidentity-obj-proxy. - E2E (
tests/**/*.spec.ts): Playwright.webServerauto-runspnpm run start-devnetagainsthttps://localhost:3000withignoreHTTPSErrors. Tests cover connect-wallet flows (memory provider, MetaMask snap, web wallet) and transaction cancel flows;tests/support/holds MetaMask automation and fs/template helpers.
WebAuthn refuses to run under TLS errors, so passkey work requires real (mkcert) certs served over https://localhost.multiversx.com (add to /etc/hosts) and adjusting vite.config.ts to port 443 with the cert files. Full steps are in README.md → "Passkey Testing Setup". The default vite.config.ts uses @vitejs/plugin-basic-ssl (self-signed), which is fine for everything except passkeys.
ESLint enforces sorted imports (import/order), sorted named exports (sort-exports), Prettier formatting, and react-hooks rules. Run pnpm lint before finishing changes. See MIGRATION_GUIDE.md for SDK version-upgrade notes.
To prove a change works, run in order:
pnpm lint # must pass (also autofixes)
pnpm test # Jest unit suite (bails on first failure)
pnpm build-devnet # type-check + production buildFor login/transaction-flow changes, also run the Playwright suite (pnpm run-playwright-test) or start pnpm start-devnet and exercise the flow at https://localhost:3000 (the In Memory Provider allows login without an external wallet). After build-testnet/build-mainnet runs, regenerate the committed devnet default with pnpm copy-devnet-config so src/config/index.ts shows no diff.
The same template dApp exists for other frameworks — useful when a task actually targets a different stack:
| Template | Stack | Repository |
|---|---|---|
| React (TypeScript) ← this repo | React 18 · TypeScript · Vite | mx-template-dapp |
| React (JavaScript) | React 19 · JSX · Vite | mx-template-dapp-reactjs |
| Next.js | Next.js 16 (App Router) · TypeScript | mx-template-dapp-nextjs |
| SolidJS | SolidJS · TypeScript · Vite | mx-template-dapp-solidjs |
| Vue | Vue 3 · TypeScript · Vite | mx-template-dapp-vue |
| Angular | Angular 20 · TypeScript | mx-template-dapp-angular |
| React Native | React Native | mx-template-dapp-react-native |