<iframe> tag. There is no JavaScript to install and no events to listen for. Pick a widget, point it at a basket, choose a width, and you are done.
The URL
<widget-name> is one of hero-card, performance, overview, or pill-row. <slug> is the basket’s slug, which is the same value used in app.cesto.co/product/<slug>.
The four widgets
| Widget | <widget-name> | Aspect ratio | Min width |
|---|---|---|---|
| Hero card | hero-card | 5 : 4 | 360 px |
| Performance | performance | 15 : 8 | 540 px |
| Overview | overview | 2 : 1 | 480 px |
| Pill row | pill-row | 15 : 2 | 300 px |
Embed snippet
Drop this into any HTML page. Replacehero-card and ai-leaders-portfolio with the widget and basket slug you want.
app.cesto.co/product/<slug> in a new tab when the user taps Invest.
Finding a basket slug
Every basket onapp.cesto.co has a slug in its URL. Open the basket on the website and copy the last path segment, which is the slug:
ai-leaders-portfolio. You can also discover slugs programmatically through the Cesto API at GET /products.
Sizing
The widget’s interior uses CSS container queries, so it scales proportionally with whatever pixel width its parent column gives it. The recommended pattern iswidth: 100% plus aspect-ratio, letting the page decide width and letting the aspect ratio decide height.
- Keep
width: 100%whenever possible and let the host column drive the width. The widget will reflow itself. - Use
loading="lazy"for widgets below the fold so the iframe defers until it scrolls into view. - The widget host sets
X-Frame-Options: ALLOWALLandframe-ancestors *, so any origin can embed it.
Theming
By default, every widget renders Cesto’s canonical dark theme, so it looks consistent wherever it’s embedded. If you want it to match your own site, you can override individual design tokens: colors, corner radius, fonts, and spacing.Theme fields
Every field is optional. Pass any subset; anything you don’t set keeps the Cesto default.| Field | Type | What it controls |
|---|---|---|
accent / accentForeground | CSS color | Primary action color, and the text on it |
background / foreground | CSS color | Surface, and body text |
muted / mutedForeground | CSS color | Secondary surfaces, and their text |
border | CSS color | Borders and dividers |
positive / negative | CSS color | Gains and losses |
radius | px or length | Corner rounding |
fontFamily / fontFamilyMono | font stack | Text and numeric fonts |
padding | px or length | Outer content padding |
maxWidth | none or length | Cap on content width |
A bad value can’t break a widget. Each field is validated on its own: an invalid value (say,
accent=notacolor) is dropped and falls back to the Cesto default, and unknown params are ignored.Setting a theme
The simplest way is to add the tokens as query params on the iframe URL, right alongsidebasket. Remember to URL-encode colors (# becomes %23):
Live theming (optional)
To change the theme after load (for example, to follow a light/dark toggle on your page), the optional@cesto/embed-sdk host helper lets you push config in live and auto-resizes the iframe to fit its content:
What stays fixed
Theming covers look, not content. A widget’s copy, its data, and the Invest destination (app.cesto.co/product/<slug>) are fixed and stay consistent with the rest of the Cesto product.
If you need anything beyond a themeable basket card on your page, that is a different surface and not a widget.
Next
Open the playground
Try every widget against any live basket, right inside the docs.