Media pipeline
The portal media pipeline converts raw uploaded images into optimized WebP variants, stores them in the GitHub repository, and serves them through a Netlify CDN-cached API route. Understanding this pipeline is useful when debugging media display issues or adding images manually.
Processing
Section titled “Processing”Images are processed by the @drawnagency/authoring CLI. Run it from the client repo root:
pnpm exec authoring process-images --project .The command reads raw images from _ingest/images/ and produces output in assets/images/. For each source image it generates WebP variants at each width in media.sizes (default: [640, 1080, 1920], configured in site-config.json).
Each processed image is assigned a 16-character hash ID derived from its content. The manifest file src/content/image-manifest.json maps each hash ID to its output folder and metadata (original filename, dimensions, MIME type). Section JSON files reference images by their hash ID in the imageId field.
Staging directory
Section titled “Staging directory”Raw images go into _ingest/images/ before processing. This directory is gitignored — only the processed output in assets/images/ gets committed to the repository.
When the /populate-site skill runs, it downloads images from websites directly into _ingest/images/. Images embedded in PDFs (logos, label artwork, pattern graphics) cannot be extracted automatically; you must provide them manually by copying the files into _ingest/images/ and re-running process-images.
Serving
Section titled “Serving”Processed images are committed to the GitHub repository as regular files. The portal serves them through /api/media/{imageId}/{width}.webp.
That API route:
- Resolves the
imageIdto a file path using the in-memory manifest cache (loaded once per function cold start). - Fetches the WebP file from GitHub using the GitHub App installation token — not the
GITHUB_TOKENPAT. This means the images are fetched server-side and the GitHub repo can remain private. - Returns the image with
Netlify-CDN-Cache-Control: public, durable, immutableso Netlify’s CDN caches it at the edge. After the first request, subsequent requests for the same image are served from the CDN without hitting the function.
Because the URL contains a content-hash ID, cached responses remain valid until the image is replaced with a new file (which produces a new hash and a new URL).
Adding images manually
Section titled “Adding images manually”To add an image outside of the /populate-site workflow:
- Drop the source file into
_ingest/images/. - Run
pnpm exec authoring process-images --project . - Note the hash ID assigned to the image in
src/content/image-manifest.json. - Reference the hash ID in your section JSON as
"imageId": "<hash>". - Commit
assets/images/,src/content/image-manifest.json, and any updated section files.