aRustyDev / aRustyDev/blog

feat: CI workflow for image resizing and optimization

Open
#53 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

## Summary

Implement an automated image processing pipeline that generates optimized, responsive image variants during CI/CD builds.

## Motivation

- Large images slow down page loads and hurt SEO
- Manually resizing images for different breakpoints is tedious
- Modern formats (AVIF, WebP) provide significant size savings but need fallbacks
- Consistent image handling improves developer experience

## Technical Approach

### Core Decisions

| Decision | Choice | Rationale |
|----------|--------|-----------|
| Processing Tool | **Sharp** | Already installed, 10-50x faster than alternatives |
| Output Formats | AVIF, WebP, JPEG | AVIF (best compression), WebP (broad support), JPEG (fallback) |
| Storage | Git-tracked source, gitignored output | Reproducible builds, no external dependencies |
| Caching | Hash-based manifest | Skip unchanged images for incremental builds |

### Size Configurations

| Name | Width | Use Case |
|------|-------|----------|
| thumb | 150px | Thumbnails, related posts |
| small | 320px | Mobile portrait |
| medium | 640px | Tablet, small desktop |
| large | 1024px | Desktop content area |
| xl | 1400px | Full-width hero images |
| 2x | 2048px | High-DPI displays |

### Configuration File (`images.config.json`)

```json
{
"$schema": "https://schemas.arusty.dev/blog/images.config.schema.json",
"sourceDir": "src/assets/images",
"outputDir": "public/_images",
"formats": ["avif", "webp", "jpeg"],
"sizes": {
"thumb": { "width": 150 },
"small": { "width": 320 },
"medium": { "width": 640 },
"large": { "width": 1024 },
"xl": { "width": 1400 }
},
"quality": {
"avif": 65,
"webp": 80,
"jpeg": 80
}
}
```

## Implementation Tasks

### Phase 1: Core Infrastructure
- [ ] Create JSON schema for `images.config.json`
- [ ] Create `scripts/process-images.ts` using Sharp
- [ ] Implement hash-based caching with manifest file
- [ ] Add `npm run images` script
- [ ] Integrate into `npm run build`

### Phase 2: GitHub Actions Integration
- [ ] Add image processing step to workflow
- [ ] Configure `public/_images/` caching
- [ ] Add cache restoration from previous builds
- [ ] Add processing metrics logging

### Phase 3: Astro Integration
- [ ] Create `` component with srcset generation
- [ ] Create image utility functions for path resolution
- [ ] Update content schema with image field types
- [ ] Document usage with examples

### Phase 4: Optimization
- [ ] Add parallel processing for multiple images
- [ ] Add error handling and clear messages
- [ ] Add `--dry-run` mode
- [ ] Add verbose logging option

## File Structure

```
blog/
├── images.config.json
├── scripts/
│ └── process-images.ts
├── src/
│ ├── assets/
│ │ ├── images/ # Source (git tracked)
│ │ └── .image-manifest.json
│ └── components/
│ └── Picture.astro
└── public/
└── _images/ # Generated (gitignored)
```

## Dependencies

- `sharp` - Already installed
- `glob` - For file discovery (add as devDependency)

## Future Enhancements

- [ ] Cloudflare Image Resizing for on-demand processing
- [ ] R2 storage for generated images
- [ ] Blur placeholder (LQIP) generation
- [ ] Art direction support for different crops per breakpoint

## Labels
enhancement, infrastructure, images

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.