diff --git a/gen_personas.py b/gen_personas.py new file mode 100644 index 0000000..cce4a78 --- /dev/null +++ b/gen_personas.py @@ -0,0 +1,84 @@ +"""Generate 4 persona images for the landing page gap-px grid. +All landscape 3:2, documentary candid, consistent warm tone. +Uses gemini-3-pro-image-preview (Nano Banana Pro). +""" +import os, time, sys +from concurrent.futures import ThreadPoolExecutor, as_completed +from google import genai +from google.genai import types + +client = genai.Client(api_key="AIzaSyCHnesXLjPw-UgeZaQotut66bgjFdvy12E") +OUT = "pledge-now-pay-later/public/images/landing" + +PROMPTS = { + "persona-charity-manager.jpg": ( + "A British South Asian woman in her late 40s wearing a navy cardigan and simple hijab, " + "sitting at a desk in a mosque community room. She is looking down at a laptop screen, focused, " + "one hand on the trackpad. Warm tungsten overhead lights. A prayer timetable is pinned to a " + "corkboard on the wall behind her. Stacks of folders and a mug of tea on the desk. " + "Shot on Canon EOS R5, 50mm, f/2.0, available light. Documentary candid, not looking at camera. " + "Warm, grounded, purposeful. 3:2 landscape aspect ratio." + ), + "persona-programme-manager.jpg": ( + "A British Arab man in his mid-30s wearing a smart navy polo shirt, sitting alone at a desk " + "in a modern charity office. He has a laptop open and a printed spreadsheet with highlighted rows " + "beside it. He is writing notes in a Moleskine notebook, pen in hand, concentrating. " + "Natural window light from the left, soft shadows. A monitor showing a campaign calendar is " + "blurred in the background. Clean desk, professional but not corporate. " + "Shot on Canon EOS R5, 35mm, f/1.8, available light. Documentary candid. " + "Organised, calm authority. 3:2 landscape aspect ratio." + ), + "persona-fundraiser.jpg": ( + "A young British Black woman in her mid-20s sitting on a bench in a London park, looking at her " + "phone screen. She wears a casual olive utility jacket and has a tote bag beside her. " + "Overcast British daylight, soft diffused light. Shallow depth of field — bare winter trees and " + "a path blurred behind her. She looks focused and slightly pleased at something on the screen. " + "Shot on Sony A7III, 85mm, f/1.4, natural light. Documentary street photography. " + "Independent, resourceful. 3:2 landscape aspect ratio." + ), + "persona-volunteer.jpg": ( + "A young British South Asian man in his early 20s wearing a lanyard and a plain dark polo shirt, " + "leaning forward at a round table during a charity dinner gala. He is handing a small card " + "to a seated older woman across the table. Warm gala tungsten lighting, white tablecloths, " + "bokeh chandeliers in the background. Other guests are blurred but visible at adjacent tables. " + "Shot on Canon EOS R5, 50mm, f/1.8, available light. Documentary candid event photography. " + "Energetic, helpful. 3:2 landscape aspect ratio." + ), +} + +def generate(filename, prompt): + t0 = time.time() + print(f" [GEN] {filename}...") + try: + resp = client.models.generate_content( + model="gemini-3-pro-image-preview", + contents=prompt, + config=types.GenerateContentConfig( + response_modalities=["TEXT", "IMAGE"], + ), + ) + for part in resp.candidates[0].content.parts: + if part.inline_data: + path = os.path.join(OUT, filename) + with open(path, "wb") as f: + f.write(part.inline_data.data) + sz = os.path.getsize(path) / 1024 + print(f" [OK] {filename} -- {sz:.0f}KB ({time.time()-t0:.1f}s)") + return filename, True + print(f" [FAIL] {filename} -- no image in response") + return filename, False + except Exception as e: + print(f" [FAIL] {filename} -- {e}") + return filename, False + +if __name__ == "__main__": + print(f"Generating {len(PROMPTS)} persona images...") + ok, fail = 0, 0 + # Generate 2 at a time (rate limits) + with ThreadPoolExecutor(max_workers=2) as pool: + futures = {pool.submit(generate, fn, p): fn for fn, p in PROMPTS.items()} + for f in as_completed(futures): + _, success = f.result() + if success: ok += 1 + else: fail += 1 + print(f"\nDone: {ok} ok, {fail} failed") diff --git a/pledge-now-pay-later/public/images/landing/persona-charity-manager.jpg b/pledge-now-pay-later/public/images/landing/persona-charity-manager.jpg new file mode 100644 index 0000000..a473e85 Binary files /dev/null and b/pledge-now-pay-later/public/images/landing/persona-charity-manager.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/persona-fundraiser.jpg b/pledge-now-pay-later/public/images/landing/persona-fundraiser.jpg new file mode 100644 index 0000000..9c9e396 Binary files /dev/null and b/pledge-now-pay-later/public/images/landing/persona-fundraiser.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/persona-programme-manager.jpg b/pledge-now-pay-later/public/images/landing/persona-programme-manager.jpg new file mode 100644 index 0000000..1ebff82 Binary files /dev/null and b/pledge-now-pay-later/public/images/landing/persona-programme-manager.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/persona-volunteer.jpg b/pledge-now-pay-later/public/images/landing/persona-volunteer.jpg new file mode 100644 index 0000000..55b4474 Binary files /dev/null and b/pledge-now-pay-later/public/images/landing/persona-volunteer.jpg differ diff --git a/pledge-now-pay-later/src/app/for/_components/index.tsx b/pledge-now-pay-later/src/app/for/_components/index.tsx index 70bd838..6c3cbfc 100644 --- a/pledge-now-pay-later/src/app/for/_components/index.tsx +++ b/pledge-now-pay-later/src/app/for/_components/index.tsx @@ -27,7 +27,7 @@ export function Footer({ active }: { active?: string }) { { href: "/for/charities", label: "Charities" }, { href: "/for/fundraisers", label: "Fundraisers" }, { href: "/for/volunteers", label: "Volunteers" }, - { href: "/for/organisations", label: "Organisations" }, + { href: "/for/organisations", label: "Programme Managers" }, ] return (