Anima Performance Tuning
Performance Targets
| Operation |
Target |
Notes |
| Single component generation |
< 10s |
Depends on complexity |
| Batch (10 components) |
< 2 min |
With rate limit delays |
| Cache hit |
< 10ms |
File-based cache |
| Full design system (50 components) |
< 15 min |
Sequential with 6s delays |
Instructions
Step 1: File-Based Generation Cache
// src/performance/cache.ts
import crypto from 'crypto';
import fs from 'fs';
class GenerationCache {
private dir: string;
constructor(cacheDir = '.anima-cache') {
this.dir = cacheDir;
fs.mkdirSync(cacheDir, { recursive: true });
}
private hash(fileKey: string, nodeId: string, settings: any): string {
return crypto.createHash('md5').update(`${fileKey}:${nodeId}:${JSON.stringify(settings)}`).digest('hex');
}
async getOrGenerate(
anima: any,
params: any,
maxAgeMs: number = 3600000, // 1 hour
): Promise<any> {
const key = this.hash(params.fileKey, params.nodesId[0], params.settings);
const path = `${this.dir}/${key}.json`;
if (fs.existsSync(path)) {
const stat = fs.statSync(path);
if (Date.now() - stat.mtimeMs < maxAgeMs) {
return JSON.parse(fs.readFileSync(path, 'utf8'));
}
}
const result = await anima.generateCode(params);
fs.writeFileSync(path, JSON.stringify(result));
return result;
}
clearOlderThan(maxAgeMs: number): number {
let cleared = 0;
for (const file of fs.readdirSync(this.dir)) {
const path = `${this.dir}/${file}`;
if (Date.now() - fs.statSync(path).mtimeMs > maxAgeMs) {
fs.unlinkSync(path);
cleared++;
}
}
return cleared;
}
}
export { GenerationCache };
Step 2: Incremental Generation (Only Changed Components)
// src/performance/incremental.ts
// Only regenerate components whose Figma nodes changed
async function getNodeLastModified(fileKey: string, nodeId: string): Promise<string> {
const res = await fetch(
`https://api.figma.com/v1/files/${fileKey}/nodes?ids=${nodeId}`,
{ headers: { 'X-Figma-Token': process.env.FIGMA_TOKEN! } }
);
const data = await res.json();
return data.lastModified;
}
async function generateOnlyChanged(
anima: any,
fileKey: string,
nodeIds: string[],
lastModifiedCache: Map<string, string>,
): Promise<string[]> {
const changed: string[] = [];
for (const nodeId of nodeIds) {
const lastMod = await getNodeLastModified(fileKey, nodeId);
if (lastMod !== lastModifiedCache.get(nodeId)) {
changed.push(nodeId);
lastModifiedCache.set(nodeId, lastMod);
}
}
console.log(`${changed.length}/${nodeIds.length} components changed — regenerating`);
return changed;
}
Step 3: Output Size Optimization
// src/performance/output-opt.ts
// Post-process generated code for smaller bundle size
function optimizeOutput(content: string): string {
return content
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove block comments
.replace(/^\s*\/\/.*$/gm, '') // Remove line comments
.replace(/\n{3,}/g, '\n\n') // Collapse multiple blank lines
.trim();
}
Output
- File-based generation cache with TTL
- Incremental generation (only changed components)
- Output size optimization via post-processing
Resources
Next Steps
For cost optimization, see anima-cost-tuning.
1---2name: anima-performance-tuning3description: |4 Optimize Anima code generation performance with caching, parallelism, and output tuning.5 Use when reducing generation latency, optimizing batch component generation,6 or improving generated code quality for production use.7 Trigger: "anima performance", "anima slow", "anima optimization", "anima caching".8allowed-tools: Read, Write, Edit, Bash(npm:*)9version: 1.0.010license: MIT11author: Jeremy Longshore <jeremy@intentsolutions.io>12tags: [saas, design, figma, anima, performance]13compatible-with: claude-code14---1516# Anima Performance Tuning1718## Performance Targets1920| Operation | Target | Notes |21|-----------|--------|-------|22| Single component generation | < 10s | Depends on complexity |23| Batch (10 components) | < 2 min | With rate limit delays |24| Cache hit | < 10ms | File-based cache |25| Full design system (50 components) | < 15 min | Sequential with 6s delays |2627## Instructions2829### Step 1: File-Based Generation Cache3031```typescript32// src/performance/cache.ts33import crypto from 'crypto';34import fs from 'fs';3536class GenerationCache {37 private dir: string;3839 constructor(cacheDir = '.anima-cache') {40 this.dir = cacheDir;41 fs.mkdirSync(cacheDir, { recursive: true });42 }4344 private hash(fileKey: string, nodeId: string, settings: any): string {45 return crypto.createHash('md5').update(`${fileKey}:${nodeId}:${JSON.stringify(settings)}`).digest('hex');46 }4748 async getOrGenerate(49 anima: any,50 params: any,51 maxAgeMs: number = 3600000, // 1 hour52 ): Promise<any> {53 const key = this.hash(params.fileKey, params.nodesId[0], params.settings);54 const path = `${this.dir}/${key}.json`;5556 if (fs.existsSync(path)) {57 const stat = fs.statSync(path);58 if (Date.now() - stat.mtimeMs < maxAgeMs) {59 return JSON.parse(fs.readFileSync(path, 'utf8'));60 }61 }6263 const result = await anima.generateCode(params);64 fs.writeFileSync(path, JSON.stringify(result));65 return result;66 }6768 clearOlderThan(maxAgeMs: number): number {69 let cleared = 0;70 for (const file of fs.readdirSync(this.dir)) {71 const path = `${this.dir}/${file}`;72 if (Date.now() - fs.statSync(path).mtimeMs > maxAgeMs) {73 fs.unlinkSync(path);74 cleared++;75 }76 }77 return cleared;78 }79}8081export { GenerationCache };82```8384### Step 2: Incremental Generation (Only Changed Components)8586```typescript87// src/performance/incremental.ts88// Only regenerate components whose Figma nodes changed8990async function getNodeLastModified(fileKey: string, nodeId: string): Promise<string> {91 const res = await fetch(92 `https://api.figma.com/v1/files/${fileKey}/nodes?ids=${nodeId}`,93 { headers: { 'X-Figma-Token': process.env.FIGMA_TOKEN! } }94 );95 const data = await res.json();96 return data.lastModified;97}9899async function generateOnlyChanged(100 anima: any,101 fileKey: string,102 nodeIds: string[],103 lastModifiedCache: Map<string, string>,104): Promise<string[]> {105 const changed: string[] = [];106107 for (const nodeId of nodeIds) {108 const lastMod = await getNodeLastModified(fileKey, nodeId);109 if (lastMod !== lastModifiedCache.get(nodeId)) {110 changed.push(nodeId);111 lastModifiedCache.set(nodeId, lastMod);112 }113 }114115 console.log(`${changed.length}/${nodeIds.length} components changed — regenerating`);116 return changed;117}118```119120### Step 3: Output Size Optimization121122```typescript123// src/performance/output-opt.ts124// Post-process generated code for smaller bundle size125126function optimizeOutput(content: string): string {127 return content128 .replace(/\/\*[\s\S]*?\*\//g, '') // Remove block comments129 .replace(/^\s*\/\/.*$/gm, '') // Remove line comments130 .replace(/\n{3,}/g, '\n\n') // Collapse multiple blank lines131 .trim();132}133```134135## Output136137- File-based generation cache with TTL138- Incremental generation (only changed components)139- Output size optimization via post-processing140141## Resources142143- [Anima API](https://docs.animaapp.com/docs/anima-api)144- [Figma API Nodes](https://www.figma.com/developers/api#get-file-nodes-endpoint)145146## Next Steps147148For cost optimization, see `anima-cost-tuning`.149