ideogram-data-handling
Implement robust image handling and metadata persistence for Ideogram outputs.
Install
mkdir -p .claude/skills/ideogram-data-handling && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/8260" && unzip -o skill.zip -d .claude/skills/ideogram-data-handling && rm skill.zipInstalls to .claude/skills/ideogram-data-handling
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.
Manage Ideogram generated image assets, metadata tracking, and lifecycleKey capabilities
- →Download and persist generated images before URL expiration
- →Track generation metadata including prompts and seeds
- →Manage local and S3 storage lifecycles
- →Reproduce images using stored seed values
- →Generate storage reports by model type
How it works
The skill wraps the Ideogram API to immediately download generated images to persistent storage and record metadata in a JSON file or database. It provides functions to reproduce images using the original seed and manage asset cleanup.
Inputs & outputs
When to use ideogram-data-handling
- →Implementing image storage pipelines
- →Tracking generation metadata and history
- →Managing temporary vs persistent asset storage
- →Ensuring data retention compliance
About this skill
Ideogram Data Handling
Overview
Manage generated image assets from Ideogram's API. Critical concern: Ideogram image URLs expire (approximately 1 hour). Every generation must be downloaded and persisted immediately. This skill covers metadata tracking, download pipelines, local and cloud storage, lifecycle management, and generation history for reproducibility.
Prerequisites
IDEOGRAM_API_KEYconfigured- Storage solution (local filesystem, S3, or GCS)
- Database for generation metadata (SQLite, Postgres, or JSON files)
Instructions
Step 1: Generation Record Schema
interface GenerationRecord {
id: string; // Unique identifier
prompt: string; // Original prompt
expandedPrompt?: string; // Magic Prompt expansion (from response)
negativePrompt?: string; // Negative prompt used
model: string; // V_2, V_2_TURBO, etc.
styleType: string; // DESIGN, REALISTIC, etc.
aspectRatio: string; // ASPECT_16_9, etc.
seed: number; // For reproducibility
resolution: string; // e.g., "1024x1024"
isSafe: boolean; // is_image_safe from response
originalUrl: string; // Temporary Ideogram URL
storedPath: string; // Local or S3 path
createdAt: string; // ISO timestamp
sizeBytes?: number; // Downloaded file size
tags?: string[]; // User-defined tags
}
Step 2: Generate, Download, and Track
import { writeFileSync, mkdirSync, statSync } from "fs";
import { join } from "path";
import { randomUUID } from "crypto";
const STORAGE_DIR = "./generated-images";
const records: GenerationRecord[] = [];
async function generateAndPersist(
prompt: string,
options: {
model?: string;
style_type?: string;
aspect_ratio?: string;
negative_prompt?: string;
seed?: number;
tags?: string[];
} = {}
): Promise<GenerationRecord> {
// Generate
const response = await fetch("https://api.ideogram.ai/generate", {
method: "POST",
headers: {
"Api-Key": process.env.IDEOGRAM_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_request: {
prompt,
model: options.model ?? "V_2",
style_type: options.style_type ?? "AUTO",
aspect_ratio: options.aspect_ratio ?? "ASPECT_1_1",
magic_prompt_option: "AUTO",
negative_prompt: options.negative_prompt,
seed: options.seed,
},
}),
});
if (!response.ok) throw new Error(`Generation failed: ${response.status}`);
const result = await response.json();
const image = result.data[0];
// Download IMMEDIATELY (URLs expire ~1 hour)
const imgResp = await fetch(image.url);
if (!imgResp.ok) throw new Error(`Download failed: ${imgResp.status}`);
const buffer = Buffer.from(await imgResp.arrayBuffer());
mkdirSync(STORAGE_DIR, { recursive: true });
const filename = `${image.seed}-${Date.now()}.png`;
const storedPath = join(STORAGE_DIR, filename);
writeFileSync(storedPath, buffer);
// Track metadata
const record: GenerationRecord = {
id: randomUUID(),
prompt,
expandedPrompt: image.prompt !== prompt ? image.prompt : undefined,
negativePrompt: options.negative_prompt,
model: options.model ?? "V_2",
styleType: image.style_type ?? options.style_type ?? "AUTO",
aspectRatio: options.aspect_ratio ?? "ASPECT_1_1",
seed: image.seed,
resolution: image.resolution,
isSafe: image.is_image_safe,
originalUrl: image.url,
storedPath,
createdAt: new Date().toISOString(),
sizeBytes: buffer.length,
tags: options.tags,
};
records.push(record);
saveRecords();
return record;
}
function saveRecords() {
writeFileSync(
join(STORAGE_DIR, "generations.json"),
JSON.stringify(records, null, 2)
);
}
Step 3: Cloud Storage (S3)
import { S3Client, PutObjectCommand, DeleteObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({ region: process.env.AWS_REGION });
async function persistToS3(imageUrl: string, seed: number): Promise<string> {
const response = await fetch(imageUrl);
const buffer = Buffer.from(await response.arrayBuffer());
const key = `ideogram/${seed}-${Date.now()}.png`;
await s3.send(new PutObjectCommand({
Bucket: process.env.S3_BUCKET!,
Key: key,
Body: buffer,
ContentType: "image/png",
CacheControl: "public, max-age=31536000, immutable",
Metadata: { seed: String(seed), source: "ideogram" },
}));
return `https://${process.env.CDN_DOMAIN}/${key}`;
}
Step 4: Reproduction from Seed
// Reproduce an image using the stored seed and prompt
async function reproduceImage(record: GenerationRecord) {
return generateAndPersist(record.prompt, {
model: record.model,
style_type: record.styleType,
aspect_ratio: record.aspectRatio,
negative_prompt: record.negativePrompt,
seed: record.seed, // Same seed = same image
tags: [...(record.tags ?? []), "reproduced"],
});
}
Step 5: Lifecycle Management
import { unlinkSync, existsSync, readdirSync, statSync } from "fs";
function cleanupOldAssets(retentionDays: number = 30) {
const cutoffMs = Date.now() - retentionDays * 86400000;
let deleted = 0;
let kept = 0;
for (const record of records) {
const createdMs = new Date(record.createdAt).getTime();
if (createdMs < cutoffMs) {
if (existsSync(record.storedPath)) {
unlinkSync(record.storedPath);
deleted++;
}
} else {
kept++;
}
}
// Remove expired records
const activeRecords = records.filter(
r => new Date(r.createdAt).getTime() >= cutoffMs
);
records.length = 0;
records.push(...activeRecords);
saveRecords();
console.log(`Cleanup: deleted ${deleted}, kept ${kept}`);
}
function storageReport() {
const totalBytes = records.reduce((sum, r) => sum + (r.sizeBytes ?? 0), 0);
const byModel = Object.groupBy(records, r => r.model);
console.log("=== Image Storage Report ===");
console.log(`Total images: ${records.length}`);
console.log(`Total size: ${(totalBytes / 1024 / 1024).toFixed(1)} MB`);
for (const [model, recs] of Object.entries(byModel)) {
console.log(` ${model}: ${recs?.length ?? 0} images`);
}
}
Step 6: Search and Query
function findByPrompt(searchTerm: string): GenerationRecord[] {
return records.filter(r =>
r.prompt.toLowerCase().includes(searchTerm.toLowerCase())
);
}
function findBySeed(seed: number): GenerationRecord | undefined {
return records.find(r => r.seed === seed);
}
function findByTags(tags: string[]): GenerationRecord[] {
return records.filter(r =>
tags.every(t => r.tags?.includes(t))
);
}
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Expired URL | Downloaded too late | Always download in same function |
| Disk full | Too many stored images | Run cleanupOldAssets() regularly |
| Missing metadata | Not tracked at generation | Use generateAndPersist wrapper |
| Duplicate prompts | Same prompt run twice | Check by prompt hash before generating |
| Lost seed | Not recorded | Always store seed from response |
Output
- Generation records with full metadata tracking
- Immediate download preventing URL expiration
- S3 cloud storage with CDN delivery
- Seed-based reproduction for exact image regeneration
- Lifecycle management with configurable retention
Resources
Next Steps
For access control, see ideogram-enterprise-rbac.
When not to use it
- →When relying on temporary Ideogram URLs for long-term access
- →When storage infrastructure is not configured
Prerequisites
Limitations
- →Ideogram image URLs expire after approximately 1 hour
- →Requires manual cleanup of old assets to prevent disk exhaustion
How it compares
Unlike a direct API call that leaves images at ephemeral URLs, this workflow ensures assets are saved locally or to cloud storage with full metadata tracking.
Compared to similar skills
ideogram-data-handling side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| ideogram-data-handling (this skill) | 0 | 27d | Caution | Intermediate |
| drizzle-orm | 32 | 2mo | No flags | Intermediate |
| sql-queries | 18 | 5mo | No flags | Intermediate |
| event-store-design | 5 | 2mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
drizzle-orm
EpicenterHQ
Drizzle ORM patterns for type branding and custom types. Use when working with Drizzle column definitions, branded types, or custom type conversions.
sql-queries
anthropics
Write correct, performant SQL across all major data warehouse dialects (Snowflake, BigQuery, Databricks, PostgreSQL, etc.). Use when writing queries, optimizing slow SQL, translating between dialects, or building complex analytical queries with CTEs, window functions, or aggregations.
event-store-design
wshobson
Design and implement event stores for event-sourced systems. Use when building event sourcing infrastructure, choosing event store technologies, or implementing event persistence patterns.
springboot-patterns
affaan-m
Spring Boot 架构模式、REST API 设计、分层服务、数据访问、缓存、异步处理和日志记录。适用于 Java Spring Boot 后端工作。
dotnet-architect
sickn33
Expert .NET backend architect specializing in C#, ASP.NET Core, Entity Framework, Dapper, and enterprise application patterns. Masters async/await, dependency injection, caching strategies, and performance optimization. Use PROACTIVELY for .NET API development, code review, or architecture decisions.
backend-development
skillcreatorai
Backend API design, database architecture, microservices patterns, and test-driven development. Use for designing APIs, database schemas, or backend system architecture.