Use when adding a new DAO to the Anticapture dashboard. Walks through enum registration, config creation, quorum label, icon setup, and wiring — with exact file paths and a worked example (FLUID).
Use when adding a new DAO to the Anticapture dashboard. Walks through enum registration, config creation, quorum label, icon setup, and wiring — with exact file paths and a worked example (FLUID).
Add a DAO to the Dashboard
Use This Skill When
You need to add a new DAO to the dashboard.
A DAO already has indexer + API integration and now needs dashboard visibility.
You are debugging why a DAO does not appear in the dashboard navigation.
Prerequisites
Before starting, you need:
DAO ID: The uppercase identifier already present in the indexer/API enums (e.g. FLUID, LIL_NOUNS)
Contract addresses: Token, Governor, Timelock (from apps/api/src/lib/constants.ts or apps/indexer/src/lib/constants.ts)
Governance rules: Voting delay, period, quorum logic, vote change, cancel function, timelock — from the API client (apps/api/src/clients/<dao>/index.ts)
Chain: Which EVM chain (mainnet, arbitrum, scroll, etc.)
Brand colors: svgColor (foreground) and svgBgColor (background) hex values
If coming from the dao-integration skill, this is already done in its Step 1 (Enum Sync). Skip to step 2.
Add the DAO to DaoIdEnum in alphabetical order:
{
= ,
}
export
enum
DaoIdEnum
// ... existing entries ...
FLUID
"FLUID"
// <-- value must match indexer/API enums exactly
// ...
The enum value must be identical across indexer, API, and dashboard.
2. Add quorum label (apps/dashboard/shared/constants/labels.ts)
Pick the label the UI shows for the DAO's quorum calculation. Reuse a generic entry
(QUORUM_CALCULATION_TYPES.TOTAL_SUPPLY, .DELEGATE_SUPPLY) when it fits — FLUID
reuses TOTAL_SUPPLY. Only add a DAO-specific entry when the calculation is unusual
(like SCROLL: "0.21% Total Supply"):
exportconstQUORUM_CALCULATION_TYPES = {
// ... existing entries ...NEW_DAO: "0.5% Total Supply", // only if no generic label fits
};
3. Create DAO config (apps/dashboard/shared/dao-config/<dao>.ts)
Create the config file exporting a DaoConfiguration object. Reference file: apps/dashboard/shared/dao-config/fluid.ts.
import { mainnet } from"viem/chains";
import { MainnetIcon } from"@/shared/components/icons/MainnetIcon";
import { QUORUM_CALCULATION_TYPES } from"@/shared/constants/labels";
importtype { DaoConfiguration } from"@/shared/dao-config/types";
import { EnsOgIcon } from"@/shared/og/dao-og-icons"; // placeholder until real iconexportconstNEW_DAO: DaoConfiguration = {
name: "New DAO",
decimals: 18,
color: {
svgColor: "#...", // foreground/text colorsvgBgColor: "#...", // background/accent color
},
ogIcon: EnsOgIcon, // placeholder — replace with real OG icon later// icon: NewDaoIcon, // uncomment when icon component existsdaoOverview: {
token: "ERC20", // or "ERC721" for NFT-based DAOschain: { ...mainnet, icon: MainnetIcon },
contracts: {
governor: "0x...",
token: "0x...",
timelock: "0x...",
},
// Optional: governance platform link (proposal IDs get appended)govPlatform: {
name: "Tally",
url: "https://tally.xyz/gov/<dao>/proposal/",
},
// Optional: Snapshot space// snapshot: "https://snapshot.box/#/s:<dao>.eth/proposals",// Optional: direct link to cancel function on Etherscan// cancelFunction: "https://etherscan.io/address/0x...#writeContract#F1",rules: {
delay: true, // has voting delay?changeVote: false, // can voters change their vote?timelock: true, // has timelock?cancelFunction: false, // has public cancel function?logic: "For", // "For" | "For + Abstain" | "For + Abstain + Against" | "All Votes Cast"quorumCalculation: QUORUM_CALCULATION_TYPES.TOTAL_SUPPLY, // or the label from step 2// proposalThreshold: "100K $TOKEN", // optional display string
},
},
// Feature flags — enable based on what the indexer/API supportstokenDistribution: true,
dataTables: true,
activityFeed: true,
governancePage: true,
// resilienceStages: true, // requires governanceImplementation fields// riskAnalysis: true, // requires governanceImplementation fields// serviceProviders: true, // if DAO has service provider data
};
Key decisions for the config
Field
How to determine
token
"ERC20" or "ERC721" — check the indexer's token handler
logic
Check calculateQuorum() in apps/api/src/clients/<dao>/index.ts
delay / timelock
Check if governor has voting delay > 0 and a timelock contract
changeVote
Check if governor supports castVote override (rare, most are false)
cancelFunction
Check if there's a public cancel() on the governor or timelock
Feature flags
Enable tokenDistribution, dataTables, governancePage for any DAO with full indexer+API. Only enable resilienceStages/riskAnalysis if governanceImplementation fields are populated
Variations by DAO type
Type
Config differences
Example
Standard ERC20 + Governor
Straightforward, follow FLUID/COMP
FLUID, ENS, UNI
ERC721 (NFT)
token: "ERC721", add notSupportedMetrics for CEX/DEX/lending, priceDisclaimer
NOUNS
Multi-token
contracts.token is an array of { label, address }
AAVE
Multi-chain
Import chain from viem/chains (e.g. scroll, arbitrum), use chain-specific icon
SCR, ARB
No governor
Omit governor from contracts, disable governancePage
ARB
Minimal (data tables only)
Only set dataTables: true, skip other feature flags
b. OG icon — Add to apps/dashboard/shared/og/dao-og-icons.tsx:
constFILL = "#EC762E"; // Anticapture accent orange — must use this colorexportfunctionFluidOgIcon({ size }: { size: number }) {
return (
<svgwidth={size}height={size}viewBox="0 0 40 40"fill="none">
{/* Same paths as main icon but with fill={FILL} */}
</svg>
);
}
If you don't have the logo yet, use any existing OG icon as a placeholder (e.g. EnsOgIcon) and omit the icon field entirely. The dashboard renders without it.
6. Governance implementation (optional, for risk analysis)
For full resilience stages and risk analysis, add governanceImplementation and attackExposure fields. See apps/dashboard/shared/dao-config/comp.ts or apps/dashboard/shared/dao-config/obol.ts as comprehensive examples. This requires manual security assessment and should be done separately.
Verification
pnpm dashboard typecheck
pnpm dashboard lint
Both must pass with 0 errors. Pre-existing warnings are acceptable.