Fix payment flexibility quote length and orphan word
- Shorten quote 03 from 'Can I split it across a few months?' to 'Can I pay monthly?' for column symmetry - Add nbsp between 'money' and 'arriving' to prevent orphan line break
This commit is contained in:
271
pledge-now-pay-later/scripts/generate-brand-photos-2.ts
Normal file
271
pledge-now-pay-later/scripts/generate-brand-photos-2.ts
Normal file
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* Generate 30 MORE brand photography assets — Batch 2
|
||||
* Run: npx tsx scripts/generate-brand-photos-2.ts
|
||||
*/
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import dotenv from "dotenv";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const API_KEY = process.env.GEMINI_API_KEY;
|
||||
if (!API_KEY) { console.error("Missing GEMINI_API_KEY"); process.exit(1); }
|
||||
|
||||
const MODEL = "gemini-3-pro-image-preview";
|
||||
const ENDPOINT = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent?key=${API_KEY}`;
|
||||
const OUTPUT_DIR = path.join(process.cwd(), "public/images/brand");
|
||||
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||
|
||||
const STYLE = `Photorealistic documentary photography. Sony A7III, shallow depth of field, available light. Candid fly-on-the-wall. Nobody looks at camera. No stock aesthetic. No staged poses. No alcohol or wine ever. No visible text or watermarks. Young modern British-Muslim community. South Asian and Arab features.`;
|
||||
|
||||
interface Photo { filename: string; prompt: string; }
|
||||
|
||||
const PHOTOS: Photo[] = [
|
||||
// ═══════════════════════════════════════════
|
||||
// RAMADAN & IFTAR (5 photos)
|
||||
// ═══════════════════════════════════════════
|
||||
{
|
||||
filename: "ramadan-01-iftar-table.jpg",
|
||||
prompt: `16:9 landscape. A long communal iftar table in a mosque hall, moments before breaking fast. Dozens of place settings — each with a paper plate, three dates, a cup of water, and a samosa. The table stretches into the distance. A few early arrivals are seated, hands in dua (prayer), eyes closed. Late afternoon golden light through high windows. The anticipation of iftar. 35mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "ramadan-02-breaking-fast.jpg",
|
||||
prompt: `16:9 landscape. The exact moment of breaking fast at a community iftar. Close-up of a young British-Muslim man biting into a date, eyes half-closed with relief and gratitude. Beside him, another person is drinking water. Paper plates with samosas and fruit. The table is packed with people shoulder to shoulder. Warm overhead light. The beautiful ordinariness of this sacred moment. 85mm f/1.4. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "ramadan-03-taraweeh-crowd.jpg",
|
||||
prompt: `16:9 landscape. Overhead angle looking down on rows and rows of men in sujood (prostration) during taraweeh prayers in a packed mosque. White, grey, and coloured thobes and prayer caps visible from above. Deep green carpet with geometric pattern. The symmetry is breathtaking. Shot from a balcony above. Warm mosque lighting. 24mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "ramadan-04-suhoor-kitchen.jpg",
|
||||
prompt: `16:9 landscape. 3am suhoor in a British-Muslim family kitchen. A mother in a dressing gown and loose hijab is making eggs at the stove while a teenage son sits at the kitchen table eating cereal, still half-asleep. A clock on the wall shows 3:15. The kitchen is lit by the warm glow of a single pendant light, darkness visible through the window. The quiet ritual of pre-dawn eating. 35mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "ramadan-05-charity-collection.jpg",
|
||||
prompt: `16:9 landscape. Outside a mosque after taraweeh prayer, a young British-Muslim volunteer in a charity bib holding a collection bucket. People are filing out of the mosque entrance, some dropping notes and coins in as they pass. The volunteer is saying thank you to an older man who just donated. Night time, the mosque entrance is warmly lit, the street is dark. 50mm f/1.8. ${STYLE}`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// OUTDOOR FUNDRAISING (5 photos)
|
||||
// ═══════════════════════════════════════════
|
||||
{
|
||||
filename: "outdoor-01-sponsored-walk.jpg",
|
||||
prompt: `16:9 landscape. A group of 8-10 young British-Muslim men and women on a charity sponsored walk through a park. They're in matching charity t-shirts, some in hijabs, walking together on a path with autumn trees. One person is holding a small charity banner. They're mid-conversation, laughing, energetic. Overcast British sky. Other park walkers in the background. The camaraderie of collective effort. 35mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "outdoor-02-street-collection.jpg",
|
||||
prompt: `16:9 landscape. A young British-Muslim woman in hijab and a charity tabard standing on a busy British high street with a collection bucket and clipboard. She's approaching a passer-by with a friendly smile. Behind her: a Boots pharmacy, a bus stop, and overcast sky. Red double-decker bus partially visible. The courage of street fundraising. Shallow depth of field on her. 85mm f/1.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "outdoor-03-funrun-finish.jpg",
|
||||
prompt: `16:9 landscape. A young British-Muslim woman in hijab crossing the finish line of a charity fun run, arms spread wide in triumph. She's wearing a running vest with a race number pinned to it. Her face shows exhausted joy. Spectators on either side cheering. A finish line banner overhead. Other runners behind her. Morning light. The physical effort of giving. 85mm f/1.4 with motion blur on the background. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "outdoor-04-cake-sale.jpg",
|
||||
prompt: `16:9 landscape. A charity bake sale table outside a community centre. Two young British-Muslim women, one in hijab, arranging homemade cakes, cupcakes, and brownies on a trestle table with a paper tablecloth. Price labels handwritten on cards. A small queue of people waiting. A child pointing at a chocolate cake. Overcast daylight. The grassroots simplicity of community fundraising. 35mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "outdoor-05-carwash-fundraiser.jpg",
|
||||
prompt: `16:9 landscape. Young British-Muslim volunteers doing a charity car wash in a mosque car park. Three teenagers in matching t-shirts, soaking wet and laughing, washing a silver car with sponges and buckets. Soapy water on the tarmac. A handwritten "Charity Car Wash £5" sign on cardboard. Another car waiting behind. Overcast British summer day. Pure joy and chaos. 35mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// IMPACT & GRATITUDE (5 photos)
|
||||
// ═══════════════════════════════════════════
|
||||
{
|
||||
filename: "impact-01-food-bank.jpg",
|
||||
prompt: `16:9 landscape. Inside a community food bank in a mosque basement. Metal shelving units stacked with tinned food, rice bags, and pasta. A young British-Muslim volunteer is handing a filled carrier bag to an older woman. Both of them have quiet, dignified expressions — no pity, no performance. Fluorescent overhead light. A weighing scale on the counter. The serious work of feeding people. 35mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "impact-02-thank-you-letter.jpg",
|
||||
prompt: `3:4 portrait. Close-up of a handwritten thank-you card lying on a desk, partially visible. A young British-Muslim charity worker's hand is holding it, reading it. We see the card from a slight angle — a child's drawing and handwriting visible but not fully legible. The person's other hand rests on the desk near a mug of tea. Warm desk lamp light. The quiet reward of charity work. 50mm macro f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "impact-03-cheque-presentation.jpg",
|
||||
prompt: `16:9 landscape. A small informal cheque presentation in a charity office. A young British-Muslim fundraiser handing over a large novelty cheque to the charity director — both in smart-casual clothes, shaking hands with one hand and holding the cheque between them. Two other team members behind them, clapping. A plain office wall with a charity logo framed print. Not a staged PR shot — a genuine moment. Overhead fluorescent light. 35mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "impact-04-building-project.jpg",
|
||||
prompt: `16:9 landscape. A group of British-Muslim community members standing in front of a partially renovated community building, looking up at the progress. Hard hats on some of them, high-vis vests. Scaffolding on the building facade. One person is pointing upward at the work. A sense of pride and progress. Overcast sky. The tangible result of fundraising — bricks and mortar. 24mm f/4.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "impact-05-classroom-abroad.jpg",
|
||||
prompt: `16:9 landscape. A video call on a laptop screen showing children in a classroom abroad, waving at the camera. The laptop is on a desk in a British charity office. A young British-Muslim woman in hijab is sitting in front of the laptop, hand raised waving back, with a huge genuine smile. The connection between giver and receiver, bridged by technology. Warm screen glow mixed with office fluorescent. 50mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// YOUTH & NEXT GENERATION (5 photos)
|
||||
// ═══════════════════════════════════════════
|
||||
{
|
||||
filename: "youth-01-workshop.jpg",
|
||||
prompt: `16:9 landscape. A charity leadership workshop in a community centre. Young British-Muslim attendees, late teens and early 20s, sitting at desks arranged in a U-shape. A facilitator at a flipchart. One young woman in hijab is asking a question with her hand half-raised. Post-it notes on the wall behind. Notebooks and water bottles on desks. Fluorescent light. Engaged, not passive. 24mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "youth-02-mentoring.jpg",
|
||||
prompt: `16:9 landscape. A one-on-one mentoring session in a quiet corner of a community centre. An older British-Muslim man in his 40s, beard with flecks of grey, sitting across from a teenage boy. The man is leaning forward, hands clasped, listening intently. The teenager is speaking, gesturing. Between them on a small table: two cups of tea. A window with grey sky behind. The gift of time and attention. 85mm f/1.4. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "youth-03-childrens-class.jpg",
|
||||
prompt: `16:9 landscape. A weekend Islamic school class in a community centre. Children aged 7-10 sitting on the floor in a semi-circle, some in traditional clothing. A young female teacher in hijab sitting at their level, holding up a picture book. The children are captivated. Colourful wall displays behind — children's artwork, Arabic alphabet posters. Bright fluorescent light. The investment in the next generation. 35mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "youth-04-uni-stall.jpg",
|
||||
prompt: `16:9 landscape. A charity fundraising stall at a British university freshers' fair. Two young British-Muslim students manning the stall — a man in a hoodie and a woman in hijab. Their table has leaflets, a banner, collection tins, and charity wristbands. A fresher student has stopped to look at a leaflet. Busy indoor hall with other stalls blurred behind. Bright harsh indoor lighting. The start of a volunteer journey. 35mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "youth-05-award-ceremony.jpg",
|
||||
prompt: `16:9 landscape. A young British-Muslim woman in hijab receiving a community volunteer award on a small stage. She's holding a framed certificate, looking down at it with a humble smile. A small audience of community members clapping in the foreground, some holding phones up. A simple stage setup — a table, a microphone, a charity banner. Community hall setting. The recognition of quiet dedication. 85mm f/1.8. ${STYLE}`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// MODERN CHARITY WORK (5 photos)
|
||||
// ═══════════════════════════════════════════
|
||||
{
|
||||
filename: "modern-01-podcast-recording.jpg",
|
||||
prompt: `16:9 landscape. Two young British-Muslim men recording a charity podcast in a makeshift studio — a small room with foam panels on the wall. Both wearing headphones, sitting at a desk with microphones on boom arms. One is mid-sentence, gesturing. Laptops open in front of them (screens not visible). A charity logo sticker on one of the laptops. Warm desk lamp mixed with overhead light. The new age of charity storytelling. 35mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "modern-02-coworking-charity.jpg",
|
||||
prompt: `16:9 landscape. Young British-Muslim charity workers in a modern coworking space. Three people at a long shared desk — one woman in hijab on a video call (laptop screen not visible), one man typing on a keyboard, another reviewing printed spreadsheets. Plants on the desk, coffee cups, a branded charity water bottle. Large windows with grey London sky. The professionalisation of small charities. 35mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "modern-03-graphic-design.jpg",
|
||||
prompt: `3:4 portrait. Over-the-shoulder shot of a young British-Muslim man at a desk, working on charity marketing materials on a large monitor (screen content blurred/not readable). His hand is on a mouse. Beside the monitor: a mood board pinned to a corkboard with colour swatches, logo printouts, and inspiration photos. A graphics tablet beside the keyboard. Evening, dark window reflecting the screen. Creative charity work. 50mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "modern-04-whatsapp-group.jpg",
|
||||
prompt: `3:4 portrait. Close-up of a young British-Muslim man's hands holding a phone. He's sitting on a London Underground tube train (visible through the window: dark tunnel, orange handrails). The phone screen shows a messaging app with multiple unread messages (screen content blurred, not readable). He's mid-scroll with his thumb. Rush hour — other commuters blurred. The always-on reality of charity coordination. 85mm f/1.4. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "modern-05-zoom-trustees.jpg",
|
||||
prompt: `16:9 landscape. A laptop on a dining table at home showing a video call grid of 6 people — a charity trustees meeting (faces small and blurred, not identifiable). A young British-Muslim woman in hijab sits in front of the laptop, her notebook open beside it with handwritten meeting notes. A cup of tea, a pen. Evening — warm pendant light above, dark window behind. The unglamorous governance of charity. 50mm f/2.0. ${STYLE}`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// TEXTURE & DETAIL SHOTS (5 photos)
|
||||
// ═══════════════════════════════════════════
|
||||
{
|
||||
filename: "detail-01-donation-jar.jpg",
|
||||
prompt: `3:4 portrait. Close-up of a glass donation jar on a shop counter, half-full of coins and a few folded notes. The jar has a simple printed label saying "Charity" (no other text). Behind it, blurred: the warm interior of a small British-Asian grocery shop — shelves of spices, packets of lentils. The shopkeeper's hand is just visible dropping a coin in. Warm tungsten light. The everyday generosity of small business. 85mm macro f/2.0. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "detail-02-prayer-beads.jpg",
|
||||
prompt: `3:4 portrait. Close-up of an elderly man's weathered hands holding wooden prayer beads (tasbih), resting on his knee. He's sitting in a mosque after prayer. His white thobe sleeve is visible. The green mosque carpet blurred beneath. Soft natural light from a nearby window. A lifetime of faith in two hands. 85mm macro f/1.4. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "detail-03-shoes-mosque.jpg",
|
||||
prompt: `16:9 landscape. Dozens of pairs of shoes arranged on shelving racks outside a mosque prayer hall entrance. Trainers, dress shoes, sandals, children's shoes — all mixed together. The mosque doorway is visible with warm light inside. A pair of tiny children's wellies sits among the adult shoes. The diversity of a congregation told through their footwear. 35mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "detail-04-fundraising-thermometer.jpg",
|
||||
prompt: `3:4 portrait. A hand-painted fundraising thermometer chart on a large piece of card, mounted on a community centre wall. The "mercury" is painted red and filled to about 75% of the target. At the top: a target amount (numbers blurred). Around the base of the chart: small stars with donor names (not readable). Blu-tack marks on the wall around it. Fluorescent light. The lo-fi optimism of community fundraising. 50mm f/2.8. ${STYLE}`,
|
||||
},
|
||||
{
|
||||
filename: "detail-05-langar-trays.jpg",
|
||||
prompt: `16:9 landscape. Overhead shot of a long table being set with food for a community meal. Foil trays of biryani, large bowls of salad, stacks of naan bread, jugs of water, and paper plates. Hands from multiple people are visible placing items. The abundance and care of communal feeding. Shot from directly above. Bright fluorescent community hall light. 24mm f/4.0 from above. ${STYLE}`,
|
||||
},
|
||||
];
|
||||
|
||||
// ─── CONCURRENT GENERATION ENGINE ──────────────────────────
|
||||
|
||||
async function generateOne(spec: Photo): Promise<boolean> {
|
||||
const outPath = path.join(OUTPUT_DIR, spec.filename);
|
||||
const t0 = Date.now();
|
||||
|
||||
try {
|
||||
const res = await fetch(ENDPOINT, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
contents: [{ parts: [{ text: `Generate a photorealistic photograph. ${spec.prompt}` }] }],
|
||||
generationConfig: { responseModalities: ["IMAGE", "TEXT"] },
|
||||
}),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const err = await res.text();
|
||||
console.error(` ❌ ${spec.filename} — API ${res.status}: ${err.slice(0, 150)}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const data: any = await res.json();
|
||||
const parts = data.candidates?.[0]?.content?.parts;
|
||||
const imgPart = parts?.find((p: any) => p.inlineData?.mimeType?.startsWith("image/"));
|
||||
|
||||
if (!imgPart) {
|
||||
const textPart = parts?.find((p: any) => p.text);
|
||||
console.error(` ❌ ${spec.filename} — No image${textPart ? ": " + textPart.text.slice(0, 100) : ""}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const buf = Buffer.from(imgPart.inlineData.data, "base64");
|
||||
fs.writeFileSync(outPath, buf);
|
||||
const ms = Date.now() - t0;
|
||||
console.log(` ✅ ${spec.filename} — ${(buf.length / 1024).toFixed(0)}KB (${(ms / 1000).toFixed(1)}s)`);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.error(` ❌ ${spec.filename} — ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const BATCH_SIZE = 10;
|
||||
const batches: Photo[][] = [];
|
||||
|
||||
for (let i = 0; i < PHOTOS.length; i += BATCH_SIZE) {
|
||||
batches.push(PHOTOS.slice(i, i + BATCH_SIZE));
|
||||
}
|
||||
|
||||
console.log("═══════════════════════════════════════════════════════");
|
||||
console.log(" PNPL Brand Photography — Batch 2 (30 more)");
|
||||
console.log(` Model: ${MODEL}`);
|
||||
console.log(` Strategy: ${batches.length} batches × ${BATCH_SIZE} concurrent`);
|
||||
console.log(` Output: ${OUTPUT_DIR}`);
|
||||
console.log("═══════════════════════════════════════════════════════");
|
||||
|
||||
const t0 = Date.now();
|
||||
let success = 0;
|
||||
let failed: Photo[] = [];
|
||||
|
||||
for (let i = 0; i < batches.length; i++) {
|
||||
console.log(`\n⚡ Batch ${i + 1}/${batches.length} — firing ${batches[i].length} requests simultaneously...`);
|
||||
const results = await Promise.allSettled(batches[i].map(p => generateOne(p)));
|
||||
const batchSuccess = results.filter(r => r.status === "fulfilled" && r.value).length;
|
||||
success += batchSuccess;
|
||||
|
||||
// Track failures
|
||||
for (const spec of batches[i]) {
|
||||
if (!fs.existsSync(path.join(OUTPUT_DIR, spec.filename))) {
|
||||
failed.push(spec);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < batches.length - 1) {
|
||||
console.log(` ⏳ 2s cooldown...`);
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
}
|
||||
}
|
||||
|
||||
// Retry failures
|
||||
if (failed.length > 0) {
|
||||
console.log(`\n🔄 Retrying ${failed.length} failures...`);
|
||||
await new Promise(r => setTimeout(r, 3000));
|
||||
|
||||
for (const spec of failed) {
|
||||
const ok = await generateOne(spec);
|
||||
if (ok) success++;
|
||||
await new Promise(r => setTimeout(r, 1500));
|
||||
}
|
||||
}
|
||||
|
||||
const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
|
||||
|
||||
console.log("\n═══════════════════════════════════════════════════════");
|
||||
console.log(` Done: ${success}/${PHOTOS.length} photos in ${elapsed}s`);
|
||||
console.log(` Total brand library: 60 photos`);
|
||||
console.log(` Output: ${OUTPUT_DIR}`);
|
||||
console.log("═══════════════════════════════════════════════════════");
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user