> Legacy V1 HTML handoff. For new decks use [Hedy Deck 2.0](/docs/hedydeck-v2.md) and [Studio](/studio). The rules below apply only to the earlier HTML format.

# Hand a deck to Hedy Deck

Create one `.hedydeck` file using [the format](/docs/deck-format-v1.md), validate it, then open it in Hedy Deck. No login, Hedy MCP connector, project access or admin credential is needed. Keep the downloadable source file so the user or another LLM can revise it later.

## Universal file handoff

Give the user `your-title.hedydeck`. Its contents are the complete UTF-8 HTML source with inline CSS/assets, the `hedy:deck` version 1 marker and speaker notes. The user opens Hedy Deck and chooses Open a deck, or drags the file onto the library. The app validates and converts it locally, then opens the presenter.

Use a real file attachment rather than only a Markdown code block. Do not add `.html` to the filename. HTTP delivery should use `Content-Type: text/plain; charset=utf-8` and `Content-Disposition: attachment; filename="your-title.hedydeck"`. For example, [Hello World downloads as a deck](/download/hello-world.hedydeck). The same file is available as [plain text for LLMs](/examples/hello-world.hedydeck).

The extension keeps the file distinct from a web page; it does not automatically register an operating-system application. On browsers that support installed web app file handlers or Share targets, the user can choose Hedy Deck in the relevant system menu. Where that integration is absent, open or drop the file from the site.

## Small-deck link

For content with fewer than 200,000 compressed bytes, gzip the complete UTF-8 HTML file, base64-encode the compressed bytes, percent-encode that base64 text, then append `#deck=` and the encoded value to the Hedy Deck home URL. Do not use a query string. The expanded file must still be below 20 MiB.

For example, in Python (replace `origin` with this site's origin):

```python
import base64, gzip
from pathlib import Path
from urllib.parse import quote
origin = "https://hedydeck.com"
source = Path("hello-world.hedydeck").read_bytes()
packed = gzip.compress(source, mtime=0)
assert len(packed) < 200_000
url = origin + "/#deck=" + quote(base64.b64encode(packed).decode("ascii"), safe="")
```

The fragment is not sent to the site's HTTP server. Anyone holding the complete link has the deck source, so share it only with intended recipients. The app decompresses, validates and imports locally. If a chat client truncates a long link or the browser lacks decompression support, use the `.hedydeck` attachment.

## Temporary drop code

A host can choose Receive from an agent and share its upload link without creating an account. The link is `/validate?drop=CODE#token=UPLOAD_KEY`: `CODE` is six characters, and the fragment contains a private upload capability. Share the complete link with the intended sender, not just the code. This is separate from a live room's four-character viewing code. Treat the fragment as a secret; do not publish it in logs or examples.

The maximum source size is 2 MiB and the drop expires after 15 minutes. The receiving browser keeps a private capability to collect the file; knowing only the drop code does not grant collection access. Submission uses CAPTCHA in the browser, and server size, expiry and rate limits apply. Do not try to bypass a challenge or reuse a CAPTCHA token.

Use the complete browser upload link when a challenge is needed. The host keeps a separate collection capability. A public `POST /api/dropbox/CODE` accepts the validated HTML with `Content-Type: text/html`, `x-hedy-drop-key: UPLOAD_KEY` and `x-hedy-captcha-token: COMPLETED_CHALLENGE_TOKEN`. No account cookie is needed. The upload key comes only from the host-provided link; the CAPTCHA token must come from completing the site's challenge. The plain code grants neither upload nor collection access. Collection validates the content and consumes the single-use temporary source. If challenge completion is unavailable, use the direct file or fragment link instead. Never fabricate a CAPTCHA token.

## Page tools (WebMCP)

The home page, the presenter, `/validate` and every `/docs/` guide offer these four legacy HTML page tools. Browsers that expose `document.modelContext` (or `navigator.modelContext`) list them through WebMCP; in every browser they are also callable from page JavaScript as `await window.hedyDecks.tools.call(name, input)`, which takes a tool name and a plain object and returns the parsed result. Chrome's own `executeTool` wants the registered tool object and the input as a JSON string. See [page tools for agents](/docs/agent-tools-v1.md) for inputs, results, both calling conventions and manual equivalents.

- `deck_instructions` `{"topic": "essentials" | "full" | "starter" | "design" | "markdown" | "handoff"}` returns the authoring instructions; the essentials are also written into the tool's description, so a listing alone teaches the format.
- `create_deck` builds a deck from Hedy Markdown (`{"markdown": "…"}`) or an outline (`{"title", "slides": [{"title", "bullets", "text", "notes", "layout", …}]}`) on the kit, validates it exactly like `/validate`, exports self-contained `.hedydeck` v1 source and saves it to this browser's library; `"download": true` also saves the file, `"returnSource": true` returns the source, `"open": true` shows it. Failures return `issues` to fix.
- `validate_deck` `{"html": "complete source"}` runs the structural and visual checks in this browser without saving.
- `import_deck` `{"html": "complete source"}` validates, converts, saves locally and opens a finished `.hedydeck`.

These page-provided tools are optional; they are not the Hedy admin connector, and no connector is needed. Do not assume WebMCP exists in every browser: if the tools are not listed there, `window.hedyDecks.tools` still works from page JavaScript, and otherwise use the documented file picker, file drop, fragment link, `/validate` page or `POST /api/validate`. Do not invent an import API, navigate to a query-string payload, or declare success without observing the deck in the app.

## Validation and completion

`POST /api/validate` accepts `text/html` and returns structural results with issues `{slide,code,message,fix}`. Follow a structural pass with `/validate` in a real browser for dimensions, overflow and font/image loading. Fix every issue; inspect the slide previews. Do not claim visual verification from server validation alone.

A successful handoff ends with the user's deck open in the presenter, correct title and slide count, and readable notes. Keep the `.hedydeck` attachment available even when a convenience link or browser tool succeeds. To edit later, change the source file, revalidate and reopen it; do not edit generated slide images.
