diff --git a/.gitignore b/.gitignore
index c8a7336..ba8c66d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.vercel
.env*.local
+.vslides.json
diff --git a/.vslides-guide.md b/.vslides-guide.md
new file mode 100644
index 0000000..e7baa53
--- /dev/null
+++ b/.vslides-guide.md
@@ -0,0 +1,1392 @@
+# Vercel Slidev Theme Guide
+
+## Presentation Setup
+
+Set global config in the **first slide's frontmatter**:
+
+```yaml
+---
+theme: ./
+title: My Presentation # Shown in footer
+footerLogo: wordmark # "wordmark" | "triangle" | "none"
+footerTitle: true # Show title in footer
+layout: 1-title
+---
+```
+
+---
+
+## Syntax Reference
+
+### Frontmatter
+
+```yaml
+---
+layout: layout-name
+variant: variant-name
+propName: propValue
+---
+```
+
+### Named Slots
+
+```markdown
+::slot-name::
+Content with **markdown**
+```
+
+### Icons
+
+[Lucide](https://lucide.dev/icons): `rocket`, `zap`, `globe`, `code`, `mail`, `twitter`, `github`, etc.
+
+### Tags
+
+```markdown
+::s1-tag::
+Coming soon
+```
+
+Colors: `gray`, `blue`, `purple`, `pink`, `red`, `amber`, `green`, `teal`
+
+Tags are used with statements in `2-statement` layouts via `s1-tag`–`s4-tag` slots. See the `2-statement` section for `tagPosition` guidance.
+
+**Color guidance:** Use color sparingly — Vercel guidance is <5% color on a slide. Prefer `gray` as the default tag color. Only use a colored tag as a rare accent (e.g. one highlight per slide). Overusing color dilutes its impact.
+
+### Images
+
+```yaml
+image: /photos/hero.jpg # Relative to public/
+grayscale: 0 # 0 = full color, 100 = grayscale (default)
+```
+
+---
+
+## Layout Variants — Full Reference
+
+### 1-title
+
+#### `variant: title` / `variant: section`
+
+Opening slide or section divider.
+
+**Structure:**
+
+- Vercel logo (title only)
+- Large centered title
+- 2×2 grid of subtitle points (up to 4), each with icon OR avatar image
+
+**Props:**
+
+- `subtitle1Icon`–`subtitle4Icon` — Lucide icon name
+- `subtitle1Image`–`subtitle4Image` — Avatar image URL (circular, grayscale)
+- `subtitleSize` — `sm` (default) or `lg` (larger avatars for presenter intros)
+
+**Slots:**
+
+- `title` — Main heading
+- `subtitle-1`, `subtitle-2`, `subtitle-3`, `subtitle-4` — Text next to each icon/avatar
+
+```yaml
+---
+layout: 1-title
+variant: title
+subtitle1Icon: rocket
+subtitle2Image: /team/alice.jpg
+---
+
+::title::
+# Welcome to Vercel
+
+::subtitle-1::
+Fast deployments
+
+::subtitle-2::
+Alice Chen, Engineering
+```
+
+---
+
+#### `variant: agenda`
+
+Numbered agenda/outline with up to 8 items in two columns.
+
+**Structure:**
+
+- Badge in top-left
+- 8 numbered items (01–08) in two columns of 4
+
+**Props:**
+
+- `badge` — Badge text (default: "Agenda")
+
+**Slots:**
+
+- `item-1` through `item-8` — Agenda item text
+
+```yaml
+---
+layout: 1-title
+variant: agenda
+badge: Today's Agenda
+---
+
+::item-1::
+Introduction
+
+::item-2::
+Demo
+
+::item-3::
+Q&A
+```
+
+---
+
+### 2-statement
+
+#### `variant: large`
+
+Single big statement, centered.
+
+**Structure:**
+
+- Large centered title
+- Smaller subtitle below
+
+**Slots:**
+
+- `title` — Main statement
+- `subtitle` — Supporting text
+
+```yaml
+---
+layout: 2-statement
+variant: large
+---
+
+::title::
+# Ship 10x faster
+
+::subtitle::
+Deploy in seconds, scale automatically
+```
+
+---
+
+#### `variant: title-2` / `title-3` / `title-4`
+
+Title on left, 2/3/4 statements stacked vertically on right.
+
+**Structure:**
+
+- Left half: Large title
+- Right half: 2, 3, or 4 Statement blocks stacked
+
+**Props:**
+
+- `tagPosition` — `inline` (default) or `above`. Use `inline` for wide statement areas (e.g. `title-2`, `cols-2`). Only use `above` when columns are narrow enough that an inline tag would wrap awkwardly (e.g. `cols-4`, `grid-4`). Don't default to `above` — it adds vertical height and leads to cramped content in rows with limited space.
+
+**Slots:**
+
+- `title` — Left side heading
+- `s1-title`, `s1-body`, `s1-tag` — First statement
+- `s2-title`, `s2-body`, `s2-tag` — Second statement
+- `s3-title`, `s3-body`, `s3-tag` — Third statement (title-3, title-4)
+- `s4-title`, `s4-body`, `s4-tag` — Fourth statement (title-4 only)
+
+```yaml
+---
+layout: 2-statement
+variant: title-3
+---
+
+::title::
+# Why Vercel?
+
+::s1-tag::
+Fast
+
+::s1-title::
+Speed
+
+::s1-body::
+Deploy in under 10 seconds
+
+::s2-title::
+Scale
+
+::s2-body::
+Auto-scaling to millions
+
+::s3-title::
+Security
+
+::s3-body::
+Enterprise-grade by default
+```
+
+---
+
+#### `variant: cols-2` / `cols-3` / `cols-4`
+
+Title at top, 2/3/4 statements in columns below.
+
+**Structure:**
+
+- Top: Title row
+- Bottom: 2, 3, or 4 Statement blocks side by side
+
+**Slots:** Same as title-N variants above.
+
+---
+
+#### `variant: grid-4`
+
+Title at top, 4 statements in 2×2 grid.
+
+**Structure:**
+
+- Top: Title row
+- Bottom: 2×2 grid of Statement blocks
+
+**Slots:** Same as title-4.
+
+---
+
+#### `variant: transition`
+
+Narrative section connector with optional progress label. Use between major content blocks to guide the audience through the presentation's narrative arc.
+
+**Structure:**
+
+- Centered title + subtitle (like `large` but lighter, using `lg` Statement)
+- Optional progress indicator at bottom (e.g. "Part 2 of 3")
+
+**Props:**
+
+- `transitionLabel` — Progress text (optional, e.g. "Part 2 of 3", "Next: The Solution")
+
+**Slots:**
+
+- `title` — Main transition text
+- `subtitle` — Supporting context
+
+```yaml
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "Part 2 of 3"
+---
+
+::title::
+Next: The Solution
+
+::subtitle::
+How we solved the performance challenge
+```
+
+**When to use:** Use `1-title variant: section` for bold section headers. Use `2-statement variant: transition` for lighter narrative connectors within a section, especially when you want a subtitle and/or progress indicator.
+
+---
+
+### 3-screenshot
+
+All variants show images in a **macOS browser frame** with traffic lights.
+
+#### `variant: full`
+
+Full-width screenshot, clipped at bottom by footer.
+
+**Props:**
+
+- `image` — Screenshot URL (required)
+- `url` — URL shown in browser bar
+- `grayscale` — 0–100 (default: 100 = full grayscale)
+
+```yaml
+---
+layout: 3-screenshot
+variant: full
+image: /screenshots/dashboard.png
+url: vercel.com/dashboard
+grayscale: 0
+---
+```
+
+---
+
+#### `variant: right-1`
+
+Statement on left (1/3), screenshot on right (2/3).
+
+**Structure:**
+
+- Left: 1 Statement (title + body)
+- Right: Browser frame with screenshot
+
+**Slots:**
+
+- `title` — Statement title
+- `body` — Statement body
+
+```yaml
+---
+layout: 3-screenshot
+variant: right-1
+image: /screenshots/deploy.png
+url: vercel.com
+---
+
+::title::
+# One-Click Deploy
+
+::body::
+Push to Git and your site is live.
+```
+
+---
+
+#### `variant: left-2`
+
+Screenshot on left (2/3), 2 statements stacked on right (1/3).
+
+**Structure:**
+
+- Left: Browser frame with screenshot
+- Right: 2 Statement blocks stacked
+
+**Slots:**
+
+- `s1-title`, `s1-body` — First statement
+- `s2-title`, `s2-body` — Second statement
+
+---
+
+#### `variant: right-list`
+
+Title + 4 list items on left (1/3), screenshot on right (2/3).
+
+**Structure:**
+
+- Left top: Title
+- Left bottom: 4 simple text rows
+- Right: Browser frame with screenshot
+
+**Slots:**
+
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items (plain text, no title/body)
+
+---
+
+#### `variant: left-list`
+
+Screenshot on left (2/3), title + 4 list items on right (1/3).
+
+Same slots as right-list.
+
+---
+
+### 4-image
+
+Images are shown **without browser frame** (full-bleed or contained).
+
+**Common Props (all variants):**
+
+- `imageMode` — How images fit: `cover` (default), `contain`, `fill`, `none`, `scale-down`
+- `grayscale` — Global grayscale for all images (`0` = full color, `100` = full grayscale, default: `100`)
+
+#### `variant: full`
+
+Full-screen image.
+
+**Props:**
+
+- `image` — Image URL
+- `grayscale` — 0–100 (default: 100)
+
+---
+
+#### `variant: left-list`
+
+Image on left (1/2), title + 4 list items on right (1/2).
+
+**Props:**
+
+- `image` — Image URL
+- `grayscale` — 0–100 (default: 100)
+
+**Slots:**
+
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items
+
+---
+
+#### `variant: title-image`
+
+Title at top (30%), image below (70%).
+
+**Props:**
+
+- `image` — Image URL
+- `grayscale` — 0–100 (default: 100)
+
+**Slots:**
+
+- `title` — Section title
+
+---
+
+#### `variant: grid-2` / `grid-3` / `grid-4`
+
+Title + 2/3/4 images, each with a statement below.
+
+**Structure:**
+
+- Top row: Title
+- Middle row: 2, 3, or 4 images side by side
+- Bottom row: 2, 3, or 4 Statement blocks (one per image)
+
+**Props:**
+
+- `image1`, `image2`, `image3`, `image4` — Image URLs
+- `grayscale1`, `grayscale2`, `grayscale3`, `grayscale4` — Per-image grayscale overrides (0–100)
+- `imageMode1`, `imageMode2`, `imageMode3`, `imageMode4` — Per-image fit mode overrides (`cover`, `contain`, `fill`, `none`, `scale-down`)
+
+For grid variants, `grayscale` and `imageMode` apply to all images by default. Use `grayscaleN` / `imageModeN` to override specific cells.
+
+**Slots:**
+
+- `title` — Section title
+- `s1-title`, `s1-body` — Caption for image1
+- `s2-title`, `s2-body` — Caption for image2
+- `s3-title`, `s3-body` — Caption for image3 (grid-3, grid-4)
+- `s4-title`, `s4-body` — Caption for image4 (grid-4 only)
+
+```yaml
+---
+layout: 4-image
+variant: grid-3
+image1: /team/alice.jpg
+image2: /team/bob.jpg
+image3: /team/carol.jpg
+grayscale1: 0
+grayscale2: 0
+grayscale3: 0
+---
+
+::title::
+# Meet the Team
+
+::s1-title::
+Alice Chen
+
+::s1-body::
+Engineering Lead
+
+::s2-title::
+Bob Smith
+
+::s2-body::
+Product Manager
+
+::s3-title::
+Carol Davis
+
+::s3-body::
+Designer
+```
+
+---
+
+### 4-mermaid
+
+Mermaid charts with the same composition model as `4-image` (image areas replaced by diagrams).
+
+**When to use:** Architecture diagrams, process flows, system maps, and side-by-side chart comparisons.
+
+**Variants:**
+
+- `variant: full` — One full-slide chart
+- `variant: left-list` — Chart left, title + list right
+- `variant: title-image` — Title top, chart below
+- `variant: grid-2` — 2 charts + 2 statement captions
+- `variant: grid-3` — 3 charts + 3 statement captions
+- `variant: grid-4` — 4 charts + 4 statement captions
+
+Grid variants use numbered chart props (chart1, chart2, etc.) and matching statement slots (s1-title/body, s2-title/body, etc.). Single-chart variants use a single chart prop. left-list adds title + item-1..item-4 slots. title-image adds a title slot.
+
+**Syntax rules (all variants):**
+
+- Put Mermaid code in frontmatter using YAML multiline strings (`|`).
+- Start with a Mermaid diagram declaration (`flowchart LR`, `flowchart TD`, etc.).
+- Prefer plain labels (`Node["Text"]`) over HTML labels if rendering is unstable.
+- Use hex colors in `classDef` and `linkStyle`.
+
+**Example: `variant: full`**
+
+## \\`\\`\\`yaml
+
+layout: 4-mermaid
+variant: full
+chart: |
+flowchart LR
+User["User"] --> Edge["Edge Router"]
+Edge -->|cache hit| Cached(["Cached"])
+Edge -->|cache miss| App["App Runtime"]
+App --> DB["Primary DB"]
+classDef success fill:#0b1d0f,stroke:#46a758,color:#63c174;
+class Cached success;
+
+---
+
+\\`\\`\\`
+
+**Example: `variant: grid-2`**
+
+## \\`\\`\\`yaml
+
+layout: 4-mermaid
+variant: grid-2
+chart1: |
+flowchart LR
+Edge["Edge"] --> API["API"]
+API -->|ok| Fast(["Low Latency"])
+classDef success fill:#0b1d0f,stroke:#46a758,color:#63c174;
+class Fast success;
+chart2: |
+flowchart LR
+API["API"] --> Guard["Rate Limit"]
+Guard -->|blocked| Drop(["Dropped"])
+classDef danger fill:#2a1314,stroke:#e5484d,color:#ff6166;
+class Drop danger;
+
+---
+
+::title::
+
+# Traffic Paths
+
+::s1-title::
+Fast path
+
+::s1-body::
+Edge + API success flow.
+
+::s2-title::
+Blocked path
+
+::s2-body::
+Rate limit rejects abusive traffic.
+\\`\\`\\`
+
+---
+
+### 5-open
+
+Flexible layouts with open content areas for custom content (iframes, demos, etc.).
+
+#### `variant: title-space`
+
+Title at top (30%), open area below (70%).
+
+**Slots:**
+
+- `title` — Section title
+- `content` — Open area (any HTML/Vue)
+
+---
+
+#### `variant: title-2-spaces` / `title-3-spaces`
+
+Title at top, 2 or 3 open areas side by side below.
+
+**Slots:**
+
+- `title` — Section title
+- `space-1`, `space-2`, `space-3` — Open areas
+
+---
+
+#### `variant: list-space`
+
+Title + 5 list items on left (1/3), open area on right (2/3).
+
+**Slots:**
+
+- `title` — Section title
+- `item-1` through `item-5` — List items
+- `space` — Open area
+
+---
+
+### 6-quote
+
+#### `variant: center`
+
+Centered quote with attribution.
+
+**Slots:**
+
+- `quote` — Quote text
+- `author` — Attribution (name, title, company)
+
+```yaml
+---
+layout: 6-quote
+variant: center
+---
+
+::quote::
+The best way to predict the future is to build it.
+
+::author::
+— Guillermo Rauch, CEO of Vercel
+```
+
+---
+
+#### `variant: with-statements`
+
+2 statements on left (1/3), quote on right (2/3).
+
+**Slots:**
+
+- `s1-title`, `s1-body` — First statement
+- `s2-title`, `s2-body` — Second statement
+- `quote`, `author` — Quote content
+
+---
+
+### 7-number
+
+#### `variant: one`
+
+Single huge metric, centered.
+
+**Slots:**
+
+- `number` — The metric (e.g., "99.9%")
+- `label` — Description (e.g., "Uptime SLA")
+
+---
+
+#### `variant: two` / `variant: three`
+
+2 or 3 metrics side by side.
+
+**Slots:**
+
+- `number-1`, `label-1` — First metric
+- `number-2`, `label-2` — Second metric
+- `number-3`, `label-3` — Third metric (three only)
+
+---
+
+#### `variant: four-with-title`
+
+Statement on left (1/3), 2×2 grid of 4 metrics on right (2/3).
+
+**Slots:**
+
+- `title`, `subtitle` — Left side statement
+- `number-1`, `label-1` through `number-4`, `label-4` — Metrics
+
+---
+
+#### `variant: six`
+
+6 metrics in 3×2 grid.
+
+**Slots:**
+
+- `number-1`, `label-1` through `number-6`, `label-6`
+
+---
+
+#### `variant: two-with-source` / `three-with-source`
+
+2 or 3 metrics with source citations below each.
+
+**Slots:**
+
+- `number-1`, `label-1`, `source-1` — First metric with citation
+- `number-2`, `label-2`, `source-2` — Second metric
+- `number-3`, `label-3`, `source-3` — Third metric (three-with-source only)
+
+---
+
+### 8-special
+
+#### `variant: qa`
+
+Q&A slide with decorative left panel.
+
+**Structure:**
+
+- Left: Decorative quote bubble SVG + optional custom content
+- Right: Badge + up to 4 icon points (contact info, links, etc.)
+
+**Props:**
+
+- `badge` — Badge text (default: "Q&A")
+- `item1Icon`, `item2Icon`, `item3Icon`, `item4Icon` — Lucide icons
+
+**Slots:**
+
+- `left` — Optional content in left panel
+- `item-1`, `item-2`, `item-3`, `item-4` — Text next to each icon
+
+```yaml
+---
+layout: 8-special
+variant: qa
+badge: Questions?
+item1Icon: mail
+item2Icon: twitter
+---
+
+::item-1::
+hello@vercel.com
+
+::item-2::
+@vercel
+```
+
+---
+
+#### `variant: thank-you`
+
+Centered Vercel triangle + "Thank you" text. No slots.
+
+---
+
+#### `variant: splash`
+
+Centered Vercel triangle only. No slots.
+
+---
+
+### 9-utility
+
+Blank canvases for custom content.
+
+- `variant: blank` — Empty with frame
+- `variant: crosshairs` — Frame + crosshair decorations
+- `variant: full-grid` — Dense alignment grid
+
+Default slot accepts any content.
+
+---
+
+### 10-code
+
+All variants show code in a **code editor frame** with filename header.
+
+**IMPORTANT — Maximum lines of code (LOC) that fit without clipping:**
+
+| Size | Full variant | 2/3 variants (right-1, left-2, right-list, left-list) |
+| ---- | ------------ | ----------------------------------------------------- |
+| `xs` | 23 lines | 19 lines |
+| `sm` | 17 lines | 14 lines |
+| `md` | 14 lines | 11 lines |
+| `lg` | 12 lines | 9 lines |
+
+**Always count your code lines (including blank lines) and pick a `codeSize` that fits.** If the code exceeds the limit, it will be clipped at the bottom. Prefer trimming code to show only the essential parts rather than cramming everything in at `xs`.
+
+**Scrollable mode:** Set `scrollable: true` to allow vertical scrolling for longer code. This should NOT be the default — only use it when showing the complete code is essential and trimming would lose important context. Non-scrollable (clipped) code is the standard look.
+
+#### `variant: full`
+
+Full-width code, clipped at bottom.
+
+**Props:**
+
+- `filename` — Filename shown in header (e.g., `api/hello.ts`)
+- `codeSize` — `xs`, `sm` (default), `md`, `lg`
+- `scrollable` — `true` to enable vertical scrolling (default: `false`, code clips at bottom)
+
+**Slots:**
+
+- `code` — Fenced code block with syntax highlighting
+
+```yaml
+---
+layout: 10-code
+variant: full
+filename: api/hello.ts
+---
+
+::code::
+\\`\\`\\`ts
+export async function GET() {
+ return Response.json({ hello: 'world' })
+}
+\\`\\`\\`
+```
+
+---
+
+#### `variant: right-1`
+
+Statement on left (1/3), code on right (2/3).
+
+**Slots:**
+
+- `title`, `body` — Statement
+- `code` — Code block
+
+---
+
+#### `variant: left-2`
+
+Code on left (2/3), 2 statements on right (1/3).
+
+**Slots:**
+
+- `code` — Code block
+- `s1-title`, `s1-body` — First statement
+- `s2-title`, `s2-body` — Second statement
+
+---
+
+#### `variant: right-list` / `left-list`
+
+Code + title + 4 list items.
+
+**Slots:**
+
+- `code` — Code block
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items
+
+---
+
+### 11-promo
+
+#### `variant: two-statements`
+
+Badge + decorative grid + 2 statements.
+
+**Structure:**
+
+- Top: Badge
+- Middle: Decorative square grid
+- Bottom: 2 Statement blocks side by side
+
+**Props:**
+
+- `badge` — Badge text
+- `gridCols` — Grid columns (default: 14)
+- `gridRows` — Grid rows (default: 3)
+
+**Slots:**
+
+- `s1-title`, `s1-body`, `s1-tag` — First statement
+- `s2-title`, `s2-body`, `s2-tag` — Second statement
+
+---
+
+### playful
+
+Animated full-screen grid layouts.
+
+#### `variant: welcome`
+
+Static "▲ W E L C O M E" display. No configuration needed.
+
+---
+
+#### `variant: triangles`
+
+Random Vercel triangles fade in/out.
+
+**Props:**
+
+- `flashInterval` — ms between new triangles (default: 2500)
+- `fadeDuration` — ms for fade out (default: 4000)
+
+---
+
+#### `variant: values`
+
+Random Vercel values (FTW, DIG DEEP, etc.) fade in/out.
+
+Same props as triangles.
+
+---
+
+#### `variant: splitflap`
+
+Mechanical split-flap display animation.
+
+Use `` components in the slide body:
+
+```yaml
+---
+layout: playful
+variant: splitflap
+---
+
+
+```
+
+**Flap props:**
+
+- `text` — Text to display (max 16 chars). Use `▲` for Vercel icon.
+- `row` — Row number (1–9)
+- `startCol` — Starting column (auto-centers if omitted)
+- `mono` — Use monospace font (default: false)
+- `flipDuration` — ms per character flip (default: 120)
+- `staggerDelay` — ms between letters (default: 100)
+
+---
+
+### 12-youtube
+
+Embedded YouTube video in a **macOS browser frame** (same chrome as 3-screenshot). The browser bar always shows `youtube.com`. Uses privacy-enhanced embedding (`youtube-nocookie.com`).
+
+**Timestamp support:** Include `&t=SECONDS` in the URL to start the video at a specific time. The component auto-extracts `t=` or `start=` from the URL and passes it to the embed player.
+
+#### `variant: full`
+
+Full-width browser frame with embedded video, clipped at bottom.
+
+**Props:**
+
+- `url` — YouTube video URL (supports `youtube.com/watch?v=`, `youtu.be/`, `youtube.com/embed/`). Append `&t=SECONDS` to start at a specific timestamp.
+
+```yaml
+---
+layout: 12-youtube
+variant: full
+url: https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=166
+---
+```
+
+---
+
+#### `variant: left-list`
+
+Video in browser frame on left (1/2), title + 4 list items on right (1/2).
+
+**Props:**
+
+- `url` — YouTube video URL. Append `&t=SECONDS` to start at a specific timestamp.
+
+**Slots:**
+
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items
+
+```yaml
+---
+layout: 12-youtube
+variant: left-list
+url: https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=120
+---
+
+::title::
+Video Walkthrough
+
+::item-1::
+Step 1: Setup
+
+::item-2::
+Step 2: Configure
+
+::item-3::
+Step 3: Deploy
+
+::item-4::
+Step 4: Monitor
+```
+
+---
+
+## Offer Layouts
+
+Sales offer slides for customer proposals. All offer layouts are dark-themed with the Vercel design system. Data is passed via **frontmatter props** (not slots) for structured data like SKUs, details, and team members.
+
+---
+
+### offer-title
+
+Cover slide for a customer offer with title and team members.
+
+**Structure:**
+
+- Large title at top
+- 2×2 team member grid at bottom (name + role in monospace)
+
+**Props:**
+
+- `team1Name`–`team4Name` — Team member names
+- `team1Role`–`team4Role` — Team member roles (shown in monospace, muted)
+
+**Slots:**
+
+- `title` — Main heading (use `
` for line breaks)
+
+```yaml
+---
+layout: offer-title
+team1Name: Jane Smith
+team1Role: ACCOUNT MANAGER
+team2Name: John Doe
+team2Role: SOLUTIONS ENGINEER
+team3Name: Alice Chen
+team3Role: CSM
+team4Name: Bob Wilson
+team4Role: CRO
+---
+::title::
+# Acme Corp's
Vercel offer
+```
+
+---
+
+### offer-statement
+
+Badge + title on left, numbered points on right.
+
+**Structure:**
+
+- Left: Outline badge + large title
+- Right: Up to 4 numbered points (01–04) with title + body
+
+**Props:**
+
+- `badge` — Badge text (default: "OUR PRICING PHILOSOPHY")
+- `badgeColor` — Badge border color (default: "#A0A0A0")
+
+**Slots:**
+
+- `title` — Left side heading
+- `point-1-title`, `point-1-body` — First numbered point
+- `point-2-title`, `point-2-body` — Second numbered point
+- `point-3-title`, `point-3-body` — Third point
+- `point-4-title`, `point-4-body` — Fourth point
+
+```yaml
+---
+layout: offer-statement
+badge: OUR PRICING PHILOSOPHY
+---
+
+::title::
+Transparency
& predictability
+
+::point-1-title::
+Usage-based
+
+::point-1-body::
+Pay for only what you use
+
+::point-2-title::
+Product flexibility
+
+::point-2-body::
+One commit across products, shift spend where you need
+
+::point-3-title::
+Scales with you
+
+::point-3-body::
+The more you buy, the better your discount
+```
+
+---
+
+### offer-product-grid
+
+Product portfolio grid showing all Vercel SKUs organized by category.
+
+**Structure:**
+
+- Title + subtitle at top
+- Grid of product categories with individual SKU pills
+- Diagonal background pattern behind grid
+
+**Props:**
+
+- `categories` — Array of `{ title, products: [{ name }], highlighted? }` (has sensible defaults with all Vercel products)
+- `rows` — Array of index arrays defining grid layout (default: `[[0,1], [2,3,4], [5,6,7,8]]`)
+
+**Slots:**
+
+- `title` — Grid heading
+- `subtitle` — Subtitle text
+
+```yaml
+---
+layout: offer-product-grid
+---
+
+::title::
+Introducing Flexible Commitment
+
+::subtitle::
+Giving your team access to the entire Vercel product portfolio
+```
+
+---
+
+### offer-timeline
+
+Flex commit timeline visualization with checkbox grid.
+
+**Structure:**
+
+- Badge at top
+- Large headline (supports mixed white/muted text via HTML spans)
+- Month 1–12 timeline with animated checkbox grid + fade overlay
+
+**Props:**
+
+- `badge` — Badge text (default: "FLEX COMMIT")
+- `startLabel` — Left label (default: "MONTH 1")
+- `endLabel` — Right label (default: "MONTH 12")
+- `months` — 12-element array of boolean arrays for checkbox states
+
+**Slots:**
+
+- `title` — Headline (use `` and `` for mixed styling)
+
+```yaml
+---
+layout: offer-timeline
+---
+
+::title::
+Swap SKUs anytime to align with
shifting needs and seasonality.
+```
+
+---
+
+### offer-pricing
+
+Discount matrix on left, rate card on right.
+
+**Structure:**
+
+- Left: Title + 2×2 discount matrix (BASE/MODERATE/HIGH/BEST)
+- Right: Rate card table with diagonal background
+
+**Props:**
+
+- `badgeText` — Rate card badge (default: "FLEX COMMIT RATE CARD")
+- `footerText` — Rate card footer (default: "ENTIRE RATE CARD AVAILABLE WITH FULL PROPOSAL")
+- `skus` — Array of `{ name, listPrice, discountPrice }` (default: 3 placeholder SKUs)
+
+**Slots:**
+
+- `title` — Left side heading
+
+```yaml
+---
+layout: offer-pricing
+skus:
+ - name: Fluid Compute
+ listPrice: $0.18/GB-hr
+ discountPrice: $0.12/GB-hr
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.40/M
+ - name: Bandwidth
+ listPrice: $0.15/GB
+ discountPrice: $0.10/GB
+---
+
+::title::
+Pricing that
scales with
you.
+```
+
+---
+
+### offer-roi
+
+Centered card with label/value rows and dotted leaders.
+
+**Structure:**
+
+- Centered rounded card with outline badge
+- Up to 3 key-value rows with dotted line between label and value
+
+**Props:**
+
+- `badge` — Card badge text (default: "ANTICIPATED QUANTIFIED VALUE")
+
+**Slots:**
+
+- `label`, `value` — First row (default: "ROI" / "$XM")
+- `label-2`, `value-2` — Second row (optional)
+- `label-3`, `value-3` — Third row (optional)
+
+```yaml
+---
+layout: offer-roi
+---
+
+::label::
+ROI
+
+::value::
+$2.5M
+
+::label-2::
+Annual savings
+
+::value-2::
+$500K
+```
+
+---
+
+### offer-details
+
+Header + key-value sidebar on left, rate card on right.
+
+**Structure:**
+
+- Header bar with customer name
+- Left: Key-value detail rows (flexible count)
+- Right: Rate card with diagonal background
+
+**Props:**
+
+- `headerText` — Header text (default: "[Customer name] offer")
+- `details` — Array of `{ label, value }` for the sidebar rows
+- `badgeText` — Rate card badge
+- `footerText` — Rate card footer
+- `skus` — Array of `{ name, listPrice, discountPrice }`
+
+```yaml
+---
+layout: offer-details
+headerText: Acme Corp offer
+details:
+ - label: Flex commit balance
+ value: $120K / YR
+ - label: Term
+ value: 2 YRS
+ - label: Support level
+ value: Enterprise
+ - label: Start date
+ value: Q1 2026
+skus:
+ - name: Fluid Compute
+ listPrice: $0.18/GB-hr
+ discountPrice: $0.12/GB-hr
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.40/M
+ - name: Bandwidth
+ listPrice: $0.15/GB
+ discountPrice: $0.10/GB
+---
+
+```
+
+---
+
+### offer-comparison
+
+Side-by-side comparison of 2–3 offer options, each with rate card.
+
+**Structure:**
+
+- Header bar with customer name
+- Equal-width columns, each with: option badge, balance/term KV rows, small rate card
+
+**Props:**
+
+- `headerText` — Header text (default: "[Customer name] offer comparison")
+- `options` — Array of `{ label, balance, term, skus: [{ name, listPrice, discountPrice }] }`
+
+```yaml
+---
+layout: offer-comparison
+headerText: Acme Corp offer comparison
+options:
+ - label: OPTION 1
+ balance: $100K / YR
+ term: 1 YR
+ skus:
+ - name: Fluid Compute
+ listPrice: $0.18
+ discountPrice: $0.15
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.70/M
+ - label: OPTION 2
+ balance: $120K / YR
+ term: 2 YRS
+ skus:
+ - name: Fluid Compute
+ listPrice: $0.18
+ discountPrice: $0.12
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.40/M
+---
+
+```
+
+---
+
+### offer-before-after
+
+Side-by-side before/after comparison with colored badges and icon rows.
+
+**Structure:**
+
+- Left: Red "BEFORE STATE" badge + year + title + X-icon rows
+- Right: Green "AFTER STATE" badge + year + title + check-icon rows
+
+**Props:**
+
+- `beforeBadge` — Left badge text (default: "BEFORE STATE")
+- `afterBadge` — Right badge text (default: "AFTER STATE")
+- `beforeYear` — Left year label (default: "2025 & EARLIER")
+- `afterYear` — Right year label (default: "2026+")
+- `beforeColor` — Left badge color (default: red `#DA2F36`)
+- `afterColor` — Right badge color (default: green `#63C173`)
+
+**Slots:**
+
+- `before-title` — Left title (default: "MIU")
+- `after-title` — Right title (default: "Flex Commit")
+- `before-1` through `before-6` — Before rows (with X icon)
+- `after-1` through `after-6` — After rows (with check icon)
+
+```yaml
+---
+layout: offer-before-after
+---
+
+::before-title::
+MIU
+
+::after-title::
+Flex Commit
+
+::before-1::
+Separate commits per SKU
+
+::after-1::
+Max flexibility
+
+::before-2::
+Monthly burndown
+
+::after-2::
+Annual burndown
+
+::before-3::
+Shallow blanket discount
+
+::after-3::
+Private rate card
+```
diff --git a/presentations/getting-started-workflows-webinar/.vslides-guide.md b/presentations/getting-started-workflows-webinar/.vslides-guide.md
new file mode 100644
index 0000000..e7baa53
--- /dev/null
+++ b/presentations/getting-started-workflows-webinar/.vslides-guide.md
@@ -0,0 +1,1392 @@
+# Vercel Slidev Theme Guide
+
+## Presentation Setup
+
+Set global config in the **first slide's frontmatter**:
+
+```yaml
+---
+theme: ./
+title: My Presentation # Shown in footer
+footerLogo: wordmark # "wordmark" | "triangle" | "none"
+footerTitle: true # Show title in footer
+layout: 1-title
+---
+```
+
+---
+
+## Syntax Reference
+
+### Frontmatter
+
+```yaml
+---
+layout: layout-name
+variant: variant-name
+propName: propValue
+---
+```
+
+### Named Slots
+
+```markdown
+::slot-name::
+Content with **markdown**
+```
+
+### Icons
+
+[Lucide](https://lucide.dev/icons): `rocket`, `zap`, `globe`, `code`, `mail`, `twitter`, `github`, etc.
+
+### Tags
+
+```markdown
+::s1-tag::
+Coming soon
+```
+
+Colors: `gray`, `blue`, `purple`, `pink`, `red`, `amber`, `green`, `teal`
+
+Tags are used with statements in `2-statement` layouts via `s1-tag`–`s4-tag` slots. See the `2-statement` section for `tagPosition` guidance.
+
+**Color guidance:** Use color sparingly — Vercel guidance is <5% color on a slide. Prefer `gray` as the default tag color. Only use a colored tag as a rare accent (e.g. one highlight per slide). Overusing color dilutes its impact.
+
+### Images
+
+```yaml
+image: /photos/hero.jpg # Relative to public/
+grayscale: 0 # 0 = full color, 100 = grayscale (default)
+```
+
+---
+
+## Layout Variants — Full Reference
+
+### 1-title
+
+#### `variant: title` / `variant: section`
+
+Opening slide or section divider.
+
+**Structure:**
+
+- Vercel logo (title only)
+- Large centered title
+- 2×2 grid of subtitle points (up to 4), each with icon OR avatar image
+
+**Props:**
+
+- `subtitle1Icon`–`subtitle4Icon` — Lucide icon name
+- `subtitle1Image`–`subtitle4Image` — Avatar image URL (circular, grayscale)
+- `subtitleSize` — `sm` (default) or `lg` (larger avatars for presenter intros)
+
+**Slots:**
+
+- `title` — Main heading
+- `subtitle-1`, `subtitle-2`, `subtitle-3`, `subtitle-4` — Text next to each icon/avatar
+
+```yaml
+---
+layout: 1-title
+variant: title
+subtitle1Icon: rocket
+subtitle2Image: /team/alice.jpg
+---
+
+::title::
+# Welcome to Vercel
+
+::subtitle-1::
+Fast deployments
+
+::subtitle-2::
+Alice Chen, Engineering
+```
+
+---
+
+#### `variant: agenda`
+
+Numbered agenda/outline with up to 8 items in two columns.
+
+**Structure:**
+
+- Badge in top-left
+- 8 numbered items (01–08) in two columns of 4
+
+**Props:**
+
+- `badge` — Badge text (default: "Agenda")
+
+**Slots:**
+
+- `item-1` through `item-8` — Agenda item text
+
+```yaml
+---
+layout: 1-title
+variant: agenda
+badge: Today's Agenda
+---
+
+::item-1::
+Introduction
+
+::item-2::
+Demo
+
+::item-3::
+Q&A
+```
+
+---
+
+### 2-statement
+
+#### `variant: large`
+
+Single big statement, centered.
+
+**Structure:**
+
+- Large centered title
+- Smaller subtitle below
+
+**Slots:**
+
+- `title` — Main statement
+- `subtitle` — Supporting text
+
+```yaml
+---
+layout: 2-statement
+variant: large
+---
+
+::title::
+# Ship 10x faster
+
+::subtitle::
+Deploy in seconds, scale automatically
+```
+
+---
+
+#### `variant: title-2` / `title-3` / `title-4`
+
+Title on left, 2/3/4 statements stacked vertically on right.
+
+**Structure:**
+
+- Left half: Large title
+- Right half: 2, 3, or 4 Statement blocks stacked
+
+**Props:**
+
+- `tagPosition` — `inline` (default) or `above`. Use `inline` for wide statement areas (e.g. `title-2`, `cols-2`). Only use `above` when columns are narrow enough that an inline tag would wrap awkwardly (e.g. `cols-4`, `grid-4`). Don't default to `above` — it adds vertical height and leads to cramped content in rows with limited space.
+
+**Slots:**
+
+- `title` — Left side heading
+- `s1-title`, `s1-body`, `s1-tag` — First statement
+- `s2-title`, `s2-body`, `s2-tag` — Second statement
+- `s3-title`, `s3-body`, `s3-tag` — Third statement (title-3, title-4)
+- `s4-title`, `s4-body`, `s4-tag` — Fourth statement (title-4 only)
+
+```yaml
+---
+layout: 2-statement
+variant: title-3
+---
+
+::title::
+# Why Vercel?
+
+::s1-tag::
+Fast
+
+::s1-title::
+Speed
+
+::s1-body::
+Deploy in under 10 seconds
+
+::s2-title::
+Scale
+
+::s2-body::
+Auto-scaling to millions
+
+::s3-title::
+Security
+
+::s3-body::
+Enterprise-grade by default
+```
+
+---
+
+#### `variant: cols-2` / `cols-3` / `cols-4`
+
+Title at top, 2/3/4 statements in columns below.
+
+**Structure:**
+
+- Top: Title row
+- Bottom: 2, 3, or 4 Statement blocks side by side
+
+**Slots:** Same as title-N variants above.
+
+---
+
+#### `variant: grid-4`
+
+Title at top, 4 statements in 2×2 grid.
+
+**Structure:**
+
+- Top: Title row
+- Bottom: 2×2 grid of Statement blocks
+
+**Slots:** Same as title-4.
+
+---
+
+#### `variant: transition`
+
+Narrative section connector with optional progress label. Use between major content blocks to guide the audience through the presentation's narrative arc.
+
+**Structure:**
+
+- Centered title + subtitle (like `large` but lighter, using `lg` Statement)
+- Optional progress indicator at bottom (e.g. "Part 2 of 3")
+
+**Props:**
+
+- `transitionLabel` — Progress text (optional, e.g. "Part 2 of 3", "Next: The Solution")
+
+**Slots:**
+
+- `title` — Main transition text
+- `subtitle` — Supporting context
+
+```yaml
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "Part 2 of 3"
+---
+
+::title::
+Next: The Solution
+
+::subtitle::
+How we solved the performance challenge
+```
+
+**When to use:** Use `1-title variant: section` for bold section headers. Use `2-statement variant: transition` for lighter narrative connectors within a section, especially when you want a subtitle and/or progress indicator.
+
+---
+
+### 3-screenshot
+
+All variants show images in a **macOS browser frame** with traffic lights.
+
+#### `variant: full`
+
+Full-width screenshot, clipped at bottom by footer.
+
+**Props:**
+
+- `image` — Screenshot URL (required)
+- `url` — URL shown in browser bar
+- `grayscale` — 0–100 (default: 100 = full grayscale)
+
+```yaml
+---
+layout: 3-screenshot
+variant: full
+image: /screenshots/dashboard.png
+url: vercel.com/dashboard
+grayscale: 0
+---
+```
+
+---
+
+#### `variant: right-1`
+
+Statement on left (1/3), screenshot on right (2/3).
+
+**Structure:**
+
+- Left: 1 Statement (title + body)
+- Right: Browser frame with screenshot
+
+**Slots:**
+
+- `title` — Statement title
+- `body` — Statement body
+
+```yaml
+---
+layout: 3-screenshot
+variant: right-1
+image: /screenshots/deploy.png
+url: vercel.com
+---
+
+::title::
+# One-Click Deploy
+
+::body::
+Push to Git and your site is live.
+```
+
+---
+
+#### `variant: left-2`
+
+Screenshot on left (2/3), 2 statements stacked on right (1/3).
+
+**Structure:**
+
+- Left: Browser frame with screenshot
+- Right: 2 Statement blocks stacked
+
+**Slots:**
+
+- `s1-title`, `s1-body` — First statement
+- `s2-title`, `s2-body` — Second statement
+
+---
+
+#### `variant: right-list`
+
+Title + 4 list items on left (1/3), screenshot on right (2/3).
+
+**Structure:**
+
+- Left top: Title
+- Left bottom: 4 simple text rows
+- Right: Browser frame with screenshot
+
+**Slots:**
+
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items (plain text, no title/body)
+
+---
+
+#### `variant: left-list`
+
+Screenshot on left (2/3), title + 4 list items on right (1/3).
+
+Same slots as right-list.
+
+---
+
+### 4-image
+
+Images are shown **without browser frame** (full-bleed or contained).
+
+**Common Props (all variants):**
+
+- `imageMode` — How images fit: `cover` (default), `contain`, `fill`, `none`, `scale-down`
+- `grayscale` — Global grayscale for all images (`0` = full color, `100` = full grayscale, default: `100`)
+
+#### `variant: full`
+
+Full-screen image.
+
+**Props:**
+
+- `image` — Image URL
+- `grayscale` — 0–100 (default: 100)
+
+---
+
+#### `variant: left-list`
+
+Image on left (1/2), title + 4 list items on right (1/2).
+
+**Props:**
+
+- `image` — Image URL
+- `grayscale` — 0–100 (default: 100)
+
+**Slots:**
+
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items
+
+---
+
+#### `variant: title-image`
+
+Title at top (30%), image below (70%).
+
+**Props:**
+
+- `image` — Image URL
+- `grayscale` — 0–100 (default: 100)
+
+**Slots:**
+
+- `title` — Section title
+
+---
+
+#### `variant: grid-2` / `grid-3` / `grid-4`
+
+Title + 2/3/4 images, each with a statement below.
+
+**Structure:**
+
+- Top row: Title
+- Middle row: 2, 3, or 4 images side by side
+- Bottom row: 2, 3, or 4 Statement blocks (one per image)
+
+**Props:**
+
+- `image1`, `image2`, `image3`, `image4` — Image URLs
+- `grayscale1`, `grayscale2`, `grayscale3`, `grayscale4` — Per-image grayscale overrides (0–100)
+- `imageMode1`, `imageMode2`, `imageMode3`, `imageMode4` — Per-image fit mode overrides (`cover`, `contain`, `fill`, `none`, `scale-down`)
+
+For grid variants, `grayscale` and `imageMode` apply to all images by default. Use `grayscaleN` / `imageModeN` to override specific cells.
+
+**Slots:**
+
+- `title` — Section title
+- `s1-title`, `s1-body` — Caption for image1
+- `s2-title`, `s2-body` — Caption for image2
+- `s3-title`, `s3-body` — Caption for image3 (grid-3, grid-4)
+- `s4-title`, `s4-body` — Caption for image4 (grid-4 only)
+
+```yaml
+---
+layout: 4-image
+variant: grid-3
+image1: /team/alice.jpg
+image2: /team/bob.jpg
+image3: /team/carol.jpg
+grayscale1: 0
+grayscale2: 0
+grayscale3: 0
+---
+
+::title::
+# Meet the Team
+
+::s1-title::
+Alice Chen
+
+::s1-body::
+Engineering Lead
+
+::s2-title::
+Bob Smith
+
+::s2-body::
+Product Manager
+
+::s3-title::
+Carol Davis
+
+::s3-body::
+Designer
+```
+
+---
+
+### 4-mermaid
+
+Mermaid charts with the same composition model as `4-image` (image areas replaced by diagrams).
+
+**When to use:** Architecture diagrams, process flows, system maps, and side-by-side chart comparisons.
+
+**Variants:**
+
+- `variant: full` — One full-slide chart
+- `variant: left-list` — Chart left, title + list right
+- `variant: title-image` — Title top, chart below
+- `variant: grid-2` — 2 charts + 2 statement captions
+- `variant: grid-3` — 3 charts + 3 statement captions
+- `variant: grid-4` — 4 charts + 4 statement captions
+
+Grid variants use numbered chart props (chart1, chart2, etc.) and matching statement slots (s1-title/body, s2-title/body, etc.). Single-chart variants use a single chart prop. left-list adds title + item-1..item-4 slots. title-image adds a title slot.
+
+**Syntax rules (all variants):**
+
+- Put Mermaid code in frontmatter using YAML multiline strings (`|`).
+- Start with a Mermaid diagram declaration (`flowchart LR`, `flowchart TD`, etc.).
+- Prefer plain labels (`Node["Text"]`) over HTML labels if rendering is unstable.
+- Use hex colors in `classDef` and `linkStyle`.
+
+**Example: `variant: full`**
+
+## \\`\\`\\`yaml
+
+layout: 4-mermaid
+variant: full
+chart: |
+flowchart LR
+User["User"] --> Edge["Edge Router"]
+Edge -->|cache hit| Cached(["Cached"])
+Edge -->|cache miss| App["App Runtime"]
+App --> DB["Primary DB"]
+classDef success fill:#0b1d0f,stroke:#46a758,color:#63c174;
+class Cached success;
+
+---
+
+\\`\\`\\`
+
+**Example: `variant: grid-2`**
+
+## \\`\\`\\`yaml
+
+layout: 4-mermaid
+variant: grid-2
+chart1: |
+flowchart LR
+Edge["Edge"] --> API["API"]
+API -->|ok| Fast(["Low Latency"])
+classDef success fill:#0b1d0f,stroke:#46a758,color:#63c174;
+class Fast success;
+chart2: |
+flowchart LR
+API["API"] --> Guard["Rate Limit"]
+Guard -->|blocked| Drop(["Dropped"])
+classDef danger fill:#2a1314,stroke:#e5484d,color:#ff6166;
+class Drop danger;
+
+---
+
+::title::
+
+# Traffic Paths
+
+::s1-title::
+Fast path
+
+::s1-body::
+Edge + API success flow.
+
+::s2-title::
+Blocked path
+
+::s2-body::
+Rate limit rejects abusive traffic.
+\\`\\`\\`
+
+---
+
+### 5-open
+
+Flexible layouts with open content areas for custom content (iframes, demos, etc.).
+
+#### `variant: title-space`
+
+Title at top (30%), open area below (70%).
+
+**Slots:**
+
+- `title` — Section title
+- `content` — Open area (any HTML/Vue)
+
+---
+
+#### `variant: title-2-spaces` / `title-3-spaces`
+
+Title at top, 2 or 3 open areas side by side below.
+
+**Slots:**
+
+- `title` — Section title
+- `space-1`, `space-2`, `space-3` — Open areas
+
+---
+
+#### `variant: list-space`
+
+Title + 5 list items on left (1/3), open area on right (2/3).
+
+**Slots:**
+
+- `title` — Section title
+- `item-1` through `item-5` — List items
+- `space` — Open area
+
+---
+
+### 6-quote
+
+#### `variant: center`
+
+Centered quote with attribution.
+
+**Slots:**
+
+- `quote` — Quote text
+- `author` — Attribution (name, title, company)
+
+```yaml
+---
+layout: 6-quote
+variant: center
+---
+
+::quote::
+The best way to predict the future is to build it.
+
+::author::
+— Guillermo Rauch, CEO of Vercel
+```
+
+---
+
+#### `variant: with-statements`
+
+2 statements on left (1/3), quote on right (2/3).
+
+**Slots:**
+
+- `s1-title`, `s1-body` — First statement
+- `s2-title`, `s2-body` — Second statement
+- `quote`, `author` — Quote content
+
+---
+
+### 7-number
+
+#### `variant: one`
+
+Single huge metric, centered.
+
+**Slots:**
+
+- `number` — The metric (e.g., "99.9%")
+- `label` — Description (e.g., "Uptime SLA")
+
+---
+
+#### `variant: two` / `variant: three`
+
+2 or 3 metrics side by side.
+
+**Slots:**
+
+- `number-1`, `label-1` — First metric
+- `number-2`, `label-2` — Second metric
+- `number-3`, `label-3` — Third metric (three only)
+
+---
+
+#### `variant: four-with-title`
+
+Statement on left (1/3), 2×2 grid of 4 metrics on right (2/3).
+
+**Slots:**
+
+- `title`, `subtitle` — Left side statement
+- `number-1`, `label-1` through `number-4`, `label-4` — Metrics
+
+---
+
+#### `variant: six`
+
+6 metrics in 3×2 grid.
+
+**Slots:**
+
+- `number-1`, `label-1` through `number-6`, `label-6`
+
+---
+
+#### `variant: two-with-source` / `three-with-source`
+
+2 or 3 metrics with source citations below each.
+
+**Slots:**
+
+- `number-1`, `label-1`, `source-1` — First metric with citation
+- `number-2`, `label-2`, `source-2` — Second metric
+- `number-3`, `label-3`, `source-3` — Third metric (three-with-source only)
+
+---
+
+### 8-special
+
+#### `variant: qa`
+
+Q&A slide with decorative left panel.
+
+**Structure:**
+
+- Left: Decorative quote bubble SVG + optional custom content
+- Right: Badge + up to 4 icon points (contact info, links, etc.)
+
+**Props:**
+
+- `badge` — Badge text (default: "Q&A")
+- `item1Icon`, `item2Icon`, `item3Icon`, `item4Icon` — Lucide icons
+
+**Slots:**
+
+- `left` — Optional content in left panel
+- `item-1`, `item-2`, `item-3`, `item-4` — Text next to each icon
+
+```yaml
+---
+layout: 8-special
+variant: qa
+badge: Questions?
+item1Icon: mail
+item2Icon: twitter
+---
+
+::item-1::
+hello@vercel.com
+
+::item-2::
+@vercel
+```
+
+---
+
+#### `variant: thank-you`
+
+Centered Vercel triangle + "Thank you" text. No slots.
+
+---
+
+#### `variant: splash`
+
+Centered Vercel triangle only. No slots.
+
+---
+
+### 9-utility
+
+Blank canvases for custom content.
+
+- `variant: blank` — Empty with frame
+- `variant: crosshairs` — Frame + crosshair decorations
+- `variant: full-grid` — Dense alignment grid
+
+Default slot accepts any content.
+
+---
+
+### 10-code
+
+All variants show code in a **code editor frame** with filename header.
+
+**IMPORTANT — Maximum lines of code (LOC) that fit without clipping:**
+
+| Size | Full variant | 2/3 variants (right-1, left-2, right-list, left-list) |
+| ---- | ------------ | ----------------------------------------------------- |
+| `xs` | 23 lines | 19 lines |
+| `sm` | 17 lines | 14 lines |
+| `md` | 14 lines | 11 lines |
+| `lg` | 12 lines | 9 lines |
+
+**Always count your code lines (including blank lines) and pick a `codeSize` that fits.** If the code exceeds the limit, it will be clipped at the bottom. Prefer trimming code to show only the essential parts rather than cramming everything in at `xs`.
+
+**Scrollable mode:** Set `scrollable: true` to allow vertical scrolling for longer code. This should NOT be the default — only use it when showing the complete code is essential and trimming would lose important context. Non-scrollable (clipped) code is the standard look.
+
+#### `variant: full`
+
+Full-width code, clipped at bottom.
+
+**Props:**
+
+- `filename` — Filename shown in header (e.g., `api/hello.ts`)
+- `codeSize` — `xs`, `sm` (default), `md`, `lg`
+- `scrollable` — `true` to enable vertical scrolling (default: `false`, code clips at bottom)
+
+**Slots:**
+
+- `code` — Fenced code block with syntax highlighting
+
+```yaml
+---
+layout: 10-code
+variant: full
+filename: api/hello.ts
+---
+
+::code::
+\\`\\`\\`ts
+export async function GET() {
+ return Response.json({ hello: 'world' })
+}
+\\`\\`\\`
+```
+
+---
+
+#### `variant: right-1`
+
+Statement on left (1/3), code on right (2/3).
+
+**Slots:**
+
+- `title`, `body` — Statement
+- `code` — Code block
+
+---
+
+#### `variant: left-2`
+
+Code on left (2/3), 2 statements on right (1/3).
+
+**Slots:**
+
+- `code` — Code block
+- `s1-title`, `s1-body` — First statement
+- `s2-title`, `s2-body` — Second statement
+
+---
+
+#### `variant: right-list` / `left-list`
+
+Code + title + 4 list items.
+
+**Slots:**
+
+- `code` — Code block
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items
+
+---
+
+### 11-promo
+
+#### `variant: two-statements`
+
+Badge + decorative grid + 2 statements.
+
+**Structure:**
+
+- Top: Badge
+- Middle: Decorative square grid
+- Bottom: 2 Statement blocks side by side
+
+**Props:**
+
+- `badge` — Badge text
+- `gridCols` — Grid columns (default: 14)
+- `gridRows` — Grid rows (default: 3)
+
+**Slots:**
+
+- `s1-title`, `s1-body`, `s1-tag` — First statement
+- `s2-title`, `s2-body`, `s2-tag` — Second statement
+
+---
+
+### playful
+
+Animated full-screen grid layouts.
+
+#### `variant: welcome`
+
+Static "▲ W E L C O M E" display. No configuration needed.
+
+---
+
+#### `variant: triangles`
+
+Random Vercel triangles fade in/out.
+
+**Props:**
+
+- `flashInterval` — ms between new triangles (default: 2500)
+- `fadeDuration` — ms for fade out (default: 4000)
+
+---
+
+#### `variant: values`
+
+Random Vercel values (FTW, DIG DEEP, etc.) fade in/out.
+
+Same props as triangles.
+
+---
+
+#### `variant: splitflap`
+
+Mechanical split-flap display animation.
+
+Use `` components in the slide body:
+
+```yaml
+---
+layout: playful
+variant: splitflap
+---
+
+
+```
+
+**Flap props:**
+
+- `text` — Text to display (max 16 chars). Use `▲` for Vercel icon.
+- `row` — Row number (1–9)
+- `startCol` — Starting column (auto-centers if omitted)
+- `mono` — Use monospace font (default: false)
+- `flipDuration` — ms per character flip (default: 120)
+- `staggerDelay` — ms between letters (default: 100)
+
+---
+
+### 12-youtube
+
+Embedded YouTube video in a **macOS browser frame** (same chrome as 3-screenshot). The browser bar always shows `youtube.com`. Uses privacy-enhanced embedding (`youtube-nocookie.com`).
+
+**Timestamp support:** Include `&t=SECONDS` in the URL to start the video at a specific time. The component auto-extracts `t=` or `start=` from the URL and passes it to the embed player.
+
+#### `variant: full`
+
+Full-width browser frame with embedded video, clipped at bottom.
+
+**Props:**
+
+- `url` — YouTube video URL (supports `youtube.com/watch?v=`, `youtu.be/`, `youtube.com/embed/`). Append `&t=SECONDS` to start at a specific timestamp.
+
+```yaml
+---
+layout: 12-youtube
+variant: full
+url: https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=166
+---
+```
+
+---
+
+#### `variant: left-list`
+
+Video in browser frame on left (1/2), title + 4 list items on right (1/2).
+
+**Props:**
+
+- `url` — YouTube video URL. Append `&t=SECONDS` to start at a specific timestamp.
+
+**Slots:**
+
+- `title` — Section title
+- `item-1`, `item-2`, `item-3`, `item-4` — List items
+
+```yaml
+---
+layout: 12-youtube
+variant: left-list
+url: https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=120
+---
+
+::title::
+Video Walkthrough
+
+::item-1::
+Step 1: Setup
+
+::item-2::
+Step 2: Configure
+
+::item-3::
+Step 3: Deploy
+
+::item-4::
+Step 4: Monitor
+```
+
+---
+
+## Offer Layouts
+
+Sales offer slides for customer proposals. All offer layouts are dark-themed with the Vercel design system. Data is passed via **frontmatter props** (not slots) for structured data like SKUs, details, and team members.
+
+---
+
+### offer-title
+
+Cover slide for a customer offer with title and team members.
+
+**Structure:**
+
+- Large title at top
+- 2×2 team member grid at bottom (name + role in monospace)
+
+**Props:**
+
+- `team1Name`–`team4Name` — Team member names
+- `team1Role`–`team4Role` — Team member roles (shown in monospace, muted)
+
+**Slots:**
+
+- `title` — Main heading (use `
` for line breaks)
+
+```yaml
+---
+layout: offer-title
+team1Name: Jane Smith
+team1Role: ACCOUNT MANAGER
+team2Name: John Doe
+team2Role: SOLUTIONS ENGINEER
+team3Name: Alice Chen
+team3Role: CSM
+team4Name: Bob Wilson
+team4Role: CRO
+---
+::title::
+# Acme Corp's
Vercel offer
+```
+
+---
+
+### offer-statement
+
+Badge + title on left, numbered points on right.
+
+**Structure:**
+
+- Left: Outline badge + large title
+- Right: Up to 4 numbered points (01–04) with title + body
+
+**Props:**
+
+- `badge` — Badge text (default: "OUR PRICING PHILOSOPHY")
+- `badgeColor` — Badge border color (default: "#A0A0A0")
+
+**Slots:**
+
+- `title` — Left side heading
+- `point-1-title`, `point-1-body` — First numbered point
+- `point-2-title`, `point-2-body` — Second numbered point
+- `point-3-title`, `point-3-body` — Third point
+- `point-4-title`, `point-4-body` — Fourth point
+
+```yaml
+---
+layout: offer-statement
+badge: OUR PRICING PHILOSOPHY
+---
+
+::title::
+Transparency
& predictability
+
+::point-1-title::
+Usage-based
+
+::point-1-body::
+Pay for only what you use
+
+::point-2-title::
+Product flexibility
+
+::point-2-body::
+One commit across products, shift spend where you need
+
+::point-3-title::
+Scales with you
+
+::point-3-body::
+The more you buy, the better your discount
+```
+
+---
+
+### offer-product-grid
+
+Product portfolio grid showing all Vercel SKUs organized by category.
+
+**Structure:**
+
+- Title + subtitle at top
+- Grid of product categories with individual SKU pills
+- Diagonal background pattern behind grid
+
+**Props:**
+
+- `categories` — Array of `{ title, products: [{ name }], highlighted? }` (has sensible defaults with all Vercel products)
+- `rows` — Array of index arrays defining grid layout (default: `[[0,1], [2,3,4], [5,6,7,8]]`)
+
+**Slots:**
+
+- `title` — Grid heading
+- `subtitle` — Subtitle text
+
+```yaml
+---
+layout: offer-product-grid
+---
+
+::title::
+Introducing Flexible Commitment
+
+::subtitle::
+Giving your team access to the entire Vercel product portfolio
+```
+
+---
+
+### offer-timeline
+
+Flex commit timeline visualization with checkbox grid.
+
+**Structure:**
+
+- Badge at top
+- Large headline (supports mixed white/muted text via HTML spans)
+- Month 1–12 timeline with animated checkbox grid + fade overlay
+
+**Props:**
+
+- `badge` — Badge text (default: "FLEX COMMIT")
+- `startLabel` — Left label (default: "MONTH 1")
+- `endLabel` — Right label (default: "MONTH 12")
+- `months` — 12-element array of boolean arrays for checkbox states
+
+**Slots:**
+
+- `title` — Headline (use `` and `` for mixed styling)
+
+```yaml
+---
+layout: offer-timeline
+---
+
+::title::
+Swap SKUs anytime to align with
shifting needs and seasonality.
+```
+
+---
+
+### offer-pricing
+
+Discount matrix on left, rate card on right.
+
+**Structure:**
+
+- Left: Title + 2×2 discount matrix (BASE/MODERATE/HIGH/BEST)
+- Right: Rate card table with diagonal background
+
+**Props:**
+
+- `badgeText` — Rate card badge (default: "FLEX COMMIT RATE CARD")
+- `footerText` — Rate card footer (default: "ENTIRE RATE CARD AVAILABLE WITH FULL PROPOSAL")
+- `skus` — Array of `{ name, listPrice, discountPrice }` (default: 3 placeholder SKUs)
+
+**Slots:**
+
+- `title` — Left side heading
+
+```yaml
+---
+layout: offer-pricing
+skus:
+ - name: Fluid Compute
+ listPrice: $0.18/GB-hr
+ discountPrice: $0.12/GB-hr
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.40/M
+ - name: Bandwidth
+ listPrice: $0.15/GB
+ discountPrice: $0.10/GB
+---
+
+::title::
+Pricing that
scales with
you.
+```
+
+---
+
+### offer-roi
+
+Centered card with label/value rows and dotted leaders.
+
+**Structure:**
+
+- Centered rounded card with outline badge
+- Up to 3 key-value rows with dotted line between label and value
+
+**Props:**
+
+- `badge` — Card badge text (default: "ANTICIPATED QUANTIFIED VALUE")
+
+**Slots:**
+
+- `label`, `value` — First row (default: "ROI" / "$XM")
+- `label-2`, `value-2` — Second row (optional)
+- `label-3`, `value-3` — Third row (optional)
+
+```yaml
+---
+layout: offer-roi
+---
+
+::label::
+ROI
+
+::value::
+$2.5M
+
+::label-2::
+Annual savings
+
+::value-2::
+$500K
+```
+
+---
+
+### offer-details
+
+Header + key-value sidebar on left, rate card on right.
+
+**Structure:**
+
+- Header bar with customer name
+- Left: Key-value detail rows (flexible count)
+- Right: Rate card with diagonal background
+
+**Props:**
+
+- `headerText` — Header text (default: "[Customer name] offer")
+- `details` — Array of `{ label, value }` for the sidebar rows
+- `badgeText` — Rate card badge
+- `footerText` — Rate card footer
+- `skus` — Array of `{ name, listPrice, discountPrice }`
+
+```yaml
+---
+layout: offer-details
+headerText: Acme Corp offer
+details:
+ - label: Flex commit balance
+ value: $120K / YR
+ - label: Term
+ value: 2 YRS
+ - label: Support level
+ value: Enterprise
+ - label: Start date
+ value: Q1 2026
+skus:
+ - name: Fluid Compute
+ listPrice: $0.18/GB-hr
+ discountPrice: $0.12/GB-hr
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.40/M
+ - name: Bandwidth
+ listPrice: $0.15/GB
+ discountPrice: $0.10/GB
+---
+
+```
+
+---
+
+### offer-comparison
+
+Side-by-side comparison of 2–3 offer options, each with rate card.
+
+**Structure:**
+
+- Header bar with customer name
+- Equal-width columns, each with: option badge, balance/term KV rows, small rate card
+
+**Props:**
+
+- `headerText` — Header text (default: "[Customer name] offer comparison")
+- `options` — Array of `{ label, balance, term, skus: [{ name, listPrice, discountPrice }] }`
+
+```yaml
+---
+layout: offer-comparison
+headerText: Acme Corp offer comparison
+options:
+ - label: OPTION 1
+ balance: $100K / YR
+ term: 1 YR
+ skus:
+ - name: Fluid Compute
+ listPrice: $0.18
+ discountPrice: $0.15
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.70/M
+ - label: OPTION 2
+ balance: $120K / YR
+ term: 2 YRS
+ skus:
+ - name: Fluid Compute
+ listPrice: $0.18
+ discountPrice: $0.12
+ - name: Edge Requests
+ listPrice: $2/M
+ discountPrice: $1.40/M
+---
+
+```
+
+---
+
+### offer-before-after
+
+Side-by-side before/after comparison with colored badges and icon rows.
+
+**Structure:**
+
+- Left: Red "BEFORE STATE" badge + year + title + X-icon rows
+- Right: Green "AFTER STATE" badge + year + title + check-icon rows
+
+**Props:**
+
+- `beforeBadge` — Left badge text (default: "BEFORE STATE")
+- `afterBadge` — Right badge text (default: "AFTER STATE")
+- `beforeYear` — Left year label (default: "2025 & EARLIER")
+- `afterYear` — Right year label (default: "2026+")
+- `beforeColor` — Left badge color (default: red `#DA2F36`)
+- `afterColor` — Right badge color (default: green `#63C173`)
+
+**Slots:**
+
+- `before-title` — Left title (default: "MIU")
+- `after-title` — Right title (default: "Flex Commit")
+- `before-1` through `before-6` — Before rows (with X icon)
+- `after-1` through `after-6` — After rows (with check icon)
+
+```yaml
+---
+layout: offer-before-after
+---
+
+::before-title::
+MIU
+
+::after-title::
+Flex Commit
+
+::before-1::
+Separate commits per SKU
+
+::after-1::
+Max flexibility
+
+::before-2::
+Monthly burndown
+
+::after-2::
+Annual burndown
+
+::before-3::
+Shallow blanket discount
+
+::after-3::
+Private rate card
+```
diff --git a/presentations/getting-started-workflows-webinar/slides.md b/presentations/getting-started-workflows-webinar/slides.md
new file mode 100644
index 0000000..33a3631
--- /dev/null
+++ b/presentations/getting-started-workflows-webinar/slides.md
@@ -0,0 +1,679 @@
+---
+theme: ./
+title: Getting Started with Vercel Workflows
+footerLogo: wordmark
+footerTitle: true
+layout: 1-title
+variant: title
+subtitle1Image: https://vercel.com/api/www/avatar/d86685cc0ac958594071ba9cf94e5c50a3551011
+subtitle2Icon: code
+subtitle3Icon: cake
+subtitle4Icon: bot
+subtitleSize: lg
+---
+
+::title::
+# Getting Started with Vercel Workflows
+
+::subtitle-1::
+Pranay Prakash, Head of Workflows
+
+::subtitle-2::
+Long-running backends in plain TypeScript
+
+::subtitle-3::
+Demo-first walkthrough
+
+::subtitle-4::
+Streaming, agents, and GA
+
+
+---
+layout: 2-statement
+variant: large
+---
+
+::title::
+# The code you run on day one can be the code you ship
+
+::subtitle::
+Workflow is about removing the whole “now productionize it with queues, workers, schedulers, and state machines” phase.
+
+
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "Demo First"
+---
+
+::title::
+Let's jump straight into the birthday card app
+
+::subtitle::
+Then we will break apart the code, the runtime model, and how that extends to agents.
+
+
+---
+layout: 2-statement
+variant: title-4
+tagPosition: inline
+---
+
+::title::
+# Birthday card generator
+
+::s1-tag::
+Input
+
+::s1-title::
+One request
+
+::s1-body::
+Describe the card, pick a birthday, add guests, and send.
+
+::s2-tag::
+Parallel
+
+::s2-title::
+Image + message
+
+::s2-body::
+Generate both pieces together, then stream progress to the UI.
+
+::s3-tag::
+Human
+
+::s3-title::
+RSVP signatures
+
+::s3-body::
+Guests click a webhook link to sign the card and resume the workflow.
+
+::s4-tag::
+Time
+
+::s4-title::
+Deliver later
+
+::s4-body::
+Sleep until the birthday, then send the final postcard.
+
+
+---
+layout: 4-mermaid
+variant: title-image
+chart: |
+ flowchart LR
+ A["User submits form"] --> B["POST /api/generate"]
+ B --> C["start(generateBirthdayCard)"]
+ C --> D["generate prompts"]
+ D --> E["generate image"]
+ D --> F["generate message"]
+ C --> G["send RSVP emails"]
+ G --> H["wait for webhook clicks"]
+ H --> I["sleep until birthday"]
+ I --> J["send final postcard"]
+ classDef accent fill:#111111,stroke:#666666,color:#ffffff;
+ class C,E,F,G,H,I,J accent;
+---
+
+::title::
+# One workflow, multiple async patterns
+
+
+---
+layout: 2-statement
+variant: cols-4
+tagPosition: above
+---
+
+::title::
+# What to watch during the live demo
+
+::s1-tag::
+1
+
+::s1-title::
+Live progress
+
+::s1-body::
+The UI updates as the workflow runs, before the final result is done.
+
+::s2-tag::
+2
+
+::s2-title::
+Parallel steps
+
+::s2-body::
+Image and message generation happen at the same time.
+
+::s3-tag::
+3
+
+::s3-title::
+Suspension
+
+::s3-body::
+The workflow actually stops running while it waits for RSVP clicks.
+
+::s4-tag::
+4
+
+::s4-title::
+Resumption
+
+::s4-body::
+The workflow wakes back up exactly where it left off.
+
+
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "After The Demo"
+---
+
+::title::
+Now let's break apart what actually happened
+
+::subtitle::
+The interesting part is how little infrastructure code is needed to model a multi-step, multi-day process.
+
+
+---
+layout: 10-code
+variant: left-2
+filename: app/api/generate/generate-birthday-card.ts
+codeSize: xs
+---
+
+::code::
+```ts
+export const generateBirthdayCard = async (...) => {
+ 'use workflow';
+
+ const { textPrompt, imagePrompt } = await generatePrompts(prompt);
+
+ const [image, text] = await Promise.all([
+ generateImage(imagePrompt),
+ generateMessage(textPrompt),
+ ]);
+
+ const webhooks = rsvpEmails.map(() => createWebhook());
+ await Promise.all(rsvpEmails.map((email, i) =>
+ requestRsvp(email, webhooks[i].url, image, text)
+ ));
+
+ const rsvpReplies = await Promise.all(webhooks);
+ await sleep(birthday!);
+ await sendRecipientEmail({ recipientEmail, cardImage: image, cardText: text, rsvpReplies });
+};
+```
+
+::s1-title::
+This reads like product logic
+
+::s1-body::
+It is top-to-bottom business logic, not a map of workers, queues, and schedulers.
+
+::s2-title::
+This is the main abstraction
+
+::s2-body::
+A workflow is just long-running code with explicit async boundaries.
+
+
+---
+layout: 10-code
+variant: right-list
+filename: app/api/generate/route.ts + app/api/generate/[runId]/stream/route.ts
+codeSize: xs
+---
+
+::code::
+```ts
+const run = await start(generateBirthdayCard, [...]);
+
+return new Response(run.readable, {
+ headers: {
+ 'x-workflow-run-id': run.runId,
+ },
+});
+
+const stream = run.getReadable({ startIndex });
+return new Response(stream);
+```
+
+::title::
+# Two routes, not an orchestration system
+
+::item-1::
+One route starts the workflow
+
+::item-2::
+One route resumes the stream
+
+::item-3::
+No webhook correlation database
+
+::item-4::
+No worker app to coordinate separately
+
+
+---
+layout: 2-statement
+variant: cols-3
+tagPosition: inline
+---
+
+::title::
+# Hooks and webhooks are the most powerful primitive here
+
+::s1-tag::
+Webhook
+
+::s1-title::
+One-time public URL
+
+::s1-body::
+Perfect for email links, approvals, signatures, and “click to continue” flows.
+
+::s2-tag::
+Hook
+
+::s2-title::
+Resume from your own code
+
+::s2-body::
+Use a token to resume from Slack, GitHub, internal events, or another route.
+
+::s3-tag::
+Pattern
+
+::s3-title::
+Event bus without extra state
+
+::s3-body::
+One workflow can naturally map to one Slack thread, one PR, one task, or one onboarding flow.
+
+
+---
+layout: 2-statement
+variant: cols-2
+tagPosition: inline
+---
+
+::title::
+# Sleep is more than a timer
+
+::s1-tag::
+Delay
+
+::s1-title::
+Wait for days or weeks
+
+::s1-body::
+The workflow suspends fully and resumes later. No server is sitting there “waiting.”
+
+::s2-tag::
+Timeout
+
+::s2-title::
+Race hooks vs sleep
+
+::s2-body::
+“Wait for a webhook, but only for 24 hours” becomes a simple pattern instead of custom infrastructure.
+
+
+---
+layout: 2-statement
+variant: cols-3
+tagPosition: inline
+---
+
+::title::
+# What `use workflow` and `use step` are actually doing
+
+::s1-tag::
+Workflow
+
+::s1-title::
+Deterministic replay
+
+::s1-body::
+The workflow function replays quickly using the event log instead of redoing side effects.
+
+::s2-tag::
+Step
+
+::s2-title::
+Full Node.js boundary
+
+::s2-body::
+Steps run the real work, serialize inputs and outputs, and become retryable execution units.
+
+::s3-tag::
+Result
+
+::s3-title::
+Code stays simple
+
+::s3-body::
+You get durability without turning your code into a state machine DSL.
+
+
+---
+layout: 4-mermaid
+variant: left-list
+chart: |
+ flowchart TD
+ A["Workflow starts"] --> B["Call step"]
+ B --> C["Step runs"]
+ C --> D["Inputs + outputs logged"]
+ D --> E["Workflow replays"]
+ E --> F["Resume from event log"]
+ F --> G["Wait on hook / sleep"]
+ G --> H["Replay and continue"]
+ classDef accent fill:#111111,stroke:#666666,color:#ffffff;
+ class B,C,D,E,F,G,H accent;
+---
+
+::title::
+# The event log powers both durability and observability
+
+::item-1::
+Every step has inputs and outputs
+
+::item-2::
+Parallel steps show up naturally
+
+::item-3::
+Replay and recovery come from the same system
+
+::item-4::
+You get the audit trail without building it yourself
+
+
+---
+layout: 2-statement
+variant: cols-3
+tagPosition: inline
+---
+
+::title::
+# Streaming is durable too
+
+::s1-tag::
+UI
+
+::s1-title::
+Live progress
+
+::s1-body::
+Steps write progress to a workflow stream so the client sees updates before the run finishes.
+
+::s2-tag::
+Recovery
+
+::s2-title::
+Resume from chunk index
+
+::s2-body::
+If the page reloads or the connection drops, the client can reconnect and continue from where it left off.
+
+::s3-tag::
+Scale
+
+::s3-title::
+Same primitive for agents
+
+::s3-body::
+Simple apps send progress JSON; agents can stream every token, tool call, and result.
+
+
+---
+layout: 10-code
+variant: left-2
+filename: flight-booking-app/workflows/chat/index.ts
+codeSize: xs
+---
+
+::code::
+```ts
+export async function chat(initialMessages: UIMessage[]) {
+ 'use workflow';
+
+ const writable = getWritable();
+
+ const agent = new DurableAgent({
+ model: 'bedrock/claude-haiku-4-5-20251001-v1',
+ system: FLIGHT_ASSISTANT_PROMPT,
+ tools: flightBookingTools,
+ });
+
+ await agent.stream({
+ messages,
+ writable,
+ preventClose: true,
+ });
+}
+```
+
+::s1-title::
+An agent is basically just a workflow
+
+::s1-body::
+LLM calls, tool calls, retries, and long-running state all fit the same model.
+
+::s2-title::
+Why DurableAgent matters
+
+::s2-body::
+It gives agent builders a native workflow abstraction instead of a fragile loop around `streamText`.
+
+
+---
+layout: 2-statement
+variant: cols-4
+tagPosition: above
+---
+
+::title::
+# Getting started is intentionally small
+
+::s1-tag::
+Setup
+
+::s1-title::
+Wrap the framework
+
+::s1-body::
+In Next.js, the setup is basically `withWorkflow(nextConfig)`.
+
+::s2-tag::
+Adoption
+
+::s2-title::
+Start with one painful path
+
+::s2-body::
+Retries, approvals, delayed sends, or multi-step AI are perfect first candidates.
+
+::s3-tag::
+Breadth
+
+::s3-title::
+Many frameworks
+
+::s3-body::
+Next.js, Astro, Express, Fastify, Hono, Nitro, Nuxt, SvelteKit, Vite, and more.
+
+::s4-tag::
+Launch
+
+::s4-title::
+Python too
+
+::s4-body::
+GA is about broadening where the model applies, not just polishing one API.
+
+
+---
+layout: 2-statement
+variant: grid-4
+tagPosition: above
+---
+
+::title::
+# Why GA matters
+
+::s1-tag::
+Internal
+
+::s1-title::
+Used across Vercel agents
+
+::s1-body::
+This is no longer a niche experiment. It is part of how Vercel runs long-lived agent systems.
+
+::s2-tag::
+Customer
+
+::s2-title::
+Flora
+
+::s2-body::
+A creative agent workflow where the core product experience is built on workflows.
+
+::s3-tag::
+Customer
+
+::s3-title::
+Durable
+
+::s3-body::
+Workflow-powered onboarding and generated customer sites as part of a real production flow.
+
+::s4-tag::
+Scale
+
+::s4-title::
+5,000+ step runs
+
+::s4-body::
+The model is not limited to toy demos. It is designed for serious, high-step, high-parallelism workloads.
+
+
+---
+layout: 2-statement
+variant: large
+---
+
+::title::
+# Durable systems should be easy to explain from the code itself
+
+::subtitle::
+If your team can read the workflow top to bottom, they can build it, debug it, and trust it in production.
+
+
+---
+layout: 8-special
+variant: qa
+badge: Questions?
+item1Icon: mail
+item2Icon: github
+item3Icon: book-open
+item4Icon: bot
+---
+
+::left::
+## Thank you
+
+Let's talk about the workflows you want to make durable next.
+
+::item-1::
+pranay@vercel.com
+
+::item-2::
+github.com/vercel/workflow-examples
+
+::item-3::
+useworkflow.dev
+
+::item-4::
+Hooks, streaming, agents, and GA
+
+
diff --git a/presentations/getting-started-workflows-webinar/slides.with-notes.bak b/presentations/getting-started-workflows-webinar/slides.with-notes.bak
new file mode 100644
index 0000000..598738a
--- /dev/null
+++ b/presentations/getting-started-workflows-webinar/slides.with-notes.bak
@@ -0,0 +1,793 @@
+---
+theme: ./
+title: Getting Started with Vercel Workflows
+footerLogo: wordmark
+footerTitle: true
+layout: 1-title
+variant: title
+subtitle1Image: https://vercel.com/api/www/avatar/d86685cc0ac958594071ba9cf94e5c50a3551011
+subtitle2Icon: code
+subtitleSize: lg
+---
+
+::title::
+# Getting Started with Vercel Workflows
+
+::subtitle-1::
+Pranay Prakash, Head of Workflows
+
+::subtitle-2::
+Durable backends in plain TypeScript
+
+
+---
+---
+layout: 2-statement
+variant: large
+---
+
+::title::
+# Long-running backends should feel like writing application code
+
+::subtitle::
+Not stitching together queues, retries, schedulers, and state machines by hand.
+
+
+---
+---
+layout: 1-title
+variant: agenda
+badge: Today's Flow
+---
+
+::item-1::
+Why async systems get messy fast
+
+::item-2::
+The Workflow mental model
+
+::item-3::
+Live demo: birthday card generator
+
+::item-4::
+What durability looks like in code
+
+::item-5::
+Human input, waiting, and resuming
+
+::item-6::
+Patterns beyond one demo app
+
+::item-7::
+How to adopt Workflow incrementally
+
+::item-8::
+Q&A
+
+
+---
+---
+layout: 2-statement
+variant: title-3
+tagPosition: inline
+---
+
+::title::
+# Why this matters
+
+::s1-tag::
+Today
+
+::s1-title::
+Async code is everywhere
+
+::s1-body::
+Background jobs, approval flows, delayed sends, retries, and agent loops show up in almost every modern app.
+
+::s2-tag::
+Pain
+
+::s2-title::
+The usual stack sprawls
+
+::s2-body::
+Queues, workers, cron, retry logic, and state tracking get split across services and become harder to reason about.
+
+::s3-tag::
+Shift
+
+::s3-title::
+Durability moves into your code
+
+::s3-body::
+Workflow turns plain TypeScript functions into resilient, observable processes without forcing a rearchitecture.
+
+
+---
+---
+layout: 2-statement
+variant: cols-3
+tagPosition: inline
+---
+
+::title::
+# What you'll learn in this session
+
+::s1-tag::
+Core
+
+::s1-title::
+Two directives
+
+::s1-body::
+How `use workflow` and `use step` convert ordinary functions into durable execution boundaries.
+
+::s2-tag::
+Practical
+
+::s2-title::
+One real product flow
+
+::s2-body::
+We will build the mental model through a birthday card app with generation, approvals, waiting, and delivery.
+
+::s3-tag::
+Adoption
+
+::s3-title::
+One migration recipe
+
+::s3-body::
+How to take an existing async path or AI agent and convert it into a workflow in minutes.
+
+
+---
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "Part 1 of 4"
+---
+
+::title::
+The fastest way to explain Workflow is through one product story
+
+::subtitle::
+We are going to use a playful app so the system design stays memorable.
+
+
+---
+---
+layout: 2-statement
+variant: title-3
+tagPosition: inline
+---
+
+::title::
+# Demo app: birthday card generator
+
+::s1-tag::
+Parallel
+
+::s1-title::
+Two AI tasks at once
+
+::s1-body::
+Generate an image and a message in parallel from one user prompt.
+
+::s2-tag::
+Human Input
+
+::s2-title::
+RSVPs as workflow events
+
+::s2-body::
+Invite friends, wait for replies, and resume the flow when real people interact.
+
+::s3-tag::
+Scheduling
+
+::s3-title::
+Deliver at the right moment
+
+::s3-body::
+Pause until the birthday, then send the final card and RSVP summary to the recipient.
+
+
+---
+---
+layout: 4-mermaid
+variant: title-image
+chart: |
+ flowchart LR
+ A["User submits prompt"] --> B["POST /api/generate"]
+ B --> C["start(generateBirthdayCard)"]
+ C --> D["generatePrompts()"]
+ D --> E["generateImage()"]
+ D --> F["generateMessage()"]
+ C --> G["requestRsvp()"]
+ G --> H["createWebhook() waits for replies"]
+ H --> I["sleep(until birthday)"]
+ I --> J["sendRecipientEmail()"]
+ classDef accent fill:#111111,stroke:#666666,color:#ffffff;
+ class C,E,F,G,H,I,J accent;
+---
+
+::title::
+# One workflow, multiple real-world async patterns
+
+
+---
+---
+layout: 10-code
+variant: right-list
+filename: app/api/generate/route.ts
+codeSize: sm
+---
+
+::code::
+```ts
+export const POST = async (request: Request) => {
+ const body = await request.json();
+
+ const run = await start(generateBirthdayCard, [
+ body.prompt,
+ body.recipientEmail,
+ body.rsvpEmails,
+ new Date(body.eventDate),
+ ]);
+
+ const values = await run.returnValue;
+ return NextResponse.json(values);
+};
+```
+
+::title::
+# Workflow starts from a normal route
+
+::item-1::
+No separate worker app
+
+::item-2::
+No custom queue producer
+
+::item-3::
+Your API returns workflow output
+
+::item-4::
+The call site stays easy to read
+
+
+---
+---
+layout: 10-code
+variant: left-2
+filename: app/api/generate/generate-birthday-card.ts
+codeSize: xs
+---
+
+::code::
+```ts
+export const generateBirthdayCard = async (...) => {
+ 'use workflow';
+
+ const { textPrompt, imagePrompt } = await generatePrompts(prompt);
+
+ const [image, text] = await Promise.all([
+ generateImage(imagePrompt),
+ generateMessage(textPrompt),
+ ]);
+
+ const webhooks = rsvpEmails.map(() => createWebhook());
+ await Promise.all(rsvpEmails.map((email, i) =>
+ requestRsvp(email, webhooks[i].url)
+ ));
+
+ const rsvpReplies = await Promise.all(webhooks);
+ await sleep(birthday!);
+ await sendRecipientEmail({ recipientEmail, cardImage: image, cardText: text, rsvpReplies });
+};
+```
+
+::s1-title::
+`use workflow`
+
+::s1-body::
+This function becomes the durable orchestrator for the whole flow.
+
+::s2-title::
+Read it top to bottom
+
+::s2-body::
+The control flow stays understandable even though the work spans time, models, emails, and human actions.
+
+
+---
+---
+layout: 10-code
+variant: right-list
+filename: app/api/generate/generate-image.ts + generate-message.ts
+codeSize: sm
+---
+
+::code::
+```ts
+export const generateImage = async (prompt: string) => {
+ 'use step';
+ const { files } = await generateText({
+ model: 'google/gemini-2.5-flash-image',
+ prompt,
+ });
+ return files.at(0);
+};
+
+export const generateMessage = async (prompt: string) => {
+ 'use step';
+ const { text } = await generateText({
+ model: 'openai/gpt-5-nano',
+ prompt,
+ });
+ return text;
+};
+```
+
+::title::
+# Each async boundary becomes explicit
+
+::item-1::
+Model calls are isolated into steps
+
+::item-2::
+Retries happen at the right boundary
+
+::item-3::
+Outputs are captured per step
+
+::item-4::
+Observability matches the code you wrote
+
+
+---
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "Live Demo"
+---
+
+::title::
+Switch from slides to the app
+
+::subtitle::
+The goal is not just to generate a card. The goal is to watch a durable workflow move through real states.
+
+
+---
+---
+layout: 2-statement
+variant: cols-4
+tagPosition: above
+---
+
+::title::
+# What to watch during the demo
+
+::s1-tag::
+1
+
+::s1-title::
+Start
+
+::s1-body::
+Submit one prompt and kick off the workflow from the UI.
+
+::s2-tag::
+2
+
+::s2-title::
+Parallel work
+
+::s2-body::
+Image and message generation can happen together.
+
+::s3-tag::
+3
+
+::s3-title::
+Pause
+
+::s3-body::
+The workflow waits for RSVP clicks and for the birthday delay.
+
+::s4-tag::
+4
+
+::s4-title::
+Resume
+
+::s4-body::
+The final email sends only after the required external events complete.
+
+
+---
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "Part 2 of 4"
+---
+
+::title::
+What just happened is the product story
+
+::subtitle::
+Now let's turn that story into a reusable mental model you can apply to your own app.
+
+
+---
+---
+layout: 2-statement
+variant: title-4
+tagPosition: inline
+---
+
+::title::
+# Four primitives to remember
+
+::s1-tag::
+Entrypoint
+
+::s1-title::
+`use workflow`
+
+::s1-body::
+Marks the durable orchestrator.
+
+::s2-tag::
+Boundary
+
+::s2-title::
+`use step`
+
+::s2-body::
+Marks retryable units of work.
+
+::s3-tag::
+External Event
+
+::s3-title::
+`createWebhook`
+
+::s3-body::
+Lets humans or systems resume a waiting workflow.
+
+::s4-tag::
+Time
+
+::s4-title::
+`sleep`
+
+::s4-body::
+Lets a workflow pause and continue later without custom schedulers.
+
+
+---
+---
+layout: 4-mermaid
+variant: left-list
+chart: |
+ flowchart TD
+ A["Workflow begins"] --> B["Step succeeds"]
+ B --> C["State + output recorded"]
+ C --> D["Next step runs"]
+ D --> E{"Failure?"}
+ E -->|yes| F["Retry only failed step"]
+ E -->|no| G["Continue forward"]
+ G --> H["Pause on webhook or sleep"]
+ H --> I["Resume without replaying completed work"]
+ classDef accent fill:#111111,stroke:#666666,color:#ffffff;
+ class B,C,D,F,H,I accent;
+---
+
+::title::
+# The event log is the superpower
+
+::item-1::
+Completed work is persisted
+
+::item-2::
+Retries target the failing boundary
+
+::item-3::
+Pauses become first-class state
+
+::item-4::
+Recovery does not mean starting over
+
+
+---
+---
+layout: 2-statement
+variant: cols-3
+tagPosition: inline
+---
+
+::title::
+# Why this feels different from the usual stack
+
+::s1-tag::
+Less Glue
+
+::s1-title::
+Fewer moving parts
+
+::s1-body::
+You are not wiring queue producers, workers, retry policies, and schedulers as separate systems.
+
+::s2-tag::
+More Clarity
+
+::s2-title::
+Code matches runtime
+
+::s2-body::
+The observable units in the platform line up with the functions and steps in your source code.
+
+::s3-tag::
+Safer AI
+
+::s3-title::
+Agents become practical
+
+::s3-body::
+Long-running tool loops, approvals, and resumable streams stop being one-off infrastructure projects.
+
+
+---
+---
+layout: 2-statement
+variant: transition
+transitionLabel: "Part 3 of 4"
+---
+
+::title::
+The birthday card app is one example, not the whole story
+
+::subtitle::
+Once the mental model clicks, the same approach applies to agent patterns, framework integrations, and production workflows.
+
+
+---
+---
+layout: 2-statement
+variant: cols-3
+tagPosition: inline
+---
+
+::title::
+# More examples from this repo
+
+::s1-tag::
+Patterns
+
+::s1-title::
+AI SDK workflow patterns
+
+::s1-body::
+Sequential, parallel, routing, orchestrator-worker, and evaluator loop patterns built on top of Workflow.
+
+::s2-tag::
+Agents
+
+::s2-title::
+Flight booking app
+
+::s2-body::
+A durable AI agent with tools, multi-turn state, retries, and stream reconnection.
+
+::s3-tag::
+Reach
+
+::s3-title::
+Framework integrations
+
+::s3-body::
+The examples repo already shows Workflow across Next.js, Astro, Hono, Nitro, Nuxt, SvelteKit, and Vite.
+
+
+---
+---
+layout: 2-statement
+variant: title-3
+tagPosition: inline
+---
+
+::title::
+# How to adopt Workflow incrementally
+
+::s1-tag::
+Start Small
+
+::s1-title::
+Pick one async path
+
+::s1-body::
+Choose a flow that already hurts: approvals, retries, delayed sends, or multi-step AI processing.
+
+::s2-tag::
+Draw Boundaries
+
+::s2-title::
+Mark the expensive edges
+
+::s2-body::
+Put model calls, external APIs, email sends, and side effects behind `use step`.
+
+::s3-tag::
+Replace Glue
+
+::s3-title::
+Keep your app, remove orchestration
+
+::s3-body::
+Start the workflow from your existing route or handler and let the platform manage durability underneath.
+
+
+---
+---
+layout: 10-code
+variant: right-list
+filename: next.config.ts
+codeSize: sm
+---
+
+::code::
+```ts
+import { withWorkflow } from 'workflow/next';
+
+const nextConfig = {};
+
+export default withWorkflow(nextConfig);
+```
+
+::title::
+# The setup story is intentionally small
+
+::item-1::
+Bring Workflow into the framework you already use
+
+::item-2::
+Keep routes, components, and deployment flow familiar
+
+::item-3::
+Add workflows where you need durability
+
+::item-4::
+Expand from one use case to many
+
+
+---
+---
+layout: 2-statement
+variant: cols-3
+tagPosition: inline
+---
+
+::title::
+# Migration recipe you can use tomorrow
+
+::s1-tag::
+1
+
+::s1-title::
+Find the workflow
+
+::s1-body::
+Look for the place where one request turns into a multi-step process.
+
+::s2-tag::
+2
+
+::s2-title::
+Isolate the steps
+
+::s2-body::
+Move each durable boundary into a small, testable function with `use step`.
+
+::s3-tag::
+3
+
+::s3-title::
+Add time and humans
+
+::s3-body::
+Once the flow is durable, webhook waits, approvals, scheduling, and agent loops feel natural instead of scary.
+
+
+---
+---
+layout: 2-statement
+variant: large
+---
+
+::title::
+# Durable systems should be easy to explain from the code itself
+
+::subtitle::
+That is the bar. If your team can read the workflow top to bottom, they can own it in production.
+
+
+---
+---
+layout: 8-special
+variant: qa
+badge: Q&A
+item1Icon: mail
+item2Icon: github
+item3Icon: book-open
+item4Icon: cake
+---
+
+::left::
+## Thank you
+
+Let's talk about the workflows you want to make durable next.
+
+::item-1::
+pranay@vercel.com
+
+::item-2::
+github.com/vercel/workflow-examples
+
+::item-3::
+useworkflow.dev
+
+::item-4::
+Birthday card demo + repo tour
+
+
diff --git a/presentations/getting-started-workflows-webinar/speaker-notes.md b/presentations/getting-started-workflows-webinar/speaker-notes.md
new file mode 100644
index 0000000..1e5dec5
--- /dev/null
+++ b/presentations/getting-started-workflows-webinar/speaker-notes.md
@@ -0,0 +1,130 @@
+# Speaker Notes
+
+Short presenter notes based on the actual mock walkthrough.
+
+## Slide 1 - Getting Started with Vercel Workflows
+
+- Quick intro.
+- Demo first, then code, then the broader story.
+- Focus today: long-running backends in plain TypeScript.
+
+## Slide 2 - The code you run on day one can be the code you ship
+
+- This is the real thesis.
+- We are used to demo first, then “productionize” later.
+- Workflow is trying to remove that whole second phase.
+
+## Slide 3 - Let's jump straight into the birthday card app
+
+- I want to go directly into the demo.
+- Then I will break apart the code and runtime.
+
+## Slide 4 - Birthday card generator
+
+- One request.
+- Parallel image + message generation.
+- Guests sign with RSVP links.
+- Wait until the birthday.
+- Send the final postcard.
+
+## Slide 5 - One workflow, multiple async patterns
+
+- Immediate work.
+- Human input.
+- Waiting on time.
+- Final delivery.
+
+## Slide 6 - What to watch during the live demo
+
+- Live progress updates.
+- Parallel steps.
+- Real suspension.
+- Real resumption.
+
+## Slide 7 - Now let's break apart what actually happened
+
+- After the demo, move into code.
+- The key message is how little infrastructure code is here.
+
+## Slide 8 - Workflow code
+
+- This reads like product logic.
+- It matches how I would whiteboard the feature.
+- That is the abstraction I want people to remember.
+
+## Slide 9 - Two routes, not an orchestration system
+
+- One route starts the workflow.
+- One route resumes the stream.
+- No extra DB for webhook correlation.
+- No separate worker service.
+
+## Slide 10 - Hooks and webhooks
+
+- This is one of the most powerful primitives.
+- Webhooks for public one-time URLs.
+- Hooks for internal resume logic.
+- Great for Slack, GitHub, approvals, and event-driven systems.
+
+## Slide 11 - Sleep is more than a timer
+
+- This is a real long-running primitive.
+- Sleep for days or weeks.
+- Also mention timeout patterns with hook vs sleep.
+
+## Slide 12 - What `use workflow` and `use step` are actually doing
+
+- Workflow replays.
+- Steps do the real work.
+- Event log resolves prior results.
+- This is why the code stays simple.
+
+## Slide 13 - The event log powers both durability and observability
+
+- Observability is not bolted on.
+- Same event log powers replay, recovery, and the audit trail.
+- Inputs and outputs are already there.
+
+## Slide 14 - Streaming is durable too
+
+- New important piece in this version of the talk.
+- Not just live streaming, resumable streaming.
+- Same primitive works for simple apps and for agents.
+
+## Slide 15 - An agent is basically just a workflow
+
+- This is the framing I used in the mock.
+- LLM calls and tool calls fit naturally into the workflow model.
+- DurableAgent is the concrete example.
+
+## Slide 16 - Getting started is intentionally small
+
+- Setup is light.
+- Start with one painful async path.
+- Mention framework breadth and Python at GA.
+
+## Slide 17 - Why GA matters
+
+- Internal usage across Vercel agents.
+- Customer stories: Flora and Durable.
+- This is the proof slide, not the hype slide.
+- Mention 5,000-step runs and serious workloads.
+
+## Slide 18 - Durable systems should be easy to explain from the code itself
+
+- This is the closing thought.
+- Reliability plus clarity.
+- If the team can read it, they can own it.
+
+## Slide 19 - Q&A
+
+- Invite questions on adoption.
+- Invite questions on hooks, streaming, and agents.
+- Seed with “what is a good first workflow candidate?” if needed.
+
+## Optional talking points if you need extra time
+
+- One workflow can map naturally to one Slack thread or one GitHub PR.
+- Timeout pattern: race a hook against sleep.
+- Streams are resumable, which matters for real production UIs.
+- DurableAgent is a clean bridge from workflows into AI agents.