diff --git a/gen_hero.py b/gen_hero.py new file mode 100644 index 0000000..b9c6c5f --- /dev/null +++ b/gen_hero.py @@ -0,0 +1,88 @@ +"""Generate a world-class hero image for Pledge Now, Pay Later.""" +import sys, io, os, time +sys.stdout.reconfigure(encoding='utf-8') + +from google import genai +from google.genai import types +from PIL import Image + +client = genai.Client(api_key="AIzaSyCHnesXLjPw-UgeZaQotut66bgjFdvy12E") +MODEL = "gemini-3-pro-image-preview" + +OUT_DIR = "pledge-now-pay-later/public/images/landing" +BRAND_DIR = "pledge-now-pay-later/brand/photography" + +PROMPTS = [ + # Concept 1: Phone notification at gala + """Photorealistic close-up documentary photograph. +A woman's hand holding a smartphone at a charity gala dinner table. The phone screen glows bright showing a green checkmark payment confirmation notification. Her hand is in sharp focus. +Background: beautifully soft bokeh of warm golden tungsten chandelier lights, round dinner tables with white tablecloths, blurred guests in formal attire. A glass of water and edge of a plate visible on the dark wooden table. +British South Asian woman, dark navy blazer sleeve, simple gold bracelet on wrist. +Shot on Sony A7IV, 50mm f/1.4, available warm tungsten light. Extremely shallow depth of field. Documentary candid style, warm color temperature. +The mood: quiet triumph. The pledge came through. Money in the bank. +Portrait orientation, 4:5 aspect ratio. Professional editorial photography.""", + + # Concept 2: Dashboard laptop at desk after event + """Photorealistic documentary photograph of a charity manager's desk, end of a successful fundraising evening. +An open MacBook showing a dashboard with bright green progress bars at 100 percent and payment confirmations. The laptop screen glows in the dim warm light. A phone beside it shows a WhatsApp message. A cup of tea, reading glasses folded on the desk. +The setting is a quiet office after an event. Warm desk lamp casting golden light, a window showing evening London skyline with city lights in the far background, completely out of focus. +British South Asian woman in her 40s, slight smile, looking at the laptop screen, only her silhouette partially visible from the side. Not looking at camera. +Shot on Leica Q2, 28mm f/1.7, available warm lamp light and blue window light. Shallow depth of field. Documentary candid style. +The mood: satisfied relief. Every pledge tracked. Every penny accounted for. +Portrait orientation, 4:5 aspect ratio. Professional editorial photography.""", + + # Concept 3: The green glow moment + """Photorealistic documentary photograph capturing the exact moment of success. +A close-up of a smartphone in a woman's hand, the screen casting a soft green glow on her face from below. She is standing at the edge of a busy charity gala ballroom. The phone shows a payment dashboard with multiple green indicators. +Background: a sweeping view of a London hotel ballroom with crystal chandeliers creating beautiful warm bokeh circles. Guests at round tables, energy and generosity in the air. All beautifully blurred. +British woman wearing a dark structured blazer, hijab, professional. She holds the phone at mid-chest level, glancing down at it with a subtle knowing expression. Candid, not posed. +Shot on Canon R5, 85mm f/1.2, warm tungsten available light. Extremely shallow depth of field. The phone and her nearest hand are razor sharp, face slightly soft, background completely dissolved into warm golden bokeh circles. +Cinematic documentary photography. The feeling: this is what success looks like. Quiet. Precise. Money in the bank. +Portrait orientation, 4:5 aspect ratio. Professional editorial photography.""", +] + +os.makedirs(OUT_DIR, exist_ok=True) +os.makedirs(BRAND_DIR, exist_ok=True) + +results = [] +for i, prompt in enumerate(PROMPTS): + for attempt in range(3): + try: + print(f"\n--- Generating concept {i+1}/3 (attempt {attempt+1}) ---") + response = client.models.generate_content( + model=MODEL, + contents=prompt, + config=types.GenerateContentConfig( + response_modalities=["IMAGE", "TEXT"], + temperature=1.0, + ), + ) + + found = False + for part in response.candidates[0].content.parts: + if part.inline_data and part.inline_data.mime_type.startswith("image/"): + img = Image.open(io.BytesIO(part.inline_data.data)) + fname = f"hero-concept-{i+1}.jpg" + path = os.path.join(OUT_DIR, fname) + if img.mode != "RGB": + img = img.convert("RGB") + img.save(path, "JPEG", quality=92, optimize=True) + sz = os.path.getsize(path) + print(f" OK {fname} -- {img.size[0]}x{img.size[1]}, {sz//1024}KB") + results.append((fname, img.size, sz)) + found = True + break + if found: + break + else: + print(" No image in response, retrying...") + + except Exception as e: + emsg = str(e).encode('ascii', 'replace').decode('ascii') + print(f" Error: {emsg}") + if attempt < 2: + time.sleep(5) + +print(f"\n=== Generated {len(results)}/3 hero concepts ===") +for fname, size, sz in results: + print(f" {fname}: {size[0]}x{size[1]}, {sz//1024}KB") diff --git a/optimize_images.py b/optimize_images.py new file mode 100644 index 0000000..174adcc --- /dev/null +++ b/optimize_images.py @@ -0,0 +1,82 @@ +"""Optimize all landing images: resize + compress + strip EXIF. +Also set hero-concept-1.jpg as the new hero image.""" +import sys, os, shutil +sys.stdout.reconfigure(encoding='utf-8') +from PIL import Image + +IMG_DIR = "pledge-now-pay-later/public/images/landing" +BRAND_DIR = "pledge-now-pay-later/brand/photography" + +# Max dimensions per image type +# Portrait (4:5 or 1:1) → max 1000px long side +# Landscape (16:9) → max 1200px wide +MAX_LANDSCAPE = 1200 +MAX_PORTRAIT = 1000 +QUALITY = 80 + +def optimize(path, max_long_side): + """Resize + compress + strip EXIF. Returns (old_size, new_size).""" + old_size = os.path.getsize(path) + img = Image.open(path) + + # Strip EXIF by creating new image + if img.mode != "RGB": + img = img.convert("RGB") + + # Resize if larger than max + w, h = img.size + long_side = max(w, h) + if long_side > max_long_side: + ratio = max_long_side / long_side + new_w = int(w * ratio) + new_h = int(h * ratio) + img = img.resize((new_w, new_h), Image.LANCZOS) + + # Save with progressive JPEG, quality 80, optimized + img.save(path, "JPEG", quality=QUALITY, optimize=True, progressive=True) + new_size = os.path.getsize(path) + return old_size, new_size, img.size + +# Step 1: Set hero-concept-1 as the main hero +hero_src = os.path.join(IMG_DIR, "hero-concept-1.jpg") +hero_dst = os.path.join(IMG_DIR, "00-hero.jpg") +if os.path.exists(hero_src): + shutil.copy2(hero_src, hero_dst) + # Also copy to brand dir + shutil.copy2(hero_src, os.path.join(BRAND_DIR, "00-hero.jpg")) + print(f"Set hero: hero-concept-1.jpg -> 00-hero.jpg") + +# Step 2: Clean up concept images +for f in ["hero-concept-1.jpg", "hero-concept-2.jpg", "hero-concept-3.jpg"]: + p = os.path.join(IMG_DIR, f) + if os.path.exists(p): + os.remove(p) + print(f"Cleaned: {f}") + +# Step 3: Optimize all images +total_old = 0 +total_new = 0 + +for fname in sorted(os.listdir(IMG_DIR)): + if not fname.endswith(".jpg"): + continue + path = os.path.join(IMG_DIR, fname) + img = Image.open(path) + w, h = img.size + img.close() + + # Determine max size based on orientation + if w > h: + max_side = MAX_LANDSCAPE # landscape + else: + max_side = MAX_PORTRAIT # portrait or square + + old_size, new_size, final_dims = optimize(path, max_side) + total_old += old_size + total_new += new_size + saved_pct = (1 - new_size / old_size) * 100 if old_size > 0 else 0 + print(f" {fname:45s} {final_dims[0]:>5d}x{final_dims[1]:<5d} {old_size//1024:>4d}KB -> {new_size//1024:>4d}KB ({saved_pct:+.0f}%)") + +print(f"\n{'='*60}") +print(f"Total: {total_old//1024}KB -> {total_new//1024}KB ({(1 - total_new/total_old)*100:.0f}% reduction)") +print(f"{'='*60}") diff --git a/pledge-now-pay-later/Dockerfile b/pledge-now-pay-later/Dockerfile index eed254d..393cc54 100644 --- a/pledge-now-pay-later/Dockerfile +++ b/pledge-now-pay-later/Dockerfile @@ -15,12 +15,16 @@ RUN npm run build FROM base AS runner WORKDIR /app ENV NODE_ENV=production +# sharp needs these native libs for image optimization +RUN apk add --no-cache libc6-compat RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs COPY --from=builder /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder /app/prisma ./prisma +# sharp is bundled in standalone output when installed +ENV NEXT_SHARP_PATH=/app/node_modules/sharp USER nextjs EXPOSE 3000 ENV PORT=3000 diff --git a/pledge-now-pay-later/brand/photography/00-hero.jpg b/pledge-now-pay-later/brand/photography/00-hero.jpg new file mode 100644 index 0000000..df9f555 Binary files /dev/null and b/pledge-now-pay-later/brand/photography/00-hero.jpg differ diff --git a/pledge-now-pay-later/next.config.mjs b/pledge-now-pay-later/next.config.mjs index 8c8bab6..569c1c8 100644 --- a/pledge-now-pay-later/next.config.mjs +++ b/pledge-now-pay-later/next.config.mjs @@ -1,6 +1,12 @@ /** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone", + images: { + formats: ["image/webp"], + deviceSizes: [640, 828, 1080, 1200], + imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], + minimumCacheTTL: 31536000, // 1 year — images are immutable, filename changes on update + }, }; export default nextConfig; diff --git a/pledge-now-pay-later/package-lock.json b/pledge-now-pay-later/package-lock.json index 0958e57..64c7752 100644 --- a/pledge-now-pay-later/package-lock.json +++ b/pledge-now-pay-later/package-lock.json @@ -28,6 +28,7 @@ "qrcode": "^1.5.4", "react": "^18", "react-dom": "^18", + "sharp": "^0.34.5", "stripe": "^20.4.0", "tailwind-merge": "^3.5.0", "zod": "^4.3.6" @@ -213,7 +214,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -786,6 +786,471 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2977,6 +3442,15 @@ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", "license": "MIT" }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -6803,7 +7277,6 @@ "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -6872,6 +7345,50 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/pledge-now-pay-later/package.json b/pledge-now-pay-later/package.json index 88cb47a..6a34a12 100644 --- a/pledge-now-pay-later/package.json +++ b/pledge-now-pay-later/package.json @@ -29,6 +29,7 @@ "qrcode": "^1.5.4", "react": "^18", "react-dom": "^18", + "sharp": "^0.34.5", "stripe": "^20.4.0", "tailwind-merge": "^3.5.0", "zod": "^4.3.6" diff --git a/pledge-now-pay-later/public/images/landing/00-hero.jpg b/pledge-now-pay-later/public/images/landing/00-hero.jpg new file mode 100644 index 0000000..f19fa6a Binary files /dev/null and b/pledge-now-pay-later/public/images/landing/00-hero.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/01-main-dashboard-hero.jpg b/pledge-now-pay-later/public/images/landing/01-main-dashboard-hero.jpg index 30e8139..312f644 100644 Binary files a/pledge-now-pay-later/public/images/landing/01-main-dashboard-hero.jpg and b/pledge-now-pay-later/public/images/landing/01-main-dashboard-hero.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/02-main-charity-manager-card.jpg b/pledge-now-pay-later/public/images/landing/02-main-charity-manager-card.jpg index 85c5efc..b58cebf 100644 Binary files a/pledge-now-pay-later/public/images/landing/02-main-charity-manager-card.jpg and b/pledge-now-pay-later/public/images/landing/02-main-charity-manager-card.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/03-main-fundraiser-card.jpg b/pledge-now-pay-later/public/images/landing/03-main-fundraiser-card.jpg index 2ac6169..aa69293 100644 Binary files a/pledge-now-pay-later/public/images/landing/03-main-fundraiser-card.jpg and b/pledge-now-pay-later/public/images/landing/03-main-fundraiser-card.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/04-main-volunteer-card.jpg b/pledge-now-pay-later/public/images/landing/04-main-volunteer-card.jpg index 1ecf3df..c15d105 100644 Binary files a/pledge-now-pay-later/public/images/landing/04-main-volunteer-card.jpg and b/pledge-now-pay-later/public/images/landing/04-main-volunteer-card.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/05-main-org-card.jpg b/pledge-now-pay-later/public/images/landing/05-main-org-card.jpg index 10fdb71..bb5a945 100644 Binary files a/pledge-now-pay-later/public/images/landing/05-main-org-card.jpg and b/pledge-now-pay-later/public/images/landing/05-main-org-card.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/06-main-pledge-form.jpg b/pledge-now-pay-later/public/images/landing/06-main-pledge-form.jpg index 2cfcdb1..f5882b9 100644 Binary files a/pledge-now-pay-later/public/images/landing/06-main-pledge-form.jpg and b/pledge-now-pay-later/public/images/landing/06-main-pledge-form.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/07-main-schedule-step.jpg b/pledge-now-pay-later/public/images/landing/07-main-schedule-step.jpg index 85a6764..e27ffee 100644 Binary files a/pledge-now-pay-later/public/images/landing/07-main-schedule-step.jpg and b/pledge-now-pay-later/public/images/landing/07-main-schedule-step.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/08-charities-hero.jpg b/pledge-now-pay-later/public/images/landing/08-charities-hero.jpg index 1cf76c3..635e862 100644 Binary files a/pledge-now-pay-later/public/images/landing/08-charities-hero.jpg and b/pledge-now-pay-later/public/images/landing/08-charities-hero.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/09-charities-amount-selection.jpg b/pledge-now-pay-later/public/images/landing/09-charities-amount-selection.jpg index b752b44..a5703e3 100644 Binary files a/pledge-now-pay-later/public/images/landing/09-charities-amount-selection.jpg and b/pledge-now-pay-later/public/images/landing/09-charities-amount-selection.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/10-charities-whatsapp.jpg b/pledge-now-pay-later/public/images/landing/10-charities-whatsapp.jpg index 08f5a14..6ff8eb3 100644 Binary files a/pledge-now-pay-later/public/images/landing/10-charities-whatsapp.jpg and b/pledge-now-pay-later/public/images/landing/10-charities-whatsapp.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/11-fundraisers-hero.jpg b/pledge-now-pay-later/public/images/landing/11-fundraisers-hero.jpg index ee2acd4..edc3c6f 100644 Binary files a/pledge-now-pay-later/public/images/landing/11-fundraisers-hero.jpg and b/pledge-now-pay-later/public/images/landing/11-fundraisers-hero.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/12-fundraisers-redirect.jpg b/pledge-now-pay-later/public/images/landing/12-fundraisers-redirect.jpg index fde127f..3b3c4ff 100644 Binary files a/pledge-now-pay-later/public/images/landing/12-fundraisers-redirect.jpg and b/pledge-now-pay-later/public/images/landing/12-fundraisers-redirect.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/13-fundraisers-dashboard.jpg b/pledge-now-pay-later/public/images/landing/13-fundraisers-dashboard.jpg index 3121653..8723fb4 100644 Binary files a/pledge-now-pay-later/public/images/landing/13-fundraisers-dashboard.jpg and b/pledge-now-pay-later/public/images/landing/13-fundraisers-dashboard.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/14-volunteers-hero.jpg b/pledge-now-pay-later/public/images/landing/14-volunteers-hero.jpg index 7b33ac8..ff8f46d 100644 Binary files a/pledge-now-pay-later/public/images/landing/14-volunteers-hero.jpg and b/pledge-now-pay-later/public/images/landing/14-volunteers-hero.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/15-volunteers-phone-stats.jpg b/pledge-now-pay-later/public/images/landing/15-volunteers-phone-stats.jpg index 12a65c5..13124e0 100644 Binary files a/pledge-now-pay-later/public/images/landing/15-volunteers-phone-stats.jpg and b/pledge-now-pay-later/public/images/landing/15-volunteers-phone-stats.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/16-volunteers-leaderboard.jpg b/pledge-now-pay-later/public/images/landing/16-volunteers-leaderboard.jpg index b699bf7..cfc1fef 100644 Binary files a/pledge-now-pay-later/public/images/landing/16-volunteers-leaderboard.jpg and b/pledge-now-pay-later/public/images/landing/16-volunteers-leaderboard.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/17-orgs-hero-boardroom.jpg b/pledge-now-pay-later/public/images/landing/17-orgs-hero-boardroom.jpg index 7601542..7893dad 100644 Binary files a/pledge-now-pay-later/public/images/landing/17-orgs-hero-boardroom.jpg and b/pledge-now-pay-later/public/images/landing/17-orgs-hero-boardroom.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/18-orgs-pipeline.jpg b/pledge-now-pay-later/public/images/landing/18-orgs-pipeline.jpg index 6f4d0ce..e83651f 100644 Binary files a/pledge-now-pay-later/public/images/landing/18-orgs-pipeline.jpg and b/pledge-now-pay-later/public/images/landing/18-orgs-pipeline.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/19-orgs-instalment-schedule.jpg b/pledge-now-pay-later/public/images/landing/19-orgs-instalment-schedule.jpg index 70ab437..c7dabb6 100644 Binary files a/pledge-now-pay-later/public/images/landing/19-orgs-instalment-schedule.jpg and b/pledge-now-pay-later/public/images/landing/19-orgs-instalment-schedule.jpg differ diff --git a/pledge-now-pay-later/public/images/landing/20-orgs-laptop-desk.jpg b/pledge-now-pay-later/public/images/landing/20-orgs-laptop-desk.jpg index f84b781..41a6011 100644 Binary files a/pledge-now-pay-later/public/images/landing/20-orgs-laptop-desk.jpg and b/pledge-now-pay-later/public/images/landing/20-orgs-laptop-desk.jpg differ diff --git a/pledge-now-pay-later/src/app/page.tsx b/pledge-now-pay-later/src/app/page.tsx index f110d40..1b847ce 100644 --- a/pledge-now-pay-later/src/app/page.tsx +++ b/pledge-now-pay-later/src/app/page.tsx @@ -101,8 +101,8 @@ export default function HomePage() {