Skip to content

Instantly share code, notes, and snippets.

@ydrea
Last active December 29, 2025 09:54
Show Gist options
  • Select an option

  • Save ydrea/9542ab33eb8a48e750b8801f9fd4d493 to your computer and use it in GitHub Desktop.

Select an option

Save ydrea/9542ab33eb8a48e750b8801f9fd4d493 to your computer and use it in GitHub Desktop.
// genassets.js
import { generateImageAsync } from '@expo/image-utils';
import fs from 'fs/promises';
import path from 'path';
import readline from 'readline';
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
async function ask(question) {
return new Promise(resolve => rl.question(question, resolve));
}
async function findPNGFile(userInput) {
const projectRoot = process.cwd();
// If user entered a full path, use it
if (userInput.includes('/') || userInput.includes('\\')) {
return userInput;
}
// Try common locations
const possibleLocations = [
`./assets/images/${userInput}`,
`./assets/${userInput}`,
`./${userInput}`,
`./images/${userInput}`,
`./src/assets/${userInput}`,
`./public/${userInput}`
];
for (const location of possibleLocations) {
const fullPath = path.join(projectRoot, location);
try {
await fs.access(fullPath);
console.log(`found at: ${location}`);
return location;
} catch {
// Continue checking other locations
}
}
// If not found, return the original input (will show error later)
return userInput;
}
async function generateAssets() {
console.log('Asset Generator\n');
// Get input file
let inputPath = await ask('PNG file name or path [LOGO.png]: ') || 'LOGO.png';
// Try to find the file
inputPath = await findPNGFile(inputPath);
const fullPath = path.join(process.cwd(), inputPath);
// Verify file exists
try {
await fs.access(fullPath);
console.log(`using: ${inputPath}`);
} catch {
console.error(`\n cannot find: ${inputPath}`);
console.log(`Full path: ${fullPath}`);
console.log('\nPlease make sure the file exists.');
rl.close();
return;
}
// Get output directory
const outputDir = await ask('Output directory [./assets/genassets]: ') || './assets/genassets';
await fs.mkdir(outputDir, { recursive: true });
console.log(`\n generating assets...\n`);
// Generate essential assets
const assets = [
{ name: 'icon-1024', width: 1024, height: 1024, bg: 'transparent', resize: 'cover' },
{ name: 'icon-192', width: 192, height: 192, bg: 'transparent', resize: 'cover' },
{ name: 'splash-android', width: 828, height: 1792, bg: '#ffffff', resize: 'contain' },
{ name: 'favicon', width: 32, height: 32, bg: 'transparent', resize: 'cover' },
];
for (const asset of assets) {
try {
const result = await generateImageAsync(
{ projectRoot: process.cwd(), cacheType: 'expo' },
{
src: inputPath,
name: asset.name,
width: asset.width,
height: asset.height,
resizeMode: asset.resize,
backgroundColor: asset.bg
}
);
await fs.writeFile(
path.join(outputDir, `${asset.name}.png`),
result.source
);
console.log(`✓ ${asset.name}.png (${asset.width}x${asset.height})`);
} catch (error) {
console.log(`✗ ${asset.name}: ${error.message}`);
}
}
console.log(`\n Done! Check: ${outputDir}`);
console.log(`\n Update app.json:`);
console.log(`"icon": "${outputDir}/icon-1024.png"`);
console.log(`"splash": {
"image": "${outputDir}/splash-android.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}`);
rl.close();
}
generateAssets().catch(error => {
console.error('Error:', error.message);
rl.close();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment