# Client presentation deck

Pitch clients with a living deck instead of a static export. Assemble your slides on a board, share it as a full-screen, click-through experience, and collect feedback inline. Reorder or swap a slide on the board and the deck updates itself, so the link you sent yesterday is never out of date.

![An interactive client presentation deck built on the Playbook API](/img/examples/presentation-deck.webp)

Live preview

**[Open the interactive preview →](/demos/presentation-deck/index.html)**  ·  a self-contained `index.html` you can click through in your browser (step through slides, read client comments) or download.

## The flow[​](#the-flow "Direct link to The flow")

1. Create a board, one asset per slide, in presentation order.
2. **Share** it for a client-facing, full-screen deck link.
3. **Embed** the deck in a proposal or send the link directly.
4. Collect client feedback per slide with **comments**.

## 1. Build the deck board[​](#1-build-the-deck-board "Direct link to 1. Build the deck board")

```
curl -X POST "https://api.playbook.com/v1/$ORG/boards" \

  -H "Authorization: Bearer $PLAYBOOK_TOKEN" \

  -H "Content-Type: application/json" \

  -d '{ "title": "Acme — Brand Refresh Pitch", "description": "Client presentation deck" }'
```

Add your slides in the order you want them presented. Rendered slides (exported from Figma, Keynote, or your design tool) upload just like any other asset:

```
curl -X POST "https://api.playbook.com/v1/$ORG/assets/batch_create_from_urls" \

  -H "Authorization: Bearer $PLAYBOOK_TOKEN" \

  -H "Content-Type: application/json" \

  -d '{

    "batch": {

      "collection_token": "acme-brand-refresh-pitch",

      "assets": [

        { "uuid": "1", "uri": "https://example.com/deck/01-cover.png", "title": "Cover" },

        { "uuid": "2", "uri": "https://example.com/deck/02-problem.png", "title": "The problem" },

        { "uuid": "3", "uri": "https://example.com/deck/03-direction.png", "title": "Creative direction" }

      ]

    }

  }'
```

Slides appear in the order they sit on the board, so arrange them there and the deck follows. For local files, see the signed-upload flow in [Uploading Assets](/docs/guides/upload.md).

## 2. Share the deck[​](#2-share-the-deck "Direct link to 2. Share the deck")

```
curl -X POST "https://api.playbook.com/v1/$ORG/boards/acme-brand-refresh-pitch/share" \

  -H "Authorization: Bearer $PLAYBOOK_TOKEN"
```

```
{ "data": { "url": "https://playbook.com/s/abc123/acme-brand-refresh-pitch" } }
```

Send that link and the client opens a full-screen, click-through deck, no attachment, no file to keep in sync. Embed it in a proposal page too:

```
<iframe

  src="https://playbook.com/s/abc123/acme-brand-refresh-pitch"

  style="width:100%;height:720px;border:0"

  title="Presentation deck"

></iframe>
```

For a fully public deck instead of a link-gated one, publish it with `POST /v1/$ORG/boards/acme-brand-refresh-pitch/publish`. See [published vs. shared](/docs/guides/sharing_and_publishing.md#published-vs-shared).

## 3. Collect feedback per slide[​](#3-collect-feedback-per-slide "Direct link to 3. Collect feedback per slide")

Clients comment directly on the shared deck. Read it back per slide to drive a review thread in your own tool:

feedback.ts

```
const ORG = "your-org";

const TOKEN = process.env.PLAYBOOK_TOKEN!;



async function slideComments(assetToken: string) {

  const res = await fetch(

    `https://api.playbook.com/v1/${ORG}/assets/${assetToken}/comments`,

    { headers: { Authorization: `Bearer ${TOKEN}` } },

  );

  const { data } = await res.json(); // threaded: replies nest under `replies`

  return data;

}
```

Comments are threaded, which maps cleanly onto a round of client notes. See [Comments](/docs/guides/comments.md).

## Related[​](#related "Direct link to Related")

* [Sharing & Publishing](/docs/guides/sharing_and_publishing.md)
* [Comments](/docs/guides/comments.md)
* [Client gallery](/docs/examples/client-gallery.md)
