Skip to content

feat(assets): generalise compression script across all asset categories #45

@wab

Description

@wab

Parent

#32 (asset pipeline migration milestone)

Problem

scripts/compress-team-photos.js (introduced in #41) only walks assets/team/*.{jpg,jpeg}. The other asset categories — assets/clients/, assets/posts/<slug>/, assets/stories/, assets/jobs/, assets/tools/, assets/legal/ — receive arbitrary-sized images from non-tech contributors and have no automated optimisation step.

Doing this before #36 (push cleaned assets to new store) avoids pushing un-optimised bytes to the new blob store and re-doing the work later.

What to build

Rename / generalise to scripts/optimize-assets.js:

  • Walks assets/**/*.{jpg,jpeg,png,webp}
  • Per-extension pipeline:
    • JPEG: resize to fit configurable max dimension (default 1600x1600), quality 80, mozjpeg encoder
    • PNG: skip unless above threshold; if above, run through sharp.png({ quality, compressionLevel: 9, palette: true }) and only keep the result if smaller than original (size-regression guard)
    • WebP: quality 80
  • Per-directory overrides via a small config map:
    • team/ → max 800x800 (portrait avatars)
    • clients/ → max 400x400 (logos)
    • posts/, stories/ → max 1600x1600 (blog covers / story images)
    • default → 1600x1600
  • Dry-run by default, --write executes (atomic write-then-rename, already in the existing script)
  • Per-file output: category/file before → after (saved X%) or skip (under threshold) / skip (no gain)
  • Summary: total before / after / saved, broken down by extension

Keep the existing scripts/compress-team-photos.js callable as a thin wrapper or delete it once the generalised version covers the same case.

Acceptance criteria

  • scripts/optimize-assets.js walks all of assets/** and handles .jpg, .jpeg, .png, .webp
  • Per-directory size limits applied
  • PNG quantisation skipped when output ≥ input (no regressions)
  • Dry-run shows what would change; --write performs atomic in-place rewrite
  • Visual smoke check on 1 file per category (HITL gate — maintainer confirms quality)
  • Total assets/ size reduced (target: ≥ 30% global, but the win is on the long tail of large blog images, not the already-compressed team/)
  • One atomic commit with conventional message

Blocks

Blocked by

Notes

DX follow-up from #41 — raised because future non-tech contributors will push arbitrary-sized images across all categories, not just team photos. Pair with the CI auto-fix issue for the full DX story.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestready-for-agentScoped, dependencies clear, acceptance criteria explicit — grabbable by an AFK agent

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions