inkathoninkathon

Frontend Architecture

Deep dive into the Next.js frontend structure and libraries

Tech Stack

The frontend is built with modern, production-ready technologies:

TechnologyVersionPurpose
Next.js15React framework with App Router
React19UI library with latest features
TypeScript5.9Type safety and better DX
Tailwind CSSv4Utility-first styling
shadcn/uiLatestHigh-quality UI components
PAPI1.15Type-safe Polkadot API
ReactiveDOT0.45Reactive Web3 state management

Project Structure

package.json
next.config.ts
tailwind.config.ts
tsconfig.json

Available Commands

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

# Development
bun run dev          # Start dev server with Turbo
bun run build        # Build for production
bun run start        # Start production server

# Code Quality
bun run lint         # Run Biome + Prettier checks
bun run lint:fix     # Auto-fix linting issues
bun run typecheck    # TypeScript type checking

# Maintenance
bun run clean        # Remove build artifacts

Key Components

Web3 Components

// Wallet connection and account selection
import { AccountSelect } from '@/components/web3/account-select'

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

<ChainSelect />
// Smart contract interaction UI
import { ContractCard } from '@/components/web3/contract-card'

<ContractCard contractAddress="..." />

ReactiveDOT Configuration

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()],
}

Contract Integration

Contract deployments are managed in /src/lib/inkathon/deployments.ts:

import { evmAddress as flipperEvmDev, ss58Address as flipperSs58Dev } from 'contracts/deployments/flipper/dev'
import { evmAddress as flipperEvmPop, ss58Address as flipperSs58Pop } from 'contracts/deployments/flipper/pop'

export const contractDeployments = {
  flipper: {
    dev: { evmAddress: flipperEvmDev, ss58Address: flipperSs58Dev },
    pop: { evmAddress: flipperEvmPop, ss58Address: flipperSs58Pop },
  },
}

Styling with Tailwind CSS v4

The project uses the latest Tailwind CSS v4 with several enhancements:

  • CSS-in-JS: Direct CSS variable usage
  • Mobile-first: Responsive design by default
  • Dark mode: Built-in theme switching
  • Custom utilities: Extended with tw-animate

Theme Configuration

/* globals.css */
@import "tailwindcss";

@theme {
  --color-primary: #e6007a;
  --color-background: #1a1a1a;
  /* Custom theme variables */
}

Component Patterns

Server Components by Default

// Prefer server components
export function Header() {
  return <header>...</header>
}

Client Components When Needed

'use client'

// Only for interactive components
export function WalletButton() {
  const [connected, setConnected] = useState(false)
  // ...
}

Suspense Boundaries

import { Suspense } from 'react'
import { AccountSelectSkeleton } from './skeletons'

<Suspense fallback={<AccountSelectSkeleton />}>
  <AccountSelect />
</Suspense>

Environment Variables

Configure the frontend with these environment variables:

VariableDescriptionExample
NEXT_PUBLIC_CHAINDefault chainpop
NEXT_PUBLIC_RPC_URLCustom RPC endpointwss://...

Performance Optimizations

  1. Turbo Mode: Enabled by default for faster builds
  2. App Router: Leverages React Server Components
  3. Code Splitting: Automatic with Next.js
  4. Image Optimization: Built-in Next.js Image component
  5. Font Optimization: Geist font with next/font

Best Practices

  1. Use functional components with the function keyword
  2. Prefer named exports over default exports
  3. Keep components small and focused
  4. Use TypeScript strictly for better type safety
  5. Minimize 'use client' directives
  6. Wrap async components in Suspense boundaries
  7. Follow kebab-case for file naming