Code pages
A code page is a coin page its creator writes in HTML and CSS instead of arranging tiles, placing apps with a <cd-app> tag. Code pages are not open to creators yet. This contract is fixed at version 1.0, so an app built for it now works on them when they open.
How your app shows
| Mode | What the page decides | What your app keeps |
|---|---|---|
| Hosted (every app) | Where your app's box is and how big, never under your minimum | Everything inside the box |
| Themed (if your manifest says so) | Hosted, plus the page's colours for the tokens you list | Your layout, words and behaviour |
Every app is hosted with nothing to declare: an app that works on a tile works on a code page. A page that asks for an app in a mode the app does not allow gets it hosted.
What a page can never do to your app
These hold on every code page, whatever its creator writes.
- It cannot shrink your app. A page sizes your box with
width,height, grid or flex, but never under your minimum:display.minWidthandminHeightif your manifest has them, else your smallest tile (120 px for each ofminColSpan, 60 px for each ofminRowSpanplus 10 px between rows). Our rule for it sits in a cascade layer that outranks every rule a page can write,!importantincluded. - It cannot style the inside of your app. A page's CSS is scoped to the page and stops at the edge of every app's box, so your prices, warnings and buttons look as you drew them. A themed app gets colours only through the tokens it lists.
- It cannot run code. A page's HTML is never put on the page as HTML. It is read into a tree of allowed elements and drawn by us, so there is nowhere for a script to be:
<script>,<iframe>,<form>,<svg>,on…handlers and inlinestyleare dropped. Links arehttps, relative ormailto; images arehttps; a page's ids are prefixed so none can stand in for one of ours. In its CSS,@import,@font-faceand@layerare dropped,url()ishttpsonly, and its animations are renamed so they cannot replace ours. - It cannot act for your app or the visitor. A page's button can do three things, and each opens our own sheet. A page cannot call your app, ask for a signature or take a payment.
- It cannot cover the coin page's own controls. A code page is contained:
position: fixedandz-indexwork inside the page and cannot reach over the Buy button, the menu or a wallet prompt.
The coin page's Content Security Policy allows inline scripts, so it is not what keeps a code page safe; these rules are. Your app keeps its own sandbox too, exactly as on a tile page: What your app must do.
Declaring themed
List the page colours your app takes in presentation.themeTokens:
"presentation": { "themeTokens": ["--cd-accent", "--cd-surface", "--cd-text"] }On a page that shows your app themed, each token you list arrives in the theme your app already gets, as the field below; the rest keep the visitor's theme. List only the ones your app reads.
| Token | Arrives as | What it colours |
|---|---|---|
--cd-accent | theme.accentColor | Accents and buttons |
--cd-surface | theme.cardBackground | The card your app sits on (we draw it under your box) |
--cd-text | theme.textPrimary | Body text |
--cd-text-muted | theme.textSecondary | Secondary text |
--cd-border | theme.borderColor | Borders and dividers |
No other token can be listed, and an empty list is refused: leave presentation out to be hosted only.
What a page writes
For reference: a page uses three tags of ours. Everything else is plain HTML and CSS.
<cd-app> places an installed app.
| Attribute | |
|---|---|
app | The app's id |
instance | Which one, for an app placed more than once |
mode | hosted (the default) or themed |
class, id, title, aria-*, data-* | As on any element, for the page's CSS |
A <cd-app> is empty: your app draws the whole box, and anything a page puts inside it is not shown.
<cd-data bind="…" format="…"> shows a value from the coin's own data, by the names the app SDK uses. A missing value shows —.
bind | |
|---|---|
symbol | The ticker, such as PEPE |
tokenName | The coin's full name |
description | The coin's description |
chainName | The chain, such as Base |
tokenAddress | The coin's contract address |
owner | The wallet that holds the page's crown |
status | The crown's status |
market.price | Price in US dollars |
market.marketCap | Market cap in US dollars |
market.volume24h | Trading volume over 24 hours, in US dollars |
market.liquidity | Liquidity in US dollars |
market.holders | How many wallets hold it |
market.totalSupply | Total supply |
market.circulatingSupply | Circulating supply |
market.txns24h | Trades over 24 hours |
market.priceChange1h | Price change over 1 hour, in percent |
market.priceChange6h | Price change over 6 hours, in percent |
market.priceChange24h | Price change over 24 hours, in percent |
format | Shows |
|---|---|
number (the default) | 12.3K |
usd | $0.0042 |
usd-compact | $1.2M |
percent | 5% |
<button cd-action="…"> runs one of our actions. A button with no action, or any other, does nothing.
cd-action | Opens |
|---|---|
buy | Our buy sheet for the coin |
sign-in | Our sign-in |
connect-wallet | Our wallet connection |
Example
A store app that takes the page's accent, surface and text colours declares, in its capp.json:
"minColSpan": 2,
"minRowSpan": 4,
"display": { "minWidth": 280, "minHeight": 320 },
"presentation": { "themeTokens": ["--cd-accent", "--cd-surface", "--cd-text"] }A page places it, themed, beside its own hero:
<main class="page">
<section class="hero">
<h1>$<cd-data bind="symbol"></cd-data></h1>
<p><cd-data bind="market.price" format="usd"></cd-data> ·
<cd-data bind="market.holders"></cd-data> holders</p>
<button cd-action="buy">Buy</button>
</section>
<cd-app app="my-store" mode="themed" class="store"></cd-app>
</main>.page {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 16px;
--cd-accent: #ff4fa3;
--cd-surface: #1b1030;
--cd-text: #fdf2ff;
}
.store { height: 420px; border-radius: 16px; }
@container page (max-width: 640px) {
.page { grid-template-columns: 1fr; }
}The store draws itself in the page's pink, dark purple and white. On a phone the page stacks it under the hero, and if the page had set height: 100px, the store would still be 320 px tall.
The schema and its versions
The manifest schema, presentation included, is published:
- the latest:
https://docs.chaindaddy.io/schemas/capp.schema.json - each version:
https://docs.chaindaddy.io/schemas/capp/<version>.json, starting athttps://docs.chaindaddy.io/schemas/capp/1.0.0.json
A published version never changes. A new field or value is a new minor version, and every manifest valid under an older version stays valid. A page drawing an app's UI itself, from data the app publishes, is planned for a later version; until then a manifest cannot declare it.