inkathoninkathon

Frontend

Deep dive into the Next.js frontend structure and libraries

Tech Stack

PackageDescription
🥟 BunPerformant package & workspace manager
⚙️ TypeScriptType-safe programming language
🛠️ BiomeModern Linter & Formatter
⚛️ Next.jsProduction-grade React framework
🎨 shadcn/ui with Tailwind CSS v4Unopinionated UI components with utility-first styling
⛓️ PapiType-safe Polkadot API
⛓️ ReactiveDOTReactive state management using Papi

File Structure

components.json
next.config.ts
package.json
tsconfig.json

Available Commands

Run these commands from the frontend directory or root with -F frontend:

# Development
bun run dev               # Start dev server

# Production Builds
bun run build             # Build for production
bun run start             # Start production server
bun run build:standalone  # Build for production (self-hosting)

# Code Quality
bun run lint              # Run linter & formatter checks
bun run lint:fix          # Auto-fix issues
bun run typecheck         # TypeScript type checking

# Maintenance
bun run clean             # Remove build artifacts

Web3 Base Components

// Wallet connection with dropdown for multiple wallets
import { ConnectButton } from '@/components/web3/connect-button'

<ConnectButton />

Shows "Connect Wallet" button that opens a dropdown with available wallets. Automatically switches to "Disconnect Wallet" when connected.

// Account selection dropdown with disconnect option
import { AccountSelect } from '@/components/web3/account-select'

function MyComponent() {
const [account, setAccount] = useState<WalletAccount>()

return <AccountSelect account={account} setAccount={setAccount} />
}

Displays connected accounts in a dropdown. Falls back to ConnectButton when no account is selected.

// Display account balance with faucet link
import { AccountBalance } from '@/components/web3/account-balance'

<AccountBalance />

Shows the spendable balance of the connected account. Includes a faucet button for testnet chains.

// Network switching component
import { ChainSelect } from '@/components/web3/chain-select'

function MyComponent() {
const [chainId, setChainId] = useState<ChainId>('dev')

return <ChainSelect chainId={chainId} setChainId={setChainId} />
}

Dropdown for switching between configured blockchain networks.

// Account mapping for contract interactions
import { MapAccountButton } from '@/components/web3/map-account-button'

<MapAccountButton />

Button to map Substrate accounts to EVM addresses. Required before interacting with contracts. Only shows when account is not mapped.

Configuration

Chains

The chain configuration is centralized in /src/lib/reactive-dot/config.ts.

export const config = {
  chains: {
    dev: {
      descriptor: dev,
      provider: getWsProvider('ws://127.0.0.1:9944'),
    },
    pop: {
      descriptor: pop,
      provider: getWsProvider('wss://rpc1.paseo.popnetwork.xyz'),
    },
    // Add more chains here
  },
  wallets: [walletconnect()],
}

Contracts

Contract deployments are managed in /src/lib/inkathon/deployments.ts. They are cross-imported from the deployments/ folder in the contracts workspace.

// Imports from the contracts workspace
import { contracts } from '@polkadot-api/descriptors'
import * as flipperPassethub from 'contracts/deployments/flipper/passethub'
import * as flipperPop from 'contracts/deployments/flipper/pop'

export const flipper = {
  contract: contracts.flipper,
  evmAddresses: {
    pop: flipperPop.evmAddress,
    passethub: flipperPassethub.evmAddress,
    // Add more deployments here
  },
  ss58Addresses: {
    pop: flipperPop.ss58Address,
    passethub: flipperPassethub.ss58Address,
    // Add more deployments here
  },
}

export const deployments = {
  flipper,
  // Add more contracts here
}

Learn More