SecondPage publishing accepts static file bundles, not renderer sections.
Minimum page
{
"title": "Project Brief",
"files": [
{
"path": "index.html",
"content_type": "text/html; charset=utf-8",
"content_base64": "PCFkb2N0eXBlIGh0bWw+PGh0bWw+Li4uPC9odG1sPg=="
}
]
}
Multi-file app
Use normal relative asset references from index.html:
<link rel="stylesheet" href="styles.css">
<script src="app.js" defer></script>
<img src="assets/chart.png" alt="Revenue chart">
Then submit all referenced files:
{
"title": "Interactive Dashboard",
"entrypoint": "index.html",
"files": [
{ "path": "index.html", "content_type": "text/html; charset=utf-8", "content_base64": "..." },
{ "path": "styles.css", "content_type": "text/css; charset=utf-8", "content_base64": "..." },
{ "path": "app.js", "content_type": "text/javascript; charset=utf-8", "content_base64": "..." },
{ "path": "assets/chart.png", "content_type": "image/png", "content_base64": "..." }
]
}
Semantic edit targets
For fresh generated pages, stamp important editable regions with stable names.
Use readable id, useful aria-label, and data-review-target-id attributes
on sections, hero blocks, headings, CTAs, repeated cards, charts, tables, forms,
nav items, and deck frames. These markers help Turner understand comments like
"make this card more premium" or "rewrite this CTA" without guessing from a
generic <div>.
<section id="hero" data-review-target-id="hero" aria-label="Hero section">
<h1 id="hero-heading" data-review-target-id="hero-heading">Launch plan</h1>
<a id="hero-primary-cta" data-review-target-id="hero-primary-cta" href="#contact">
Book a walkthrough
</a>
</section>
Deck bundle
For new decks, prefer prepare_deck; it creates this supported structure
without changing slide HTML:
<!doctype html>
<html data-sp-document-type="deck">
<body>
<main data-secondpage-deck data-sp-canvas-width="1280" data-sp-canvas-height="720">
<section id="sp-slide-slide-1" data-sp-frame data-sp-slide-id="slide-1">
<h1>Opening idea</h1>
</section>
<section id="sp-slide-slide-2" data-sp-frame data-sp-slide-id="slide-2">
<h1>Second idea</h1>
</section>
</main>
</body>
</html>
Every slide root needs a stable data-sp-slide-id. Publish with
presentation: { "intent": "deck" }. A successful publish is not readiness
evidence; only presentation.status: "ready" verifies presentation controls for
that version.
Updating safely
- Read the current complete bundle. If
file_bundleis null, export it and retain the exported version ID and manifest; verify referenced file bytes before editing. - For a default-route bundle, submit every file with the matching
base_version_id. - For custom entrypoints or routes, follow Publishing and revisions and preserve the manifest in both signed-upload calls. If the client cannot PUT files, hand off that upload.
- On
version_conflict, re-read/export and reconcile before retrying.
Do not send only the changed file. Updates are full bundle replacements.
Practical guidance
- Use
index.htmlas the entrypoint unless there is a strong reason not to. - Keep asset paths stable between versions when possible.
- Put generated CSS and JS in separate files for easier future updates.
- Inline only tiny assets. Use
create_media_uploadfor larger images or original video files, and keep normal CSS/JS/fonts/data as separate bundle files when they fit the payload limits. - When using direct media uploads, reference the returned
asset_urlin HTML and pass the completed IDs asmedia_asset_idsoncreate_pageorupdate_pagewhen you want explicit claiming. - If the user gave you an existing HTML export, publish the export as-is rather than translating it into a SecondPage-specific structure.