chore: add image optimization script and README

This commit is contained in:
Gregory Campbell
2026-06-03 21:49:46 -04:00
parent 9ba13ab4cd
commit 51d2a9c822
3 changed files with 93 additions and 1 deletions
+33
View File
@@ -1,3 +1,36 @@
# personal_site
This repository is a React-based personal website for Gregory Campbell.
Quick commands
```bash
# install deps (use legacy peer deps if you hit TypeScript/react-scripts conflicts)
npm install --legacy-peer-deps
# run dev server
npm start
# build production
npm run build
# optimize images (requires sharp)
# install sharp (one-time):
npm run optimize-images:install
# then run optimization:
npm run optimize-images
```
Image optimization
This repo includes `scripts/optimize-images.js`, a small Node script that uses `sharp` to generate WebP resized variants for images found in `src/assets`. The script writes outputs to `public/images` by default.
If you prefer a different pipeline, consider using `imagemin` or a CI-integrated image optimization step.
Deployment / Amplify notes
- The project uses `package-lock.json` (npm) — ensure CI is configured to use `npm install` and not `yarn`.
- If deploying via AWS Amplify and it errors with multiple lockfiles, ensure only one lockfile (package-lock.json) is present.
[![Netlify Status](https://api.netlify.com/api/v1/badges/b9a5df97-64f4-4888-8d76-548e77e029ae/deploy-status)](https://app.netlify.com/projects/gregoryjcampbell/deploys)
This is the source code for my [Personal Website](https://gregoryjcampbell.netlify.app/).
+3 -1
View File
@@ -29,7 +29,9 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"optimize-images": "node scripts/optimize-images.js",
"optimize-images:install": "npm install --save-dev sharp --legacy-peer-deps"
},
"eslintConfig": {
"extends": "react-app"
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
async function main() {
let sharp;
try {
sharp = require('sharp');
} catch (e) {
console.error('\nError: the package "sharp" is not installed.');
console.error('Install it with: npm install --save-dev sharp');
console.error('Or run: npm run optimize-images:install to install prerequisites.\n');
process.exit(1);
}
const assetsDir = path.join(__dirname, '..', 'src', 'assets');
const outDir = path.join(__dirname, '..', 'public', 'images');
if (!fs.existsSync(assetsDir)) {
console.error('No assets directory found at', assetsDir);
process.exit(1);
}
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
const files = fs.readdirSync(assetsDir).filter((f) => /\.(jpe?g|png)$/i.test(f));
if (!files.length) {
console.log('No PNG/JPG assets found to optimize.');
return;
}
console.log(`Optimizing ${files.length} images to ${outDir} ...`);
const sizes = [320, 640, 1024];
for (const file of files) {
const input = path.join(assetsDir, file);
const name = path.parse(file).name;
for (const w of sizes) {
const outPath = path.join(outDir, `${name}-${w}.webp`);
try {
await sharp(input)
.resize({ width: w })
.webp({ quality: 80 })
.toFile(outPath);
console.log('wrote', outPath);
} catch (err) {
console.error('failed to process', input, err.message);
}
}
}
console.log('\nImage optimization complete. Copy generated files into your build or update components to reference them.');
}
main().catch((err) => {
console.error(err);
process.exit(1);
});