Design doc derived from
jun-19-verex.md. Reference UI:docs/images/verex-ui/homepage.png(Polymarket-style). (2026-06-23)
| # | Area | Status |
|—|——|——–|
| 1 | Basic Web UI — Kalshi-referenced, binary markets, real CTF contracts on anvil | ✅ built 2026-07-07 (shadcn UI + on-chain trading; see addendum 2) |
| 2 | Deploy to GCP + Cloud SQL DB + domain verex.jaylabs.xyz | ✅ complete — verex-api/verex-web live on Cloud Run, Cloud SQL wired, Sepolia trading live (chain decision resolved: (a) testnet); custom domain routed via Firebase Hosting (jul-25 5278191, prod routing jul-27 9921e23) |
| 3 | Portfolio page + market resolution (operator #0 as admin) | ✅ implemented + verified 2026-07-20 — details/jul-20-portfolio-resolution-design.md |
| 4 | Trade/resolution latency UX (chained on-chain txs feel slow on a real chain) | ✅ complete 2026-07-28 — #1 (demo-wallet pre-warming) + #2 (optimistic trade UI) done and verified live; leftover #3 (ResolvePanel optimism) and #4 (SSE) are superseded by the jul-28 async-settlement design (jul-28-verex-design.md Task C) — details/jul-22-trade-resolution-latency-ux.md |
| 5 | Per-environment contract isolation (separate backbone per local/test/production, not shared) | ✅ complete — separate test/prod backbones recorded in packages/contracts/deployments.json and enforced by the seed’s VEREX_DEPLOY_TARGET manifest + preflight; residual polish rides with future deploy work — details/jul-22-per-environment-contract-isolation.md |
| Topic | Proposed | Note |
|——-|———-|——|
| Web app | packages/web (Next.js 14, App Router) | existing scaffold (layout.tsx, page.tsx) |
| Data layer | DB-only → real CTF contracts (anvil) + DB mirror | superseded 2026-07-07 per jay: “use real contract for the market” |
| DB | Cloud SQL for PostgreSQL + Prisma | consistent with rabbit; verex has no DB yet |
| API | Next.js route handlers + Prisma in web | simplest for DB-only; alt = existing packages/api (Fastify) — open Q |
| Market type | Categorical (N outcomes; binary = N=2) | per spec |
| Domain | verex.jaylabs.xyz (subdomain) → Cloud Run | spec names this exact host |
| Deploy pattern | mirror rabbit scripts/deploy.sh (secrets → Secret Manager) | reuse known-good flow |
| UI kit | shadcn/ui + Tailwind | see Task 1 addendum — research + legal-risk notes |
💸 Cost: Cloud SQL bills monthly even when idle (~$8–10+ smallest tier).
Build a Polymarket-style UI driven entirely by the database (no contract integration yet).
docs/images/verex-ui/homepage.png)Market.category)./market/[slug]): all outcomes + prices, chart, description, and a
(mock) trade panel — buys recorded in the DB, no on-chain calls.// prisma/schema.prisma
generator client { provider = "prisma-client-js" }
datasource db { provider = "postgresql"; url = env("DATABASE_URL") }
enum MarketStatus { OPEN RESOLVED CANCELLED }
model Market {
id String @id @default(cuid())
slug String @unique
title String
description String?
category String? // "Politics","Sports","Crypto"…
imageUrl String?
status MarketStatus @default(OPEN)
volume Decimal @default(0) @db.Decimal(20, 2)
closesAt DateTime?
resolvedOutcomeId String? // winning outcome once RESOLVED
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
outcomes Outcome[]
@@index([category, status])
}
model Outcome {
id String @id @default(cuid())
marketId String
market Market @relation(fields: [marketId], references: [id], onDelete: Cascade)
label String // "Yes"/"No" or "Candidate A"…
price Decimal @db.Decimal(10, 6) // implied probability 0..1
sortOrder Int @default(0)
@@index([marketId])
}
Optional later: PricePoint (chart history), Position/Trade (mock trading per user).
Open: include mock trading in v1, or read-only display first?
| You (jay) | Me (Claude) |
|—|—|
| Confirm API choice (Next.js routes vs packages/api) | Add Prisma + schema + migration |
| Confirm v1 scope: read-only vs mock trading | Build homepage (tabs, featured, grid) + market detail |
| Approve seed markets (how many / which categories) | Seed sample categorical markets to match the screenshot |
| | Wire list/detail API routes (DB-backed) |
Current packages/web is bare Next.js 14 (no Tailwind, no component lib, hand-rolled CSS) — the
source of the “awkward” look. Research summary (2026 landscape):
| Option | Fit for Verex | Verdict |
|---|---|---|
| shadcn/ui (+ Tailwind, Radix primitives) | De facto standard for Next.js; copy-in code you own (no dep lock-in) → full freedom to build our own visual identity; shadcn charts (Recharts) covers the probability chart; a11y from Radix |
✅ pick |
| Mantine | Batteries-included, strong for data-dense B2B dashboards; own styling system (not Tailwind) | good, but heavier identity to override |
| MUI | Enterprise breadth (data grid etc.) | Material look fights a Polymarket-style feed |
| HeroUI / daisyUI / Aceternity | lighter or animation-focused | not aimed at data-dense trading UI |
Why shadcn specifically for us: (1) 2026 trend is headless/Tailwind-first — shadcn is its center of gravity, best AI-tooling + ecosystem support; (2) copied-in source = we can diverge the theme tokens (colors/typography/radius) from both Polymarket and any prior work, which is exactly what the risk section below needs; (3) jay already knows it — lowest learning cost.
Implementation note: Task 1 build starts with tailwindcss + shadcn init in packages/web
(theme tokens defined once in globals.css), then the screens in the spec above.
Context: jay built a similar Polymarket-style UI with shadcn at a previous company; concern is a future claim that Verex copies that work. Not legal advice — framework + hygiene below; for real assurance have an IP/employment lawyer read the old employment contract.
How the law sees it (US frame; KR analog in parens):
Mitigation checklist (do these; mostly already repo policy):
docs/history/ decision log (already the
convention) shows independent creation with dates — the strongest practical defense.Sources: Untitled UI — React component libraries 2026 · Dualite — shadcn/MUI/Radix compared · C&C IP — UI/UX legal protection: trade dress vs copyright · Harvard — look & feel: copyright or trade dress · Proskauer — website trade dress claims
We can use this screen shots from Kalshi
1) Main page

We can use this screen shot from Kalshi
—
Implemented on branch claude/deploy-export-log per jay’s “working version, complete features” directive:
DeployCTF.s.sol, then prepareCondition → registerToken → operator splits
10k USDC inventory per market). Addresses live in the DB (ChainConfig) — no env coordination.CTFExchange.fillOrder tx — the user (demo anvil
account 1–5, keys server-side) signs the maker order, the operator (account 0) fills from its
inventory. Auto-faucet keeps the flow one-click. DB mirrors each fill: price impact (linear,
L=2000 USDC), volume, trade log, chart point. Production wallet path (MetaMask → AA session
keys) stays the S7 track.anvil → pnpm --filter @verex/api db:reset (migrate + deploy + seed) →
pnpm --filter @verex/api dev → pnpm --filter @verex/web dev.⚠️ New decision needed first — where does the chain live in the cloud? Task 1 now trades
against anvil, which is local-only. Options for verex.jaylabs.xyz:
| Option | What it means | Trade-off |
|---|---|---|
| (a) Testnet (recommended) | Deploy CTF backbone to a public testnet (e.g. Base Sepolia); operator key in Secret Manager | Real public chain, demoable anywhere; needs faucet ETH + key management |
| (b) Hosted anvil | Run anvil in a Cloud Run/GCE container | Fast, but state resets on restart — toy-grade |
| (c) DB-only fallback | Cloud version reads DB, trading disabled (“local demo only” banner) | Cheapest; loses the headline feature in the cloud |
jay does (needs your accounts/access):
doubletree-498007 (rabbit) or create a new one; confirm billing is on.jaylabs.xyz’s
nameservers are ns-cloud-e*.googledomains.com — the zone lives in Cloud DNS, so Claude
can add the verex record via gcloud dns. jay’s only possible action: click Verify in
Google Search Console if Cloud Run demands domain-ownership verification (Claude adds the TXT
record; the verify click needs jay’s Google account).Claude does (scriptable, no jay input needed):
DATABASE_URL in Secret Manager.verex-api (Fastify — trading needs it in the cloud now) and verex-web (Next.js), with API_URL wired web→api.scripts/deploy.sh mirroring rabbit’s shape (build → push secrets → gcloud run deploy --set-secrets).verex.jaylabs.xyz → verex-web; hand jay the DNS record to add.DeployCTF.s.sol to the testnet, re-run the seed against it, store operator key in Secret Manager.verex.jaylabs.xyz)DATABASE_URL → Secret Manager.packages/web; connect to Cloud SQL.verex.jaylabs.xyz → the Cloud Run service.deploy.sh shape (push secrets to Secret Manager, --set-secrets).| You (jay) | Me (Claude) |
|—|—|
| Confirm billing enabled on the GCP project | Create Cloud SQL instance + DB + user |
| Edit DNS at the registrar — zone is on Cloud DNS; only click Verify in Search Console if prompted | Write verex/scripts/deploy.sh (mirror rabbit) |
| (DNS record itself: Claude adds via gcloud dns) | Run gcloud run domain-mappings create for verex.jaylabs.xyz + add the CNAME in Cloud DNS |
| Update OAuth redirect URI if login is used | Set AUTH_URL, push secrets, deploy |
Which GCP project for verex? Rabbit uses
doubletree-498007; reuse it or a separate project?
docs/history/ (per verex convention).claude/<topic>.packages/api?doubletree-498007 or a separate project for verex?Say “go” and I’ll build everything on a single branch — claude/jun-19-verex
(Tasks 1 + 2 together) — pausing for review before any commit. Per the task’s
“after the implementation”: summarize in docs/history/, push, open a PR, then merge.