gamma-migration-deep-dive
Deep dive into migrating to Gamma from other presentation platforms. Use when migrating from PowerPoint, Google Slides, Canva, or other presentation tools to Gamma. Trigger with phrases like "gamma migration", "migrate to gamma", "gamma import", "gamma from powerpoint", "gamma from google slides".
What this skill does
# Gamma Migration Deep Dive
## Current State
!`npm list 2>/dev/null | head -10`
## Overview
Migrate presentation workflows from PowerPoint, Google Slides, Canva, or other platforms to Gamma's AI-powered generation. Gamma takes a fundamentally different approach -- instead of manually placing slides, you provide content and Gamma generates the presentation. Migration is about converting your content pipeline, not your slide files.
## Prerequisites
- Gamma API access (Pro+ plan)
- Source presentations accessible for content extraction
- Node.js 18+ for migration scripts
- Completed `gamma-install-auth` setup
## Migration Approaches
| Approach | When to Use | Effort |
|----------|-------------|--------|
| Content extraction + regeneration | Lots of text-heavy presentations | Medium |
| Import via Gamma UI | One-off migration of key decks | Low |
| Template recreation | Repeatable presentation formats | Medium |
| Parallel operation | Gradual transition over time | Low |
**Key insight:** You don't "import" slides into Gamma. You extract content from old presentations and regenerate them using Gamma's AI. This often produces better results than the originals.
## Instructions
### Step 1: Inventory Source Presentations
```typescript
// scripts/inventory-presentations.ts
import { readdir, stat } from "node:fs/promises";
import { join, extname } from "node:path";
interface PresentationInfo {
path: string;
format: string;
sizeMB: number;
lastModified: Date;
}
async function inventoryPresentations(dir: string): Promise<PresentationInfo[]> {
const entries = await readdir(dir, { recursive: true });
const presentations: PresentationInfo[] = [];
for (const entry of entries) {
const ext = extname(entry).toLowerCase();
if ([".pptx", ".ppt", ".key", ".pdf", ".md"].includes(ext)) {
const fullPath = join(dir, entry);
const info = await stat(fullPath);
presentations.push({
path: fullPath,
format: ext,
sizeMB: info.size / (1024 * 1024),
lastModified: info.mtime,
});
}
}
console.log(`Found ${presentations.length} presentations:`);
const byFormat = presentations.reduce((acc, p) => {
acc[p.format] = (acc[p.format] || 0) + 1;
return acc;
}, {} as Record<string, number>);
console.log("By format:", byFormat);
return presentations;
}
```
### Step 2: Extract Content from PowerPoint
```typescript
// scripts/extract-pptx.ts
// Use 'pptx-parser' or 'officegen' to extract text content
import JSZip from "jszip";
import { readFile } from "node:fs/promises";
import { DOMParser } from "xmldom";
async function extractPptxContent(pptxPath: string): Promise<string[]> {
const buffer = await readFile(pptxPath);
const zip = await JSZip.loadAsync(buffer);
const slides: string[] = [];
const slideFiles = Object.keys(zip.files)
.filter((f) => f.match(/ppt\/slides\/slide\d+\.xml$/))
.sort();
for (const slideFile of slideFiles) {
const xml = await zip.file(slideFile)!.async("string");
const doc = new DOMParser().parseFromString(xml);
// Extract all text elements
const textNodes = doc.getElementsByTagName("a:t");
const texts: string[] = [];
for (let i = 0; i < textNodes.length; i++) {
const text = textNodes[i].textContent?.trim();
if (text) texts.push(text);
}
slides.push(texts.join("\n"));
}
return slides;
}
// Convert extracted content to Gamma prompt
function slidesToGammaPrompt(slides: string[], title: string): string {
let prompt = `${title}\n\n`;
slides.forEach((content, i) => {
prompt += `Slide ${i + 1}:\n${content}\n\n`;
});
return prompt;
}
```
### Step 3: Batch Migration Script
```typescript
// scripts/migrate-to-gamma.ts
import { createGammaClient } from "../src/client";
import { pollUntilDone } from "../src/poll";
import pLimit from "p-limit";
const gamma = createGammaClient({ apiKey: process.env.GAMMA_API_KEY! });
const limit = pLimit(2); // Max 2 concurrent generations
interface MigrationItem {
title: string;
content: string;
sourceFile: string;
}
async function migrateBatch(items: MigrationItem[]) {
const results = await Promise.allSettled(
items.map((item) =>
limit(async () => {
console.log(`Migrating: ${item.title}`);
const { generationId } = await gamma.generate({
content: item.content,
outputFormat: "presentation",
textMode: "condense", // AI condenses extracted text
exportAs: "pptx", // Get PPTX for comparison
});
const result = await pollUntilDone(gamma, generationId);
return {
title: item.title,
sourceFile: item.sourceFile,
gammaUrl: result.gammaUrl,
exportUrl: result.exportUrl,
creditsUsed: result.creditsUsed,
};
})
)
);
// Report
const succeeded = results.filter((r) => r.status === "fulfilled");
const failed = results.filter((r) => r.status === "rejected");
console.log(`\nMigration complete: ${succeeded.length} succeeded, ${failed.length} failed`);
for (const r of results) {
if (r.status === "fulfilled") {
console.log(` OK: ${r.value.title} → ${r.value.gammaUrl}`);
} else {
console.log(` FAIL: ${r.reason}`);
}
}
}
```
### Step 4: Template Recreation
For recurring presentation types (weekly reports, proposals, etc.), create Gamma templates:
```text
Migration steps for templates:
1. Identify repeating presentation formats in your org
2. Create a one-page template gamma in the Gamma app:
- gamma.app → Create → design a single representative page
3. Note the template gamma ID from the URL
4. Use POST /v1.0/generations/from-template with the gammaId
5. Update your automation scripts to use generateFromTemplate()
```
```typescript
// After template creation in Gamma UI
const MIGRATED_TEMPLATES: Record<string, string> = {
"weekly-report": "gamma_template_weekly_abc123",
"sales-proposal": "gamma_template_proposal_def456",
"team-update": "gamma_template_update_ghi789",
};
async function generateFromMigratedTemplate(
templateKey: string,
content: string
) {
const gammaId = MIGRATED_TEMPLATES[templateKey];
if (!gammaId) throw new Error(`Unknown template: ${templateKey}`);
const { generationId } = await gamma.generateFromTemplate({
gammaId,
prompt: content,
exportAs: "pdf",
});
return pollUntilDone(gamma, generationId);
}
```
### Step 5: Validation Checklist
After migrating each presentation:
```text
- [ ] Content accuracy: AI-generated text matches source intent
- [ ] Slide count: reasonable for the content volume
- [ ] Theme/branding: workspace theme applied correctly
- [ ] Export quality: PDF/PPTX downloads successfully
- [ ] Links preserved: any URLs from original are in the content
- [ ] Stakeholder review: key presentations reviewed by owners
```
## Supported Migration Paths
| Source | Method | Fidelity | Notes |
|--------|--------|----------|-------|
| PowerPoint (.pptx) | Extract text → regenerate | Content-high, design-new | AI redesigns slides |
| Google Slides | Export as .pptx → extract | Content-high, design-new | Export first |
| Canva | Export as .pdf → extract text | Medium | Limited text extraction |
| Keynote (.key) | Export as .pptx → extract | Content-high, design-new | Export first |
| Markdown (.md) | Direct use as content | High | Best migration path |
| Notion pages | Export as .md → use directly | High | Clean text extraction |
## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| Content too long | Exceeds 100K token limit | Split into multiple presentations |
| Credit budget exceeded | Too many migrations at once | Batch over multiple days |
| Poor output quality | Content too unstructured | Add structure (headings, bullets) to extracted content |
| Missing images | Images in source not extracted | Gamma generates new images; reference image concepts in text |
## Resources
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.