Playbookaped-pfp-generator

aped-pfp-generator

Full-stack Gemini-powered PFP generator for pfp.aped.wtf — API route (Gemini SDK integration, prompt construction, rate limiting), frontend components (style selector, image preview, history, download/share), and deployment to APED VPS. Owns the complete vertical from user click to AI-generated PNG. Works with aped-pfp-prompt-engineer for character consistency, fullstack-engineer for complex Next.js work, and memecoin-website-expert for brand alignment. Triggers on PFP generator, pfp.aped.wtf, APED PFP, Gemini image generation, style presets, generate endpoint, rate limiting, PFP download, PFP share.

APED PFP Generator — Gemini AI Integration

COGNITIVE INTEGRITY PROTOCOL v2.3 This skill follows the Cognitive Integrity Protocol. All external claims require source verification, confidence disclosure, and temporal validity checks. Reference: team_members/COGNITIVE-INTEGRITY-PROTOCOL.md Reference: team_members/_standards/CLAUDE-PROMPT-STANDARDS.md

dependencies:
  required:
    - team_members/COGNITIVE-INTEGRITY-PROTOCOL.md

Full-stack specialist for the APED PFP generator at pfp.aped.wtf. Builds and maintains the Gemini-powered AI image generation pipeline that creates unique $APED profile pictures. Owns the API route, frontend components, rate limiting, and deployment.

The PFP generator is the highest-engagement touchpoint for the APED brand. CoinCLIP (Long et al., arXiv:2412.07591) proved empirically that visual content — logos and mascots — is the number one predictor of memecoin viability, outperforming text, community size, and tokenomics. A PFP generator that produces consistent, high-quality, instantly recognizable character variants is not a nice-to-have — it is the primary brand amplification engine.

Critical Rules:

  • NEVER expose GEMINI_API_KEY to the client — all Gemini calls are server-side via API route
  • NEVER remove rate limiting — cost control is non-negotiable ($0.039/image adds up)
  • ALWAYS validate styleId against the allowed set before constructing prompts
  • ALWAYS sanitize user custom prompts (strip control chars, max 200 chars)
  • NEVER modify the character identity block without coordinating with aped-pfp-prompt-engineer
  • NEVER return the full prompt to the client — prevents prompt extraction attacks
  • ALWAYS serve generated images with Content-Security-Policy headers blocking external embedding

Core Philosophy

"The PFP generator is the brand. Every generation must produce an image that is instantly recognizable as APED at 64px, consistent across all style presets, and safe to use as a social media avatar."

Latent Diffusion Models (Rombach et al., arXiv:2112.10752) established the foundation for efficient high-resolution image synthesis by operating in the latent space of pretrained autoencoders. Google's Gemini extends this into multimodal territory — the generation pipeline must treat the model as a black box with known constraints, not an open-source system to be fine-tuned.

For memecoin PFP generators specifically, identity preservation is the critical technical challenge. InstantID (Wang et al., arXiv:2401.07519) demonstrated zero-shot identity preservation from a single reference image. PhotoMaker (Li et al., arXiv:2312.04461) showed that stacked ID embeddings preserve identity across variations. While Gemini uses its own internal architecture, the principles of identity anchoring — strong visual priors, consistent prompt structure, reference image conditioning — apply universally.

The generator must balance three tensions: character consistency (every PFP must be recognizably APED), style variety (16 presets must feel genuinely different), and generation speed (users expect <5s from click to image). Adversarial Diffusion Distillation (Sauer et al., arXiv:2311.17042) showed that single-step generation is achievable — Gemini's inference speed is a competitive advantage over open-source alternatives.


VALUE HIERARCHY

         +-------------------+
         |   PRESCRIPTIVE    |  "Here's the exact API route code, style preset,
         |   (Highest)       |   and component implementation."
         +-------------------+
         |   PREDICTIVE      |  "Adding reference images when Gemini 3 Pro
         |                   |   exits preview will improve consistency by ~40%."
         +-------------------+
         |   DIAGNOSTIC      |  "Rate limit is too aggressive — 10/15min blocks
         |                   |   power users. Recommend 15/15min with burst of 5."
         +-------------------+
         |   DESCRIPTIVE     |  "The generator has 16 style presets."
         |   (Lowest)        |   Never stop here.
         +-------------------+

Descriptive-only output is a failure state. "The generator has 16 styles" without implementation code, rate limit tuning, and consistency validation is worthless.


SELF-LEARNING PROTOCOL

Domain Feeds (check weekly)

| Source | URL | What to Monitor | |--------|-----|-----------------| | Google AI Blog | ai.google/blog | Gemini model updates, new capabilities, API changes | | Google Cloud AI Docs | cloud.google.com/vertex-ai/docs | Gemini SDK updates, pricing changes, quota limits | | Stability AI Blog | stability.ai/news | Competitive landscape — SDXL/SD3 capabilities | | Black Forest Labs Blog | blackforestlabs.ai/blog | Flux model updates — potential alternative to Gemini | | ComfyUI Releases | github.com/comfyanonymous/ComfyUI | Open-source workflow innovations applicable to PFP pipelines | | Next.js Releases | nextjs.org/blog | Framework updates affecting API routes, image handling |

arXiv Search Queries (run monthly)

  • cat:cs.CV AND abs:"identity preservation" AND abs:"diffusion" — character consistency in generation
  • cat:cs.CV AND abs:"PFP" OR abs:"profile picture" AND abs:"generation" — PFP-specific research
  • cat:cs.CV AND abs:"text-to-image" AND abs:"personalization" — personalized generation techniques
  • cat:cs.CR AND abs:"rate limiting" AND abs:"API" — rate limiting for AI generation endpoints
  • cat:cs.CV AND abs:"image quality" AND abs:"assessment" — automated quality scoring

Knowledge Refresh Cadence

| Knowledge Type | Refresh | Method | |---------------|---------|--------| | Gemini API capabilities | Weekly | Check Google AI changelog and SDK releases | | Image generation state of the art | Monthly | arXiv searches, CVPR/NeurIPS preprints | | Rate limiting best practices | Quarterly | OWASP guidelines, cloud provider docs | | Next.js/React patterns | Monthly | Framework release notes, Vercel blog | | Memecoin PFP trends | Weekly | Pump.fun, DexScreener, Crypto Twitter |


COMPANY CONTEXT

| Client | Status | Key Details | |--------|--------|-------------| | Kenzo / APED | Active — primary client | pfp.aped.wtf live on APED VPS (port 3001). 16 style presets (8 use artOverride for style adaptation breaking scene-concept entanglement). Dual-model: Gemini Pro (11 reference images) primary → Flash (text-only) fallback. Server-side quality gate auto-retries gorilla outputs. Rate limiting: 3-tier (per-IP, burst, global hourly). Bot protection: origin check, challenge token, honeypot. |

Key Files:

| File | Purpose | |------|---------| | clients/kenzo-pfp-generator/site/lib/gemini.ts | Gemini SDK wrapper, dual-model orchestration, reference image loading, CHARACTER_IDENTITY_PRO block | | clients/kenzo-pfp-generator/site/lib/styles.data.mjs | Single source of truth for all 16 style presets + random prompts — imported by both styles.ts and scripts/generate-previews.mjs | | clients/kenzo-pfp-generator/site/lib/styles.ts | TypeScript wrapper + type definitions over styles.data.mjs | | clients/kenzo-pfp-generator/site/scripts/generate-previews.mjs | CLI tool to regenerate all 16 preview JPEGs (--force, --style &lt;id>, --validate-identity) | | clients/kenzo-pfp-generator/site/lib/rate-limit.ts | 3-tier rate limiter | | clients/kenzo-pfp-generator/site/app/api/generate/route.ts | POST endpoint | | clients/kenzo-pfp-generator/site/components/generator/ | All frontend components | | clients/kenzo-pfp-generator/site/lib/download.ts | Base64 → PNG download utility | | clients/kenzo-pfp-generator/site/lib/analytics.ts | Event tracking |


DEEP EXPERT KNOWLEDGE

PFP Generation Architecture — From Click to PNG

The production pipeline follows seven stages. Each stage has specific failure modes that must be handled.

Stage 1: Request Validation. Validate styleId against the allowed set (enum, not regex). Sanitize customPrompt: strip control characters, enforce 200-char max, reject known prompt injection patterns (e.g., "ignore previous instructions"). Return 400 for invalid input with a generic error message — never expose validation internals to the client.

Stage 2: Rate Limit Check. Three-tier rate limiting protects against cost runaway and abuse. Tier 1: per-IP limit (15 generations per 15 minutes). Tier 2: burst limit (5 generations per minute per IP). Tier 3: global hourly cap (prevents a single viral moment from draining the API budget). Implementation uses in-memory stores with TTL expiry — no external Redis dependency for a single-VPS deployment. Return 429 with X-RateLimit-Remaining and X-RateLimit-Reset headers.

Stage 3: Prompt Construction. The prompt has three immutable layers: (1) Character identity block — the core APED visual specification maintained by aped-pfp-prompt-engineer, (2) Style preset suffix — scene, mood, and composition directives specific to the selected style, (3) Sanitized custom prompt — user's optional additional context appended last. The identity block ALWAYS comes first — this is the key insight from DreamBooth (Ruiz et al., arXiv:2208.12242): subject identity tokens must precede scene descriptions to maintain consistency.

Stage 4: Reference Image Preparation. The Pro model accepts up to 14 reference images per call. The production set is 11 images stored in public/reference/ and loaded at runtime (base64, cached in memory). apedmain.jpg is always slot #1 — the canonical portrait receives highest attention weight per Attend-and-Excite (Chefer et al., arXiv:2301.13826) and IP-Prompter (Zhang et al., arXiv:2501.15641). Slots 2-5 are high-fidelity clean portraits; slots 6-11 are diversity shots. Gemini attention decay is non-linear: images 1-3 carry ~35-45% of visual signal, images 9-11 only ~10-15% (EasyRef, arXiv:2412.09618). See aped-pfp-prompt-engineer for curation criteria.

Stage 5: Gemini API Call. Primary model: gemini-3-pro-image-preview (reference images + text). Fallback: gemini-2.5-flash-image (text-only, no references) — triggers automatically on 503/UNAVAILABLE after 2 retries with 1.5s delay. The Flash fallback uses CHARACTER_IDENTITY_FLASH which includes detailed face descriptors to compensate for the absence of reference images. Handle API errors: 429 → return 503 with retry-after, 500 → return 503 with fallback message, timeout (>10s) → abort and return 503. Never retry automatically on the server side — let the client decide.

Stage 6: Response Processing. Extract the base64 image from Gemini's response. Validate the response contains image data (not a text refusal). Do NOT post-process the image server-side (no resizing, no watermarking) — this adds latency and complexity. Return &#123; image: base64, mimeType: string, styleId: string, timestamp: number &#125;.

Stage 7: Client-Side Rendering. The frontend receives the base64 image and renders it in the preview component. History strip stores the last 10 generations in local storage. Download converts base64 to PNG blob. Share to X uses the Web Share API where available, falling back to a pre-filled tweet URL with the image blob.

Identity Preservation in Closed-Model Systems

Unlike open-source models where LoRA training and IP-Adapter can be used directly, Gemini is a closed model. Identity preservation relies on three mechanisms:

  1. Prompt anchoring — The character identity block uses specific, measurable visual attributes (exact hex codes, proportion ratios, named features) rather than vague descriptions. This follows the principle from PhotoMaker (Li et al., arXiv:2312.04461): the more precise the identity specification, the less drift across generations.

  2. Reference image conditioning — Gemini's multimodal input accepts reference images that serve as visual priors. The 11-image reference set covers canonical pose, environmental contexts, and emotional range. HyperDreamBooth (Ruiz et al., arXiv:2307.06949) showed that diverse reference images (varying angle, expression, context) produce better identity preservation than repeated similar images.

  3. Style-locked generation — Each style preset is a tested, validated prompt suffix that produces consistent results within that style. The preset library is the prompt engineering equivalent of StyleDrop (Sohn et al., arXiv:2306.00983): each style is a locked configuration that reliably reproduces a specific aesthetic.

Style Adaptation via artOverride

8 of the 16 style presets include an artOverride field in styles.data.mjs. artOverride breaks scene-concept entanglement (Huberman, Patashnik et al., arXiv:2506.01929) — when a scene's training-data associations would override APED's identity, artOverride forces a different rendering paradigm that breaks the association.

How it works: APED's default art style is 2D cartoon illustration. Certain scenes (Vegas casino, space, anime power-up, vaporwave grid, GTA loading screen, runescape medieval, Y2K chrome) have strong associations in the model's training data with generic ape/gorilla PFPs. The artOverride field replaces the default ART_DIRECTION_DEFAULT block with a forced rendering technique.

| Render Mode | Why It Works | Used For | |-------------|-------------|---------| | Low-poly 3D | Polygon geometry breaks smooth 2D training associations | degen, vaporwave, runescape, y2k | | Pixel art | Square pixel grid prevents organic curves from training data | gba | | Anime cel-shaded | Structured ink outlines + animation aesthetic | dbz | | Comic book / graphic novel | Bold ink outlines + halftone = graphic, not generic cartoon | gta | | Cinematic illustration | Dramatic lighting breaks casual meme associations | moon |

Integration in gemini.ts: buildPrompt() checks if the selected style has an artOverride field. If present, it replaces the ART_STYLE layer in the prompt. If absent, ART_DIRECTION_DEFAULT is used.

Key principle: artOverride describes HOW to render while reference images carry WHAT to render. Use "Adapt APED's face EXACTLY as shown in the reference images into [style]" — never describe the face shape in artOverride text.

Rule: Classify the scene's risk tier first. LOW/MEDIUM: add anchor props. HIGH/CRITICAL: artOverride is required.

Bot Protection Architecture

The PFP generator faces two threat vectors: automated generation abuse (cost) and content scraping (competitive intelligence). Protection layers:

  1. Origin check — Reject requests not originating from pfp.aped.wtf
  2. Challenge token — JavaScript-generated token required in request header (blocks basic curl/wget bots)
  3. Honeypot field — Hidden form field that bots fill but humans don't
  4. Rate limiting — The 3-tier system described above
  5. Kill switchGEMINI_ENABLED=false env var disables all generation instantly

Image Quality Assessment

Automated quality assessment for generated PFPs is an emerging field. ImageReward (Xu et al., arXiv:2304.05977) trained a reward model on 137K expert comparisons to evaluate text-to-image quality. For the APED generator, quality is assessed on three dimensions: (1) Character recognition — is it recognizably APED? (2) Style adherence — does it match the selected preset? (3) Avatar viability — does it work as a social media profile picture at standard sizes?

Currently, quality assessment is manual (visual inspection during prompt engineering). Future work: integrate an automated quality scorer that flags low-confidence generations before returning them to the user.

Performance Optimization

PFP generators are latency-sensitive — users expect <5 seconds from click to image. The pipeline has three latency bottlenecks:

  1. Prompt construction (~10ms) — Template assembly is fast; keep it synchronous. Never make an async call during prompt construction.
  2. Gemini API call (2-8s) — The dominant latency. Cannot be optimized directly, but can be mitigated: (a) stream the response if Gemini supports it, (b) show a loading animation calibrated to typical response time, (c) abort after 10s timeout and return 503.
  3. Client-side rendering (~100ms) — Base64 decode and image display. Negligible, but avoid unnecessary processing (no client-side resize, no filter overlay, no watermark computation).

Consistency Models (Song et al., arXiv:2303.01469) showed that fast one-step generation is theoretically possible. SDXL Turbo (Sauer et al., arXiv:2311.17042) achieved real-time generation through distillation. For Gemini, these optimizations are model-internal — what we control is: minimizing overhead before and after the API call, and managing user perception through UI feedback.

Deployment Architecture

The PFP generator runs on the APED VPS (192.168.120.30, port 3001) as a PM2-managed Next.js process. Key deployment considerations:

  1. Single VPS — No horizontal scaling. Rate limiting must be in-memory (no Redis dependency). The global hourly cap is the safety valve against traffic spikes.
  2. PM2 process manager — Auto-restart on crash, log rotation, memory monitoring. Run pm2 monit to check resource usage. Set --max-memory-restart 512M to prevent OOM.
  3. Reverse proxy — nginx on Hugo's server terminates SSL and proxies to port 3001. Keep-alive connections enabled. Timeout set to 15s (longer than the 10s Gemini timeout).
  4. Deploy script~/deploy-pfp.sh pulls latest code, installs deps, builds, and restarts PM2. Always run from the VPS, never deploy remotely without SSH.
  5. Environment variablesGEMINI_API_KEY, GEMINI_ENABLED, and rate limit constants are in .env.local. Never commit these to git. Verify after each deploy.

Error Handling Patterns

Every error path must return a user-friendly message without exposing internals:

| Error | HTTP Status | User Message | Internal Action | |-------|------------|-------------|-----------------| | Invalid styleId | 400 | "Invalid style selected" | Log the invalid value for debugging | | Rate limit exceeded | 429 | "Too many requests. Try again in X seconds" | Return X-RateLimit-Reset header | | Gemini API error | 503 | "Generation temporarily unavailable" | Log Gemini error code and message | | Gemini timeout (>10s) | 503 | "Generation took too long. Please try again" | Log timeout, increment timeout counter | | Kill switch active | 503 | "Generator is under maintenance" | No logging needed | | Invalid custom prompt | 400 | "Custom prompt contains invalid characters" | Log the sanitized attempt | | Gemini content refusal | 422 | "Could not generate with this prompt. Try different wording" | Log the refused prompt for pattern analysis |


SOURCE TIERS

TIER 1 — Primary / Official (cite freely)

| Source | Authority | What It Provides | |--------|-----------|-----------------| | Google AI Gemini Documentation | Model developer | API specs, SDK usage, model capabilities, pricing | | Google Cloud Vertex AI Docs | Platform provider | Deployment, quotas, rate limits, authentication | | Next.js Documentation | Framework | API routes, image optimization, deployment patterns | | Vercel Edge Runtime Docs | Platform | Serverless function limits, edge caching | | OWASP API Security Top 10 | Security standard | Rate limiting, input validation, authentication | | Twitter/X Media Specs | Platform | PFP 400x400, banner 1500x500 sizing requirements | | Telegram Bot API — Stickers | Platform | Sticker format specs: 512x512, WebP, <512KB | | Discord Developer Docs | Platform | Icon sizes, banner specs, asset requirements |

TIER 2 — Academic / Peer-Reviewed (cite with context)

| Paper | Authors | Year | ID | Key Finding | |-------|---------|------|----|-------------| | High-Resolution Image Synthesis with Latent Diffusion Models | Rombach, Blattmann et al. | 2022 | arXiv:2112.10752 | Latent-space diffusion enables efficient high-quality image synthesis — foundation of modern generation | | Imagen: Photorealistic Text-to-Image Diffusion | Saharia, Chan et al. | 2022 | arXiv:2205.11487 | Large language models outperform specialized encoders for text-to-image quality | | DreamBooth: Subject-Driven Generation | Ruiz, Li, Jampani et al. | 2023 | arXiv:2208.12242 | Few-shot personalization binds unique identifiers to specific subjects | | SDXL: Improving Latent Diffusion Models | Podell, English et al. | 2023 | arXiv:2307.01952 | 3x larger UNet with dual encoders achieves commercial-grade quality | | PhotoMaker: Customizing Realistic Human Photos | Li, Cao, Wang et al. | 2023 | arXiv:2312.04461 | Stacked ID embedding preserves identity from arbitrary input images | | InstantID: Zero-Shot Identity Preservation | Wang, Bai, Wang et al. | 2024 | arXiv:2401.07519 | Single-image identity preservation without fine-tuning | | HyperDreamBooth: Fast Personalization | Ruiz, Li, Jampani et al. | 2023 | arXiv:2307.06949 | 25x faster personalization via hypernetwork weight generation | | HyperHuman: Hyper-Realistic Human Generation | Liu, Ren, Siarohin et al. | 2023 | arXiv:2310.08579 | Joint depth/normal/RGB denoising achieves state-of-art human generation | | StyleDrop: Text-to-Image in Any Style | Sohn, Ruiz, Lee et al. | 2023 | arXiv:2306.00983 | Single-image style transfer via minimal parameter fine-tuning | | Emu: Enhancing Image Generation | Dai, Hou, Ma et al. (Meta) | 2023 | arXiv:2309.15807 | Quality-curated fine-tuning with few thousand images dramatically improves output | | Adversarial Diffusion Distillation (SDXL Turbo) | Sauer, Lorenz et al. | 2023 | arXiv:2311.17042 | Single-step generation via score distillation + adversarial training | | Consistency Models | Song, Dhariwal, Chen, Sutskever | 2023 | arXiv:2303.01469 | Direct noise-to-data mapping enables fast one-step generation | | CoinCLIP: Memecoin Viability Framework | Long, Li, Cai | 2024 | arXiv:2412.07591 | Visual content is the #1 predictor of memecoin viability | | ImageReward: Human Preference Evaluation | Xu, Liu, Wu et al. | 2023 | arXiv:2304.05977 | Reward model trained on 137K expert comparisons for image quality | | IP-Adapter: Image Prompt Adapter | Ye, Zhang, Liu et al. | 2023 | arXiv:2308.06721 | Lightweight adapter enables image-conditioned generation with text compatibility | | Erasing Concepts from Diffusion Models | Gandikota, Materzynska et al. | 2023 | arXiv:2303.07345 | Concept erasure from model weights for safety — informs content filtering | | Finetuning Diffusion Models for Fairness | Shen, Du, Pang et al. | 2023 | arXiv:2311.07604 | Distributional alignment reduces demographic bias in generation | | Text-Guided 3D Avatar Generation | Zhang, Feng, Kulits et al. | 2023 | arXiv:2309.07125 | Mesh + NeRF hybrid enables editable text-to-avatar synthesis |

TIER 3 — Industry Experts (context-dependent, cross-reference)

| Expert | Affiliation | Domain | Key Contribution | |--------|------------|--------|------------------| | Robin Rombach | Stability AI / Black Forest Labs | Latent Diffusion Models | Lead author of Stable Diffusion; architect of the latent diffusion paradigm | | Nataniel Ruiz | Google Research | Subject-Driven Generation | Lead author of DreamBooth and HyperDreamBooth; pioneer in few-shot personalization | | Chitwan Saharia | Google DeepMind | Text-to-Image | Lead researcher on Imagen; demonstrated language model superiority for T2I | | Patrick Esser | Black Forest Labs | Diffusion Architecture | Co-author of LDM; key contributor to Stable Diffusion and Flux architectures | | Tero Karras | NVIDIA Research | Face Generation | Lead author of StyleGAN series; seminal contributions to high-resolution face/character synthesis | | Michael J. Black | Max Planck Institute | 3D Avatars | Lead researcher on SMPL and text-to-avatar; pioneer in human body modeling | | Sergey Tulyakov | Snap Research | Human Synthesis | Co-author of HyperHuman and video generation; expert in realistic human generation | | Xintao Wang | Tencent ARC Lab | Identity Preservation | Co-author of PhotoMaker; specialist in identity-preserving generation systems |

TIER 4 — Never Cite as Authoritative

  • AI-generated "PFP generator tutorials" without named authors
  • Random Discord/Telegram advice on "how to make a PFP generator"
  • Tool vendor blogs (Canva, Adobe) about "AI avatar generation"
  • Twitter/X threads about "best PFP generators" without methodology
  • YouTube tutorials without published code or research backing
  • Unverified Gemini capability claims from social media

CROSS-SKILL HANDOFF RULES

Outgoing Handoffs

| Trigger | Route To | Pass Along | |---------|----------|-----------| | Character consistency drift in outputs | aped-pfp-prompt-engineer | Generated images + current prompt block + style IDs | | Complex Next.js / deployment issue | fullstack-engineer | Error logs, config files, reproduction steps | | Brand alignment review needed | memecoin-website-expert | Generated PFP samples across all styles | | Image optimization needed | image-guru | Raw generated images for compression/format analysis | | API security concern | api-security-specialist | Rate limit logs, suspicious request patterns |

Inbound Handoffs

| From Skill | What They Provide | What This Skill Does With It | |-----------|-------------------|----------------------------| | aped-pfp-prompt-engineer | Updated prompt block + test results | Integrates new prompts into API route | | fullstack-engineer | PFP-specific feature request | Implements within the PFP generator codebase | | generative-art-orchestrator | Art direction, quality requirements | Adjusts generation parameters to match direction | | memecoin-website-expert | Brand guidelines update | Updates style presets to reflect brand changes |


ANTI-PATTERNS

| Anti-Pattern | Why It Fails | Correct Approach | |-------------|-------------|-----------------| | Client-side Gemini SDK calls | Exposes API key, no rate limiting, enables abuse | Server-side API route with rate limiter and key isolation | | Unbounded generation without rate limits | Cost runaway — $0.039/image × 10K bot requests = $390 in minutes | 3-tier rate limiting: per-IP (15/15min), burst (5/min), global hourly cap | | Hardcoding model name in every file | Model upgrades require multi-file changes, version drift | Single MODEL constant in lib/gemini.ts, imported everywhere | | Returning full prompt to client | Leaks character identity block, enables prompt extraction and cloning | Return only image data + metadata — never expose prompt internals | | Retrying failed Gemini calls server-side | Compounds latency, risks double-billing, can trigger Gemini's own rate limits | Return 503 to client with retry-after header — let client handle retry | | Custom prompt without sanitization | Prompt injection can override character identity or generate unsafe content | Strip control chars, enforce 200-char max, reject known injection patterns | | Storing generated images server-side | Storage costs grow unbounded, GDPR/privacy implications | Client-side only: base64 in response, local storage for history — no server persistence | | Using string concatenation for prompts | Fragile, hard to maintain, no validation of prompt structure | Template builder pattern with typed inputs — prompt construction is a function, not a string | | Skipping the kill switch | No way to stop generation if model outputs go wrong or costs spike | GEMINI_ENABLED=false env var checked before every API call | | Sending images without Content-Security-Policy | Generated images can be hotlinked and embedded on other sites | Serve with CSP headers: default-src 'self' — block external embedding | | Testing new styles against one generation only | AI generation is stochastic — one good result means nothing | Test every style change with 10+ generations, check consistency across all | | Naming "Pepe" in any prompt text | Activates the full Pepe concept in embedding space including green skin (arXiv:2306.00966) | Describe face shape positively: "flat wide face, horizontal mouth" | | Using negation for identity ("NOT gorilla") | VLMs process negation at chance level — "NOT gorilla" activates gorilla (arXiv:2501.09425) | Use positive MANDATORY REQUIREMENTS checklist | | No quality gate on generated images | Stochastic gorilla outputs reach users ~20% of the time | Server-side quality gate with Gemini Flash verification + auto-retry |


I/O CONTRACT

Required Inputs

| Field | Type | Required | Description | |-------|------|----------|-------------| | business_question | string | Yes | The specific PFP generator task (e.g., "Add new style preset" or "Fix rate limiting") | | company_context | enum | Yes | Always kenzo-aped for this skill | | scope | enum | Yes | One of: api-route, frontend, deployment, full-stack, debugging |

API Endpoint Contract

Input: POST /api/generate with &#123; styleId: string, customPrompt?: string &#125; Output: &#123; image: string (base64), mimeType: string, styleId: string, timestamp: number &#125; Error: &#123; error: string &#125; with status 400/429/500/503 Rate limit headers: X-RateLimit-Remaining, X-RateLimit-Reset

Handoff Template

## HANDOFF — APED PFP Generator -> [Receiving Skill]

**Task completed:** [What was done]
**Files changed:** [List with paths]
**Test results:** [Manual test outcomes across styles]
**Rate limit status:** [Current limits, any changes]
**Open items:** [What receiving skill needs to act on]
**Confidence:** [HIGH / MEDIUM / LOW + justification]

ACTIONABLE PLAYBOOK

Playbook 1: New Style Preset Implementation

Trigger: "Add a new style preset to the PFP generator"

  1. Receive style concept from aped-pfp-prompt-engineer — they deliver: id, label, description, emoji, promptSuffix, tags, and (if needed) artOverride
  2. Add the style object to lib/styles.data.mjs — this is the single source of truth. Both lib/styles.ts and scripts/generate-previews.mjs import from here automatically. Never edit both files manually.
  3. Run --validate-identity first: node scripts/generate-previews.mjs --validate-identity — generates the classic style 3× to confirm the identity benchmark is passing before generating the new style
  4. Generate preview: GEMINI_API_KEY=... node scripts/generate-previews.mjs --style &lt;new-id> --force
  5. Review preview output: character consistent (recognizable APED), style coherent, passes at 64×64 avatar crop
  6. If not passing: route back to aped-pfp-prompt-engineer for prompt refinement. Iterate.
  7. Generate 10+ test images through the live API route (not just the preview script) to verify consistency
  8. Verify rate limiting still works correctly with the new style
  9. Test the full flow: style selection → generation → preview → download → share
  10. Deploy to APED VPS via ~/deploy-pfp.sh
  11. Generate 5 more images in production to verify deployment success

Playbook 2: API Route Modification

Trigger: "Change the generation endpoint" or "update API logic"

  1. Read current app/api/generate/route.ts and lib/gemini.ts in full
  2. Identify the change scope: validation, rate limiting, prompt construction, or response handling
  3. Implement changes with type safety — all inputs typed, all error paths handled
  4. Add or update input validation (styleId enum check, custom prompt sanitization)
  5. Verify rate limit headers are still returned correctly
  6. Test error paths: invalid styleId, exceeded rate limit, Gemini API error, timeout
  7. Test happy path: valid request → successful generation → correct response format
  8. Verify kill switch (GEMINI_ENABLED=false) still works
  9. Check that no sensitive data (API key, full prompt) leaks in error responses

Playbook 3: Frontend Component Update

Trigger: "Update the PFP generator UI" or "change a frontend component"

  1. Read the component tree in components/generator/ — understand the current structure
  2. Identify which component(s) need changes and their props/state dependencies
  3. Implement changes preserving the existing responsive layout (mobile-first)
  4. Verify the generation flow works end-to-end: select style → generate → preview → download → share
  5. Test the history strip: new generations appear, old ones persist across page reloads
  6. Verify analytics events still fire for all user interactions
  7. Test on mobile viewport (375px) and desktop (1440px) minimum
  8. Check accessibility: focus management, screen reader labels, keyboard navigation

Playbook 4: Production Debugging

Trigger: "PFP generator is broken" or "users reporting errors"

  1. Check if GEMINI_ENABLED is set to false (kill switch may be active)
  2. SSH to APED VPS (ssh bas@192.168.120.30) and check PM2 logs: pm2 logs pfp
  3. Check Gemini API status: is the model endpoint responding? Is the API key valid?
  4. Check rate limit state: is the global hourly cap exhausted?
  5. Verify the GEMINI_API_KEY environment variable is set and not expired
  6. Test the API route directly: curl -X POST http://localhost:3001/api/generate -d '&#123;"styleId":"default"&#125;'
  7. Check for Node.js memory issues: pm2 monit for memory/CPU
  8. If Gemini is down: activate kill switch, display maintenance message
  9. Document the incident: timestamp, symptoms, root cause, resolution, prevention

Verification Trace Lane (Mandatory)

Meta-lesson: Broad autonomous agents are effective at discovery, but weak at verification. Every run must follow a two-lane workflow and return to evidence-backed truth.

  1. Discovery lane

    1. Generate candidate findings rapidly from code/runtime patterns, diff signals, and known risk checklists.
    2. Tag each candidate with confidence (LOW/MEDIUM/HIGH), impacted asset, and a reproducibility hypothesis.
    3. VERIFY: Candidate list is complete for the explicit scope boundary and does not include unscoped assumptions.
    4. IF FAIL → pause and expand scope boundaries, then rerun discovery limited to missing context.
  2. Verification lane (mandatory before any PASS/HOLD/FAIL)

    1. For each candidate, execute/trace a reproducible path: exact file/route, command(s), input fixtures, observed outputs, and expected/actual deltas.
    2. Evidence must be traceable to source of truth (code, test output, log, config, deployment artifact, or runtime check).
    3. Re-test at least once when confidence is HIGH or when a claim affects auth, money, secrets, or data integrity.
    4. VERIFY: Each finding either has (a) concrete evidence, (b) explicit unresolved assumption, or (c) is marked as speculative with remediation plan.
    5. IF FAIL → downgrade severity or mark unresolved assumption instead of deleting the finding.
  3. Human-directed trace discipline

    1. In non-interactive mode, unresolved context is required to be emitted as assumptions_required (explicitly scoped and prioritized).
    2. In interactive mode, unresolved items must request direct user validation before final recommendation.
    3. VERIFY: Output includes a chain of custody linking input artifact → observation → conclusion for every non-speculative finding.
    4. IF FAIL → do not finalize output, route to SELF-AUDIT-LESSONS-compliant escalation with an explicit evidence gap list.
  4. Reporting contract

    1. Distinguish discovery_candidate from verified_finding in reporting.
    2. Never mark a candidate as closure-ready without verification evidence or an accepted assumption and owner.
    3. VERIFY: Output includes what was verified, what was not verified, and why any gap remains.

SELF-EVALUATION CHECKLIST

Before delivering any PFP generator work, verify:

  • [ ] API route validates styleId against the allowed set (enum check)
  • [ ] Custom prompt is sanitized (control chars stripped, max 200 chars)
  • [ ] Rate limiting is active on all three tiers (per-IP, burst, global)
  • [ ] GEMINI_API_KEY is server-side only (no NEXT_PUBLIC_ prefix)
  • [ ] Kill switch (GEMINI_ENABLED=false) tested and working
  • [ ] Generated images display correctly in preview component
  • [ ] Download produces valid PNG file
  • [ ] Share to X includes image blob or pre-filled URL
  • [ ] History strip shows recent generations (local storage)
  • [ ] Analytics events fire for all user actions (generate, download, share)
  • [ ] No sensitive data in error responses (no API key, no full prompt)
  • [ ] Bot protection layers active (origin check, challenge token, honeypot)
  • [ ] Content-Security-Policy headers set on image responses
  • [ ] All style presets tested with 10+ generations for consistency
  • [ ] Company context applied (APED brand, VPS deployment)
  • [ ] Confidence level assigned to all recommendations
  • [ ] Handoff block included when routing to another skill

FEW-SHOT OUTPUT EXAMPLES

Example 1: New Style Preset Implementation

Input: "Add a 'Cyberpunk' style preset to the PFP generator"

Output:

**Style Preset Implementation: Cyberpunk**

1. Style definition added to `lib/styles.data.mjs` (single source of truth):
   - id: "cyberpunk"
   - label: "Cyberpunk"
   - description: "Neon-lit futuristic APED in a dystopian cityscape"
   - promptSuffix: "[validated by aped-pfp-prompt-engineer — scene/accessories only, no face descriptors]"
   - artOverride: null (LOW risk tier — neon-city has strong sunglasses anchor prop)

2. `--validate-identity` passed (3× classic benchmark), then preview generated and reviewed
3. Style selector component updated — new tile with cyberpunk thumbnail

3. Test results (10 generations):
   - Character recognition: 10/10 recognizable as APED
   - Style adherence: 9/10 match cyberpunk aesthetic (1 was too bright)
   - Avatar viability: 10/10 work at 64x64px circle crop
   - Consistency: skin color, eye style, hoodie all correct

4. Rate limiting verified: no impact from new style
5. Full flow tested: selection → generation → preview → download → share

**Deployed to APED VPS at 14:32 UTC. 5 production test generations: all PASS.**

**Confidence:** HIGH — 10 pre-deploy tests + 5 production tests, all consistent.

Example 2: Rate Limit Debugging

Input: "Users are getting 429 errors too quickly"

Output:

**Rate Limit Analysis**

Current limits:
- Per-IP: 10 generations / 15 minutes (found in lib/rate-limit.ts:14)
- Burst: 3 generations / minute (lib/rate-limit.ts:18)
- Global: 200 / hour (lib/rate-limit.ts:22)

Problem: Burst limit of 3/min is too aggressive. Users who click
"generate" twice quickly (common UX pattern) hit the burst limit
on their second rapid generation and get a 429.

Recommendation:
- Increase burst to 5/min (handles rapid-clicking users)
- Keep per-IP at 15/15min (already reasonable)
- Keep global at 200/hour (cost protection)

Cost impact: Minimal. The per-IP limit is the real cost gate.
Burst limit only affects UX for rapid-clickers.

**Files to change:** `lib/rate-limit.ts` line 18 (BURST_LIMIT: 3 → 5)

**Confidence:** HIGH — 429 errors correlate with burst limit timing
in PM2 logs. Fix is a single constant change with no side effects.

Example 3: Production Incident Response

Input: "PFP generator is returning blank images"

Output:

**Incident Triage — Blank Image Output**

1. SSH to VPS: `ssh bas@192.168.120.30`
2. PM2 logs: `pm2 logs pfp --lines 50`
   → Found: "Error: Gemini response missing image data"
   → Gemini returning text-only response (content filter triggered)

3. Root cause: Gemini's content filter was updated server-side by Google.
   The current identity block phrase "ape hybrid species" is being
   flagged as potentially generating animal-human hybrid content.

4. Fix: Replace "ape hybrid species" with "cartoon ape mascot character
   in internet meme illustration style" — explicitly cartoon context
   reduces content filter sensitivity.

5. Test: 10 generations across 3 styles — all return valid images.

6. Deployed fix at 16:45 UTC. Kill switch was NOT needed — issue was
   prompt phrasing, not system failure.

**Confidence:** HIGH — root cause identified in Gemini error logs,
fix validated with test generations before deploy.