{"topic":"asset-handoff","content":"# Asset handoff: media and rich content in a Page bundle\n\n**Architectural invariant**: agents own asset generation and bundle assembly;\nSecondPage stores and serves the exact files they submit. SecondPage does not\ngenerate images, scrape the web, render section objects, or inject a chart or\nmap runtime. Choose the right asset path, include accessible HTML, and validate\nthe completed bundle before publishing.\n\n## Include ordinary assets in the bundle\n\nFor CSS, JavaScript, fonts, small images, charts, maps, and data files, use\nnormal relative paths and submit every referenced file with the Page. A static\nmap can be an image; an interactive map, chart, or table is HTML and JavaScript\nthat you author and ship with the bundle. Do not assume SecondPage has a\nprovider key, an installed UI library, or a renderer for a section type.\n\n```html\n<figure id=\"neighborhood-map\" data-review-target-id=\"neighborhood-map\">\n  <img src=\"assets/tokyo-map.webp\" alt=\"Six Tokyo neighborhoods on a map\">\n  <figcaption>Six neighborhoods we toured</figcaption>\n</figure>\n```\n\nUse semantic structure and a text alternative for rich visuals. An interactive\ncontrol must work with a keyboard and preserve a useful non-JavaScript reading\npath where practical.\n\n## Direct media uploads\n\nFor larger images or original video files, do not put the bytes into the Page\nbundle as base64. Use `create_media_upload`, upload the file bytes to the\nreturned `upload_url` with HTTP `PUT` and the returned `required_headers`, then\ncall `complete_media_upload`. Reference the returned `asset_url` in the Page:\n\n```html\n<img src=\"/_sp/media/asset-id/photo.webp\" alt=\"Product detail\">\n<video src=\"/_sp/media/asset-id/demo.mp4\" controls></video>\n```\n\nUploaded media is Page-scoped. It inherits the Page's visibility after the Page\nis published or updated with that `asset_url`. For deterministic claiming, pass\nthe completed asset IDs as `media_asset_ids` on an `html` or inline-file\n`create_page` or `update_page` call; the server also detects approved\n`/_sp/media/...` URLs in submitted HTML.\n\n## Page upload continuations\n\nFor a multi-file Page when HTTP is available, use the same Page tools with an\nupload continuation. For one self-contained document use `html`; use inline\nfiles only when HTTP is unavailable:\n\n1. Call `create_page` or `update_page` with `upload_files`, including every\n   file's relative `path`, `content_type`, `byte_size`, and lowercase SHA-256.\n2. Upload only files whose response status is `upload_required` using HTTP\n   `PUT` to `upload_url` and the returned `required_headers`.\n3. Call the same tool again with `upload_session_id`, retaining the original\n   metadata and, for updates, the required `base_version_id`. A manifest is\n   optional for the default `index.html` route; include one for multiple routes\n   or a custom entrypoint. Include `asset_paths` when known.\n4. Use the returned deployment status, or `read_page`, to confirm the Page.\n\nPage deployment assets are content-addressed and deduplicated within the\norganization by SHA-256. Re-deploys should upload only changed files. Scalable\nPages are static-only in v1.\n\n## What SecondPage never does\n\n- Call Mapbox, Tavily, Firecrawl, OpenAI Image Generation, Replicate, or other\n  external APIs on your behalf\n- Generate images or scrape web pages\n- Transform, repair, or add functionality to the HTML, CSS, JavaScript, or\n  media the agent supplies\n- Host arbitrary unclaimed files. SecondPage stores Page-scoped image/video\n  uploads claimed by a Page and deployment assets claimed by a verified Page\n  deployment; everything else remains in your tool environment or at an\n  external URL.\n\nThese concerns remain in **your tool environment**. SecondPage's job is to\npublish the complete, validated Page bundle you produce.\n"}