Mirror of awesome-nano-banana-pro-prompts tuned for OpenAI's upcoming
GPT Image 2 (codename "duct-tape"):
- Swap CMS model filter to gpt-image-2 + campaign gpt-image-2-prompts
- i18n.ts: all 16 languages rebranded; rewrite seedancePromo to
cross-promote nano-banana-pro, and whatIs content to reflect
GPT Image 2's actual strengths:
* Pixel-perfect multi-language text rendering (zh/en/ja)
* Cross-image pixel-level consistency
* Commercial-ready illustration quality
* True art style induction
Primary languages (en, zh, zh-TW, ja, ko) hand-translated;
others fall back to English copy (will be refined later)
- markdown-generator: cover image path switched to
gpt-image-2-prompts-cover-{en,zh}.png, arenaUrl points at the
gallery page (the side-by-side arena page doesn't exist yet)
- GitHub Actions:
* update-readme.yml runs on cron 0 0,12 * * * (twice daily
per product request, instead of every 4 hours)
* sync-approved-to-cms.yml wired to gpt-image-2 model
- Cover images, issue templates, docs, LICENSE (year 2026) updated
- Initial 16 README_*.md files generated from live CMS (78 prompts,
44 categories) so the repo renders immediately without waiting
for the first Action run
Secrets the repo needs before the Action runs on the remote:
- CMS_HOST
- CMS_API_KEY
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import fetch from 'node-fetch';
|
|
import type { Media } from './cms-client.js';
|
|
|
|
const CMS_HOST = process.env.CMS_HOST;
|
|
const CMS_API_KEY = process.env.CMS_API_KEY;
|
|
|
|
/**
|
|
* Upload image to CMS
|
|
* @param imageUrl Original image URL
|
|
* @returns CMS media object
|
|
*/
|
|
export async function uploadImageToCMS(imageUrl: string): Promise<Media> {
|
|
try {
|
|
// Download image
|
|
const imageResponse = await fetch(imageUrl);
|
|
if (!imageResponse.ok) {
|
|
throw new Error(`Failed to fetch image: ${imageResponse.statusText}`);
|
|
}
|
|
|
|
const imageBuffer = await imageResponse.arrayBuffer();
|
|
const contentType = imageResponse.headers.get('content-type') || 'image/jpeg';
|
|
|
|
// Extract filename from URL
|
|
const urlParts = imageUrl.split('/');
|
|
const filename = urlParts[urlParts.length - 1].split('?')[0] || 'image.jpg';
|
|
|
|
// Create FormData
|
|
const formData = new FormData();
|
|
const blob = new Blob([imageBuffer], { type: contentType });
|
|
formData.append('file', blob, filename);
|
|
|
|
// Upload to CMS
|
|
const uploadResponse = await fetch(`${CMS_HOST}/api/media`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `users API-Key ${CMS_API_KEY}`,
|
|
},
|
|
body: formData as any,
|
|
});
|
|
|
|
if (!uploadResponse.ok) {
|
|
const errorText = await uploadResponse.text();
|
|
throw new Error(`Failed to upload image: ${uploadResponse.statusText} - ${errorText}`);
|
|
}
|
|
|
|
const data = await uploadResponse.json() as { doc: Media };
|
|
const media = data.doc;
|
|
|
|
return media;
|
|
} catch (error) {
|
|
console.error('Error uploading image to CMS:', error);
|
|
// If upload fails, throw error instead of returning original URL
|
|
// The caller should handle the error
|
|
throw error;
|
|
}
|
|
}
|