OddMaki
Customization

Custom Features

The Venue Starter ships features as self-contained modules — toggle them with env vars, extend them in place, or replace them with your own.

The Venue Starter organizes the app into feature modules under features/. Each module owns its routes, components, hooks, and SDK calls. Modules are cheaply removable (delete the folder + its imports) and cheaply replaceable (swap the implementation while keeping the route surface).

Feature Modules

The starter includes these modules out of the box:

ModuleWhat It Provides
authWallet connection via RainbowKit or Privy (email/social login)
walletDeposits, withdrawals, USDC balance UI
venueVenue home, stats, and setup guard
marketsMarket browser, filters, tag pages
market-detailPer-market page: pricing, chart, orderbook, order form
market-groupsGrouped-market rendering and NegRisk conversion UI
price-marketPyth-powered Up/Down and Strike market UI
price-chartCandlestick / line price history from the subgraph
tradingOrder form, slippage controls, batch quote UX
orderbookLive CLOB rendering and tick-level depth
market-holdersPosition viewer and redemption flow
resolutionUMA asserter UI and Pyth resolution triggers
leaderboardTrader leaderboards backed by subgraph analytics
trader-profilePublic profiles, PnL, open positions
market-creationCreate binary, grouped, and price markets
market-settingsTag/metadata editor for market creators and venue operators
access-controlDeploy and manage whitelist/NFT/token gates
realtimeSubgraph polling + websocket-style updates
theme-editorLive color-picker for theme.config.json

Each module is a plain directory of React components, hooks, and helpers — no framework of its own, no plugin system to learn.

Toggling Features with Env Vars

The common toggles are wired through config/venue.config.ts and flipped with env vars:

# Show the "Create Market" flow in the nav
NEXT_PUBLIC_ENABLE_MARKET_CREATION=true

# Expose the live theme editor (useful on staging)
NEXT_PUBLIC_ENABLE_THEME_EDITOR=true

# Choose a wallet auth provider
NEXT_PUBLIC_AUTH_PROVIDER=rainbowkit   # or "privy"

venueConfig.features is the single source of truth — read it in components instead of re-reading process.env:

import { venueConfig } from '@/config/venue.config';

export function Nav() {
  return (
    <nav>
      <Link href="/markets">Markets</Link>
      {venueConfig.features.enableMarketCreation && (
        <Link href="/create">Create</Link>
      )}
    </nav>
  );
}

Removing a Feature

Feature modules are designed to be deleted cleanly. For example, to drop the leaderboard:

  1. Delete features/leaderboard/
  2. Remove any import of it (your TypeScript build will tell you where)
  3. Remove the corresponding route from app/ if one exists

Because modules don't register with a central manifest, there's no plugin file to update.

Adding a Feature

Create a new folder under features/ and colocate everything the feature needs:

features/
  my-feature/
    components/
    hooks/
    queries.ts       // subgraph or SDK calls
    types.ts
    index.ts         // public API for the module

Expose routes by creating files under app/ that import from features/my-feature:

// app/my-feature/page.tsx
import { MyFeaturePage } from '@/features/my-feature';
export default MyFeaturePage;

Hook into the SDK client via the existing provider — useOddMakiClient() returns a fully configured client reading from NEXT_PUBLIC_VENUE_ID and the connected wallet.

Replacing a Feature

The common case is replacing the stock order form or market tile with your own. Because modules encapsulate their rendering, you can usually:

  1. Fork the module folder (e.g. copy features/trading to features/my-trading)
  2. Point the affected route at your fork
  3. Leave the original in place until you're ready to delete it

There's no inheritance or base-class model — just plain React components and SDK calls.

What's Next