# Blog Image Audit Guide

**Last Updated:** 2026-01-10

## Overview

This guide provides instructions for running image audits, interpreting reports, fixing common issues, and maintaining image health across all blog posts.

## Quick Start

### Run Comprehensive Audit

```bash
python3 v2/scripts/blog/comprehensive-image-audit.py
```

This runs all verification checks and generates a comprehensive report.

### Monitor Image Health

```bash
python3 v2/scripts/blog/monitor-image-health.py
```

Run this periodically (e.g., weekly) to catch new issues.

## Audit Scripts

### 1. Image References Audit

**Purpose:** Extract all image references from all blog post JSON files.

**Script:** `v2/scripts/blog/audit-image-references.py`

**Usage:**

```bash
python3 v2/scripts/blog/audit-image-references.py
```

**Output:** `docs/data/blog-image-references-audit.json`

**What it checks:**

- Featured images per post
- Images array entries per post
- HTML content image references (`<img>` tags)
- WordPress URLs still present
- Local paths referenced

**Interpreting results:**

- `posts_with_wordpress_urls`: Should be 0
- `unique_local_paths`: List of all referenced image paths
- `posts_with_issues`: Posts that need attention

### 2. Physical Images Audit

**Purpose:** Catalog all files in `/v2/img/insights/` and identify orphaned/duplicate files.

**Script:** `v2/scripts/blog/audit-physical-images.py`

**Usage:**

```bash
python3 v2/scripts/blog/audit-physical-images.py --check-duplicates
```

**Output:** `docs/data/blog-physical-images-audit.json`

**What it checks:**

- All files with sizes, formats, modification dates
- Orphaned files (not referenced in any post)
- Duplicate files (same content, different names)

**Interpreting results:**

- `orphaned_files`: Files not referenced in any post (can be deleted)
- `duplicates`: Files with identical content (can be consolidated)

### 3. Image Mapping Audit

**Purpose:** Cross-reference image references with physical files.

**Script:** `v2/scripts/blog/audit-image-mapping.py`

**Usage:**

```bash
python3 v2/scripts/blog/audit-image-mapping.py
```

**Output:** `docs/data/blog-image-mapping-audit.json`

**What it checks:**

- Posts with missing images
- Posts with broken image paths
- Posts with WordPress URLs
- Posts with incorrect formats
- Posts with missing alt text
- Posts with missing dimensions

**Interpreting results:**

- `posts_with_missing_images`: Posts referencing non-existent files
- `total_missing_images`: Total count of missing image references
- `orphaned_files`: Physical files not referenced anywhere

### 4. Featured Images Verification

**Purpose:** Verify all featured images use correct paths and exist.

**Script:** `v2/scripts/blog/verify-featured-images.py`

**Usage:**

```bash
python3 v2/scripts/blog/verify-featured-images.py
```

**Output:** `docs/data/blog-featured-images-verification.json`

**What it checks:**

- All featured images use `/insights/bilder/` format
- All featured image files exist
- All featured images are WebP or SVG
- All featured images have valid alt text
- All featured images have width/height

**Interpreting results:**

- `posts_ok`: Posts with no issues
- `posts_with_warnings`: Posts with minor issues (missing alt, dimensions)
- `posts_with_errors`: Posts with critical issues (missing files, WordPress URLs)

### 5. Content Images Verification

**Purpose:** Verify all HTML content images use correct paths and exist.

**Script:** `v2/scripts/blog/verify-content-images.py`

**Usage:**

```bash
python3 v2/scripts/blog/verify-content-images.py
```

**Output:** `docs/data/blog-content-images-verification.json`

**What it checks:**

- All `<img src>` attributes use `/insights/bilder/` format
- All `srcset` attributes use `/insights/bilder/` format
- All referenced files exist
- No WordPress URLs remain in HTML content
- All images have proper attributes (alt, loading, width, height)

**Interpreting results:**

- `images_ok`: Images with no issues
- `images_with_warnings`: Images with minor issues (missing attributes)
- `images_with_errors`: Images with critical issues (missing files, WordPress URLs)

### 6. URL Rewrite Testing

**Purpose:** Test that `.htaccess` rewrite rule works correctly.

**Script:** `v2/scripts/blog/test-url-rewrite.py`

**Usage:**

```bash
python3 v2/scripts/blog/test-url-rewrite.py --sample-size 30
```

**Output:** `docs/data/blog-url-rewrite-test.json`

**What it checks:**

- Image URLs are accessible (200 status)
- Rewrite rule is working correctly

**Interpreting results:**

- `accessible`: Images that returned 200 OK
- `not_found`: Images that returned 404 (check file paths)
- `errors`: Network errors (check server configuration)

### 7. Image Wrapping Testing

**Purpose:** Test lightbox wrapper creation for various image patterns.

**Script:** `v2/scripts/blog/test-image-wrapping.py`

**Usage:**

```bash
python3 v2/scripts/blog/test-image-wrapping.py
```

**Output:** `docs/data/blog-image-wrapping-test.json`

**What it checks:**

- Images with srcset
- Images without srcset
- Images already in `<a>` tags
- Images with various attributes
- Images with empty alt text

**Interpreting results:**

- `images_with_srcset`: Count of images with responsive srcset
- `images_inside_link`: Images that won't be wrapped (already in links)
- `images_empty_alt`: Images needing alt text

## Fixing Common Issues

### Issue: WordPress URLs Still Present

**Symptoms:**

- Images load from WordPress domain
- Audit shows WordPress URLs in references

**Fix:**

```bash
python3 v2/scripts/blog/convert-wordpress-urls-in-json.py --dry-run  # Preview
python3 v2/scripts/blog/convert-wordpress-urls-in-json.py  # Apply
```

**Verification:**

```bash
python3 v2/scripts/blog/audit-image-references.py | grep -i "wordpress"
```

### Issue: Missing Image Files

**Symptoms:**

- Images return 404 errors
- Audit shows missing files

**Fix:**

1. Check if file exists in `/v2/img/insights/`
2. If missing, download from WordPress (if still accessible):
   ```bash
   python3 v2/scripts/blog/fix-missing-images.py --dry-run
   ```
3. Note: Most "missing" images are srcset variants - browser falls back to main src

**Verification:**

```bash
python3 v2/scripts/blog/verify-content-images.py
```

### Issue: Missing Alt Text

**Symptoms:**

- Images have empty or missing alt attributes
- Accessibility warnings

**Fix:**

```bash
python3 v2/scripts/blog/fix-image-attributes.py --dry-run  # Preview
python3 v2/scripts/blog/fix-image-attributes.py  # Apply
```

**Verification:**

```bash
python3 v2/scripts/blog/verify-content-images.py | grep -i "missing alt"
```

### Issue: Missing Loading Attribute

**Symptoms:**

- Images don't lazy load
- Performance issues

**Fix:**

```bash
python3 v2/scripts/blog/fix-image-attributes.py
```

**Verification:**

```bash
python3 v2/scripts/blog/verify-content-images.py | grep -i "missing loading"
```

### Issue: Missing Dimensions

**Symptoms:**

- Layout shift when images load
- CLS (Cumulative Layout Shift) issues

**Fix:**

```bash
python3 v2/scripts/blog/fix-image-attributes.py
```

**Verification:**

```bash
python3 v2/scripts/blog/verify-content-images.py | grep -i "missing dimensions"
```

### Issue: Images Not Displaying

**Symptoms:**

- Images load (200 status) but don't display
- CSS issues

**Fix:**

1. Check CSS rules in `v2/css/blog.css`
2. Update minified CSS:
   ```bash
   npm run minify
   ```
3. Verify CSS includes image rules:
   ```bash
   grep -c "blog-image-lightbox-trigger\|\.post-content.*img" v2/css/blog.min.css
   ```

**Verification:**

- Check browser DevTools
- Verify CSS rules are applied
- Check for JavaScript errors

## Maintenance Procedures

### Weekly Tasks

1. **Monitor Health:**

   ```bash
   python3 v2/scripts/blog/monitor-image-health.py
   ```

2. **Review Logs:**
   ```bash
   tail -20 docs/data/blog-image-health-monitor.log
   ```

### Monthly Tasks

1. **Run Comprehensive Audit:**

   ```bash
   python3 v2/scripts/blog/comprehensive-image-audit.py
   ```

2. **Review Reports:**

   - Check `docs/data/blog-comprehensive-audit.json`
   - Review any warnings or errors
   - Fix issues found

3. **Clean Up Orphaned Files:**
   ```bash
   python3 v2/scripts/blog/audit-physical-images.py --check-duplicates
   # Review orphaned_files in report
   # Delete files not referenced in any post
   ```

### After Adding New Posts

1. **Verify Images:**

   ```bash
   python3 v2/scripts/blog/verify-featured-images.py --file {category}/{slug}
   python3 v2/scripts/blog/verify-content-images.py --file {category}/{slug}
   ```

2. **Check for WordPress URLs:**
   ```bash
   python3 v2/scripts/blog/audit-image-references.py --file {category}/{slug}
   ```

## Best Practices

### Before Committing Changes

1. Run verification scripts
2. Fix any issues found
3. Update minified CSS if CSS changed
4. Review audit reports

### When Adding New Images

1. Download and convert to WebP
2. Place in `/v2/img/insights/`
3. Use `/insights/bilder/` path format
4. Update post JSON file
5. Verify image displays correctly

### When Updating Existing Posts

1. Check for WordPress URLs
2. Verify image paths are correct
3. Ensure images have proper attributes
4. Run verification scripts

## Troubleshooting

### Script Errors

**Error:** "Script not found"

- **Solution:** Check script path, ensure you're in project root

**Error:** "Posts directory not found"

- **Solution:** Verify `v2/data/blog/posts/` exists

**Error:** "Permission denied"

- **Solution:** Make scripts executable: `chmod +x v2/scripts/blog/*.py`

### Report Interpretation

**High missing_images count:**

- Usually srcset variants (normal)
- Only fix if main src is missing

**WordPress URLs found:**

- Run `convert-wordpress-urls-in-json.py`
- Verify PostContent.php defensive cleanup

**Orphaned files:**

- Review before deleting
- May be used in future posts

## Related Documentation

- [IMAGE_STORAGE_GUIDE.md](./IMAGE_STORAGE_GUIDE.md) - Image storage system overview
- [BLOG_TYPOGRAPHY_GUIDE.md](./BLOG_TYPOGRAPHY_GUIDE.md) - Typography and content formatting
