gamma-local-dev-loop
Guides the setup of local development environments including mock servers for testing Gamma API integrations.
Install
mkdir -p .claude/skills/gamma-local-dev-loop && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2737" && unzip -o skill.zip -d .claude/skills/gamma-local-dev-loop && rm skill.zipInstalls to .claude/skills/gamma-local-dev-loop
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Set up local development workflow for Gamma API integration.Key capabilities
- →Set up a local development environment for Gamma API
- →Create a reusable Gamma API client wrapper
- →Implement a poll helper with timeout for API calls
- →Develop a mock server for offline Gamma API development
- →Configure development scripts for Gamma API integration
How it works
This skill sets up an efficient local development workflow for Gamma API integrations by providing a project structure, a reusable client wrapper, a poll helper, and a mock server for offline development.
Inputs & outputs
When to use gamma-local-dev-loop
- →Configuring local development environment
- →Testing API calls locally
- →Building mock responses
- →Optimizing dev integration workflows
About this skill
Gamma Local Dev Loop
Overview
Set up an efficient local development workflow for Gamma API integrations. Since Gamma is a REST API with no SDK, the dev loop centers on HTTP request/response testing, mock servers for offline development, and a reusable client wrapper.
Prerequisites
- Completed
gamma-install-authsetup - Node.js 18+ with
tsxfor TypeScript execution GAMMA_API_KEYin.env
Instructions
Step 1: Project Structure
gamma-integration/
├── src/
│ ├── client.ts # Reusable Gamma API client
│ ├── generate.ts # Generation workflows
│ └── poll.ts # Polling helper
├── test/
│ ├── mock-server.ts # Local mock for offline dev
│ └── integration.test.ts
├── .env # GAMMA_API_KEY (gitignored)
├── .env.example # Template without secrets
├── package.json
└── tsconfig.json
Step 2: Reusable Client Wrapper
// src/client.ts
import "dotenv/config";
const GAMMA_BASE = "https://public-api.gamma.app/v1.0";
export interface GammaClient {
generate(body: GenerateRequest): Promise<GenerateResponse>;
poll(generationId: string): Promise<PollResponse>;
listThemes(): Promise<Theme[]>;
listFolders(): Promise<Folder[]>;
}
export function createClient(apiKey?: string, baseUrl?: string): GammaClient {
const key = apiKey ?? process.env.GAMMA_API_KEY;
if (!key) throw new Error("GAMMA_API_KEY required");
const base = baseUrl ?? GAMMA_BASE;
const headers = { "X-API-KEY": key, "Content-Type": "application/json" };
async function request(method: string, path: string, body?: unknown) {
const res = await fetch(`${base}${path}`, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Gamma ${res.status}: ${text}`);
}
return res.json();
}
return {
generate: (body) => request("POST", "/generations", body),
poll: (id) => request("GET", `/generations/${id}`),
listThemes: () => request("GET", "/themes"),
listFolders: () => request("GET", "/folders"),
};
}
Step 3: Poll Helper with Timeout
// src/poll.ts
import type { GammaClient } from "./client";
export async function waitForCompletion(
client: GammaClient,
generationId: string,
opts = { intervalMs: 5000, timeoutMs: 120000 }
) {
const deadline = Date.now() + opts.timeoutMs;
while (Date.now() < deadline) {
const result = await client.poll(generationId);
if (result.status === "completed") return result;
if (result.status === "failed") throw new Error(`Generation failed: ${result.error}`);
await new Promise((r) => setTimeout(r, opts.intervalMs));
}
throw new Error(`Poll timeout after ${opts.timeoutMs}ms`);
}
Step 4: Mock Server for Offline Dev
// test/mock-server.ts
import http from "node:http";
const MOCK_PORT = 9876;
const generations = new Map<string, { status: string; tick: number }>();
const server = http.createServer((req, res) => {
res.setHeader("Content-Type", "application/json");
// POST /v1.0/generations
if (req.method === "POST" && req.url === "/v1.0/generations") {
const id = `mock_${Date.now()}`;
generations.set(id, { status: "in_progress", tick: 0 });
res.end(JSON.stringify({ generationId: id }));
return;
}
// GET /v1.0/generations/:id — completes after 3 polls
const pollMatch = req.url?.match(/\/v1\.0\/generations\/(.+)/);
if (req.method === "GET" && pollMatch) {
const gen = generations.get(pollMatch[1]);
if (!gen) { res.writeHead(404); res.end("{}"); return; }
gen.tick++;
if (gen.tick >= 3) gen.status = "completed";
res.end(JSON.stringify({
generationId: pollMatch[1],
status: gen.status,
...(gen.status === "completed" && {
gammaUrl: `https://gamma.app/docs/mock-${pollMatch[1]}`,
exportUrl: `https://export.gamma.app/mock.pdf`,
creditsUsed: 10,
}),
}));
return;
}
// GET /v1.0/themes
if (req.url === "/v1.0/themes") {
res.end(JSON.stringify([
{ id: "theme_1", name: "Professional" },
{ id: "theme_2", name: "Modern" },
]));
return;
}
// GET /v1.0/folders
if (req.url === "/v1.0/folders") {
res.end(JSON.stringify([{ id: "folder_1", name: "Test Folder" }]));
return;
}
res.writeHead(404);
res.end("{}");
});
server.listen(MOCK_PORT, () => console.log(`Mock Gamma API on :${MOCK_PORT}`));
Step 5: Development Scripts
{
"scripts": {
"dev:mock": "tsx test/mock-server.ts",
"dev:generate": "tsx src/generate.ts",
"test": "vitest run",
"test:integration": "GAMMA_BASE=http://localhost:9876/v1.0 vitest run test/integration"
}
}
Step 6: Integration Test
// test/integration.test.ts
import { describe, it, expect } from "vitest";
import { createClient } from "../src/client";
import { waitForCompletion } from "../src/poll";
const BASE = process.env.GAMMA_BASE ?? "http://localhost:9876/v1.0";
describe("Gamma API", () => {
const client = createClient("test-key", BASE);
it("generates and polls to completion", async () => {
const { generationId } = await client.generate({
content: "Test presentation",
outputFormat: "presentation",
});
expect(generationId).toBeTruthy();
const result = await waitForCompletion(client, generationId);
expect(result.status).toBe("completed");
expect(result.gammaUrl).toContain("gamma.app");
});
it("lists workspace themes", async () => {
const themes = await client.listThemes();
expect(themes.length).toBeGreaterThan(0);
});
});
Dev Loop Summary
| Activity | Command | Hits Live API? |
|---|---|---|
| Start mock server | npm run dev:mock | No |
| Generate (mock) | GAMMA_BASE=http://localhost:9876/v1.0 npm run dev:generate | No |
| Run tests | npm test (uses mock) | No |
| Live API test | GAMMA_API_KEY=gma_... tsx src/generate.ts | Yes |
Error Handling
| Issue | Cause | Fix |
|---|---|---|
GAMMA_API_KEY required | Missing env var | Add to .env or export |
| Mock returns 404 | Wrong mock port/path | Verify GAMMA_BASE points to mock |
| Poll timeout locally | Mock tick count too high | Reduce tick threshold |
fetch is not defined | Node.js < 18 | Upgrade to Node.js 18+ |
Resources
Next Steps
Proceed to gamma-sdk-patterns for reusable API wrapper patterns.
Prerequisites
Limitations
- →`GAMMA_API_KEY required` if missing env var
- →Mock returns 404 if wrong mock port/path is used
- →`fetch is not defined` if Node.js version is less than 18
How it compares
This skill provides a specific local development loop for Gamma API, including a mock server, unlike general API integration guides.
Compared to similar skills
gamma-local-dev-loop side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| gamma-local-dev-loop (this skill) | 3 | 26d | Caution | Intermediate |
| mcp-builder | 136 | 3mo | Review | Advanced |
| telegram-bot-builder | 106 | 6mo | Review | Intermediate |
| telegram-mini-app | 62 | 6mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
mcp-builder
anthropics
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
telegram-bot-builder
davila7
Expert in building Telegram bots that solve real problems - from simple automation to complex AI-powered bots. Covers bot architecture, the Telegram Bot API, user experience, monetization strategies, and scaling bots to thousands of users. Use when: telegram bot, bot api, telegram automation, chat bot telegram, tg bot.
telegram-mini-app
davila7
Expert in building Telegram Mini Apps (TWA) - web apps that run inside Telegram with native-like experience. Covers the TON ecosystem, Telegram Web App API, payments, user authentication, and building viral mini apps that monetize. Use when: telegram mini app, TWA, telegram web app, TON app, mini app.
stripe-integration
wshobson
Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.
n8n-expression-syntax
czlonkowski
Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node variables, troubleshooting expression errors, or working with webhook data in workflows.
langchain-architecture
wshobson
Design LLM applications using the LangChain framework with agents, memory, and tool integration patterns. Use when building LangChain applications, implementing AI agents, or creating complex LLM workflows.