Structure vs skin
venue-kit ships components, hooks and a token contract on npm with no styling stack required. Skin it with plain CSS, or copy the Tailwind blocks from the registry. Restyle freely; never rewire the trade path.
@prophecy-dev/venue-kit is the structural half of a venue: VenueShell, MarketGrid,
MarketCard, MarketDetail, CategoryNav, Leaderboard, PositionsTable, search and browse.
It is deliberately not a brand. Everything visible is skinned from one ProphecyTheme through the
--pc-* custom properties the provider publishes, so a venue can look like anything without forking
a component. See Venue Kit for a full venue built from it with zero custom CSS, and
Theming for the token contract.
The kit’s own stylesheet lives in a low-priority cascade layer (@layer prophecy-venue-kit), so any
unlayered CSS in your venue beats it — no !important, no specificity war.
Two ways to skin it
The npm package needs no styling stack. It ships components, headless hooks (useMarketBrowse,
usePositions, …) that return read-only derived data plus prop-getters, state primitives, its own
stylesheet, and the --pc-* token contract. Install it and you have a working, themeable venue with
nothing else in your build.
From there, two routes — pick by what your team already uses:
1. Plain CSS over the tokens. Write ordinary CSS against the --pc-* variables, or hand the kit
your own class names. No build-time styling dependency at all.
This is what Prophecy Studio generates: its venues compose venue-kit’s npm components and style
them with a plain globals.css. If you’re wondering what the default path looks like, it’s this one
— not the registry.
2. The shadcn registry. Styled markup copied into your venue and owned by you: VenueShell,
MarketCard, a whole browse page, and per-venue themes. Served from
cdn.prophecyhosting.com/r/*.json, installed the ordinary shadcn way:
npx shadcn@latest add https://cdn.prophecyhosting.com/r/venue-shell.json
npx shadcn@latest add https://cdn.prophecyhosting.com/r/market-card.json
npx shadcn@latest add https://cdn.prophecyhosting.com/r/browse-page.json
These blocks are Tailwind v4, so this route assumes Tailwind. Take it if you’re already on that stack and want editable markup; skip it entirely otherwise.
Either way, one line does not move: the trade handler stays on npm. Markup is exactly the thing a person or an AI agent should rewrite wholesale; a multi-step async money flow is exactly the thing neither should re-implement by accident. Copied code silently drops wiring — so skins are copyable and the money path isn’t.
If you do use Tailwind
| npm package | registry blocks | |
|---|---|---|
| React | 19 (peer allows ≥18) | 19 |
| Styling | none required — self-contained CSS in a cascade layer | Tailwind v4 + shadcn CLI |
| Ownership | ours, semver, patched centrally | yours, once copied |
| Used by | Studio’s generated venues, the reference venue | teams already on Tailwind |
venue-kit-theme is the bridge: it maps the runtime --pc-*
brand tokens into Tailwind’s @theme, so the skins use them as ordinary utilities — bg-card,
text-foreground, bg-primary, rounded-card, font-display, and the --spacing density scale.
Import it once after Tailwind, and a theme change at runtime restyles the utilities with it.
npx shadcn@latest add https://cdn.prophecyhosting.com/r/venue-kit-theme.json
Nothing else changes if you skip this: the token contract is plain CSS custom properties and the components carry their own stylesheet, so the kit is fully themeable without Tailwind anywhere.
The one rule
Restyle, never rewire.
Layout, copy, order, density, colour — yours. The quote, the predict path and the checkout drawer stay inside the kit’s hooks. Rebuild those and you’ve taken ownership of pricing, slippage, session handling and the gasless path — four things that change on our side and would silently rot on yours.
The rules the kit already knows
Behaviour lives in the kit precisely so every venue gets it right at once. Two worth knowing, because they’ve each caused real bugs:
- Tradeable, not un-resolved. The grid shows tradeable markets by default. A voided market, or
one past its deadline, is still un-resolved — offering it sends a user into a guaranteed on-chain
revert. Gate interaction on
isTradeable(). isClosed()means settled. Resolved or voided — not “closed for trading”. UseisTradeable()for the interaction question. PassincludeSettledif you deliberately want history.- A position’s entry price is
nullafter any sale, not a number.costBasisis gross of sales whilesharesis what remains, so the ratio stops being a price — a real row rendered 2526% for a share that settles between 0 and 1.usePositionRowsreturnsnullthere and you render an em dash. The same applies to P&L on a trade that hasn’t filled:null, never0.
Bring your own card, not your own list
The one seam worth knowing by name. A venue that wanted its own positions card had only renderRow,
which fills a single <tr> — so it forked the whole list instead: the hook call, the states, the row.
The fork compiled, looked right, and silently dropped the sell affordance, so that venue shipped a
book with no way to exit a position at all. Copied code drops wiring; that is the same rule as
above, one layer up.
// Your markup. The kit's fetching, states, in-flight rows, and sell.
<PositionsTable wallet={w} renderCard={(row) => <MyCard row={row} />} />
// Or take the rows headlessly and build the whole surface.
const { rows, loading, isEmpty } = usePositionRows(wallet)
A row arrives already decided — status ('confirmed' / 'confirming'), entry, now, pnl,
sellable, a wired sell(), and every label formatted at the market’s own decimals. The sell
control renders as your node’s sibling, not inside it, because a card is very often itself a
<button> and a nested button is invalid HTML.
When you outgrow it
Compose the kit’s pieces yourself rather than replacing them: the components take the data you already have from the hooks. The step after that is generating the venue — which is what Prophecy Studio does, over this same kit.