Skip to content

ad-asset-pipeline

Use when running the full ad asset pipeline — classify, center-crop, deduplicate, generate platform variants, and sync to Cloudinary. Orchestrates all 5 pipeline skills in sequence with progress reporting and resume capability.

ModelSource
sonnetpack: ad-assets

Full ad asset pipeline orchestrator. Runs all 5 pipeline skills in sequence. Accepts a Cloudinary folder or local directory as input, processes every qualifying image through classification, smart cropping, deduplication, variant generation, and Cloudinary sync. Supports batch mode, per-asset error recovery, and resume from a prior run’s sync status.


Full Reference

Mandatory Announcement — FIRST OUTPUT before anything else:

┏━ ⚡ ad-asset-pipeline ━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Pipeline: [source] → [N] assets → [platform(s)] ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Full ad asset pipeline orchestrator. Runs all 5 pipeline skills in sequence. Accepts a Cloudinary folder or local directory as input, processes every qualifying image through classification, smart cropping, deduplication, variant generation, and Cloudinary sync. Supports batch mode, per-asset error recovery, and resume from a prior run’s sync status.


[Cloudinary folder / local directory]
1. classify-ad-assets
→ AssetClassification[] (eligible assets only)
2. face-center-crop
→ Crop gravity assigned (g_face | g_auto)
3. deduplicate-assets
→ Deduplicated variant list (3-layer check)
4. generate-ad-variants
→ Variant manifest (all platform/placement URLs)
5. sync-to-cloudinary
→ sync-status.json + Cloudinary public IDs

Full pipeline on a Cloudinary folder:

Terminal window
node pipeline.js --folder ads/source-images --platforms meta,pinterest,google

Resume a prior run (skip already-synced):

Terminal window
node pipeline.js --folder ads/source-images --resume

Single asset:

Terminal window
node pipeline.js --asset ads/source-images/photo-001 --platforms meta

Dry run (classify + report, no uploads):

Terminal window
node pipeline.js --folder ads/source-images --dry-run

Show a status table per asset, updated in real time:

photo-001 classify ✓ crop ✓ dedup ✓ variants ✓ sync ✓
photo-002 classify ✓ crop ✓ dedup ✓ variants ✓ sync ●
photo-003 classify ✓ crop ✓ dedup ✗ (duplicate of photo-001)
photo-004 classify ✗ (stage 1: dimension_too_small)
photo-005 classify ✓ crop ✓ dedup ✓ variants ✓ sync ✗ (failed)
[████████████░░░░] 3/5 complete

  • Individual asset failures do not halt the pipeline — the error is captured and processing continues
  • A summary of failures is reported at the end with actionable next steps
  • Retry failed assets by re-running with --resume — deduplicate-assets skips synced variants, sync-to-cloudinary retries failed ones

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Pipeline complete
photo-001 ✓ 63 variants synced
photo-002 ✓ 58 variants synced
photo-003 ✗ duplicate — skipped
photo-004 ✗ dimension_too_small
photo-005 ◐ 2 variants failed
3 assets processed · 121 variants synced · 2 failed
▸ Re-run with --resume to retry failed variants

User SaysRoute To
”Classify this image / folder”classify-ad-assets
”Crop for ads / face-center”face-center-crop
”Remove duplicates”deduplicate-assets
”Generate ad sizes / variants”generate-ad-variants
”Upload to Cloudinary / sync”sync-to-cloudinary
”Full pipeline / start to finish”This skill — run all stages
”Resume / retry failed”This skill — with --resume

All pipeline config lives in a single pipeline.config.ts (or JSON) at project root. Each section maps to the corresponding skill’s config interface. See individual skill docs for per-stage config options.

export const pipelineConfig: PipelineConfig = {
classify: {
rules: { minWidth: 600, minHeight: 314, ... },
gemini: { domainContext: 'Your domain here', ... },
weights: DEFAULT_WEIGHTS,
thresholds: DEFAULT_ELIGIBILITY,
},
variants: {
cloudName: process.env.CLOUDINARY_CLOUD_NAME!,
google: { allowBeforeAfter: false },
},
sync: {
cloudName: process.env.CLOUDINARY_CLOUD_NAME!,
concurrency: 5,
maxRetries: 3,
statusFilePath: './sync-status.json',
},
concurrency: 3,
dryRun: false,
resume: false,
platforms: ['meta', 'pinterest', 'google'],
};