Skillshub adobe-reference-architecture
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/jeremylongshore/claude-code-plugins-plus-skills/adobe-reference-architecture" ~/.claude/skills/comeonoliver-skillshub-adobe-reference-architecture && rm -rf "$T"
manifest:
skills/jeremylongshore/claude-code-plugins-plus-skills/adobe-reference-architecture/SKILL.mdsource content
Adobe Reference Architecture
Overview
Production-ready architecture patterns for Adobe API integrations, designed around the three main API families: Firefly Services (creative AI), PDF Services (document automation), and I/O Events (event-driven).
Prerequisites
- Understanding of layered architecture
- TypeScript project setup
- Decision on which Adobe APIs to integrate
Instructions
Step 1: Project Structure
my-adobe-project/ ├── src/ │ ├── adobe/ # Adobe client layer │ │ ├── auth.ts # OAuth Server-to-Server token management │ │ ├── firefly-client.ts # Firefly API wrapper (generate, fill, expand) │ │ ├── pdf-client.ts # PDF Services wrapper (create, extract, merge) │ │ ├── photoshop-client.ts # Photoshop API wrapper (cutout, actions) │ │ ├── events-client.ts # I/O Events registration and verification │ │ ├── types.ts # Shared Adobe types │ │ └── errors.ts # Error classification (retryable vs permanent) │ ├── services/ # Business logic layer │ │ ├── image-generation.ts # Orchestrates Firefly + Photoshop workflows │ │ ├── document-pipeline.ts # Orchestrates PDF create/extract/merge │ │ └── event-processor.ts # Routes and processes I/O Events │ ├── api/ # API layer (routes, controllers) │ │ ├── health.ts # Health check including Adobe IMS │ │ ├── webhooks/adobe.ts # I/O Events webhook endpoint │ │ └── routes/ │ │ ├── images.ts # Image generation endpoints │ │ └── documents.ts # Document processing endpoints │ ├── jobs/ # Background job layer │ │ ├── firefly-batch.ts # Batch image generation queue │ │ └── pdf-extraction.ts # Async PDF extraction worker │ └── index.ts ├── tests/ │ ├── unit/ │ │ ├── adobe/auth.test.ts │ │ └── services/ │ └── integration/ │ └── adobe/ │ ├── firefly.test.ts │ └── pdf-services.test.ts ├── config/ │ ├── adobe.development.json │ ├── adobe.staging.json │ └── adobe.production.json └── package.json
Step 2: Layer Architecture
┌─────────────────────────────────────────────────────┐ │ API Layer │ │ Routes, Controllers, Webhook Endpoints │ ├─────────────────────────────────────────────────────┤ │ Service Layer │ │ Business Logic, Workflow Orchestration │ │ (image-generation.ts, document-pipeline.ts) │ ├─────────────────────────────────────────────────────┤ │ Adobe Client Layer │ │ auth.ts, firefly-client.ts, pdf-client.ts │ │ Token caching, retry, error classification │ ├─────────────────────────────────────────────────────┤ │ Infrastructure Layer │ │ Cache (LRU/Redis), Queue (BullMQ), Monitoring │ └─────────────────────────────────────────────────────┘
Rules:
- API layer never calls Adobe APIs directly — always through Service layer
- Service layer orchestrates multiple Adobe clients (e.g., Firefly + Photoshop)
- Adobe Client layer handles auth, retry, error classification
- Infrastructure layer is swappable (in-memory cache for dev, Redis for prod)
Step 3: Error Boundary
// src/adobe/errors.ts export class AdobeServiceError extends Error { constructor( message: string, public readonly code: string, public readonly httpStatus: number, public readonly retryable: boolean, public readonly api: 'firefly' | 'pdf-services' | 'photoshop' | 'events', public readonly retryAfter?: number, public readonly originalError?: Error ) { super(message); this.name = 'AdobeServiceError'; } static fromResponse(api: string, status: number, body: string, headers?: Headers): AdobeServiceError { const retryAfter = headers?.get('Retry-After'); return new AdobeServiceError( `Adobe ${api} API error (${status}): ${body.slice(0, 200)}`, status === 429 ? 'RATE_LIMITED' : status === 401 ? 'AUTH_EXPIRED' : status >= 500 ? 'SERVER_ERROR' : 'CLIENT_ERROR', status, status === 429 || status >= 500, api as any, retryAfter ? parseInt(retryAfter) : undefined, ); } }
Step 4: Configuration Management
// config/adobe.ts export interface AdobeConfig { clientId: string; clientSecret: string; scopes: string; environment: 'development' | 'staging' | 'production'; apis: { firefly: { enabled: boolean; baseUrl: string }; pdfServices: { enabled: boolean }; photoshop: { enabled: boolean; baseUrl: string }; events: { enabled: boolean; webhookUrl: string }; }; retry: { maxRetries: number; baseDelayMs: number }; cache: { enabled: boolean; ttlSeconds: number }; } export function loadConfig(): AdobeConfig { const env = process.env.NODE_ENV || 'development'; const base = require(`./adobe.${env}.json`); return { ...base, clientId: process.env.ADOBE_CLIENT_ID!, clientSecret: process.env.ADOBE_CLIENT_SECRET!, scopes: process.env.ADOBE_SCOPES!, environment: env as any, }; }
Step 5: Health Check
// src/api/health.ts export async function adobeHealthCheck(config: AdobeConfig) { const checks: Record<string, any> = {}; // Always check IMS auth try { const start = Date.now(); await getCachedToken(); checks.ims = { status: 'healthy', latencyMs: Date.now() - start }; } catch (e: any) { checks.ims = { status: 'unhealthy', error: e.message }; } // Check enabled APIs if (config.apis.firefly.enabled) { checks.firefly = await pingEndpoint('https://firefly-api.adobe.io'); } if (config.apis.photoshop.enabled) { checks.photoshop = await pingEndpoint('https://image.adobe.io'); } const overall = Object.values(checks).every( (c: any) => c.status === 'healthy' ) ? 'healthy' : 'degraded'; return { status: overall, services: checks }; }
Data Flow
User Request │ ▼ ┌─────────────┐ │ Express │ ← Webhook from Adobe I/O Events │ Router │ └──────┬───┬──┘ │ │ ▼ ▼ ┌────────┐ ┌────────────┐ │Service │ │Event │ │Layer │ │Processor │ └───┬────┘ └──────┬─────┘ │ │ ▼ ▼ ┌──────────────────────┐ ┌─────────┐ │ Adobe Client Layer │───▶│ Cache │ │ (auth + API calls) │ │ LRU/Redis│ └──────────┬───────────┘ └─────────┘ │ ┌──────┼──────┐ ▼ ▼ ▼ ┌──────┐┌──────┐┌──────┐ │Firefly││PDF ││Photo │ │API ││Svc ││shop │ └──────┘└──────┘└──────┘
Output
- Layered project structure separating concerns
- Error boundary with classification and retry logic
- Per-environment configuration with secret injection
- Health check covering IMS and all enabled APIs
Resources
Next Steps
For multi-environment setup, see
adobe-multi-env-setup.