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:
2026-03-04 13:58:42 +08:00
parent 6b71fa227b
commit ef37ca0c18
160 changed files with 6555 additions and 549 deletions

BIN
debug-2550.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

144
gen_kaffarah.py Normal file
View File

@@ -0,0 +1,144 @@
"""
Generate 3 on-brand kaffarah-community.jpg replacements.
Uses anti-AI prompting strategy from cr-brand-style.json.
"""
import sys, io, os, time, json
sys.stdout.reconfigure(encoding='utf-8')
from google import genai
from google.genai import types
from PIL import Image
API_KEY = "AIzaSyCHnesXLjPw-UgeZaQotut66bgjFdvy12E"
MODEL = "gemini-3-pro-image-preview"
OUT = "screenshots/kaffarah-replacements"
os.makedirs(OUT, exist_ok=True)
client = genai.Client(api_key=API_KEY)
# ── ANTI-AI STYLE BLOCK ──
# No camera names, no "golden hour", no emotion words, no "bokeh".
# Describe PHYSICS of light, SPECIFIC objects, ACTIONS not feelings.
STYLE = (
"Raw documentary photograph with visible film grain and slight color noise in the shadows. "
"The color is MUTED — pulled-back saturation, faded dusty quality, blacks slightly lifted, "
"NOT warm amber or orange-tinted. Highlights have a faint yellow-green cast. "
"Shadows lean cool and neutral. "
"Single hard directional light source creating deep shadows on one side. "
"Unlit areas stay DARK, not filled in. "
"The framing is IMPERFECT — a partial figure or object intrudes at one edge of the frame. "
"The subject is slightly off-center. There is foreground obstruction. "
"Skin has visible pores, uneven tone, slight dust. Hair is uncombed. "
"Clothing is thin worn cotton, faded, creased, with visible stitching. "
"The environment is CLUTTERED with real objects at multiple depth planes. "
"NO smooth skin. NO perfect composition. NO warm glow. NO clean backgrounds. "
"Aspect ratio: exactly 2:1 wide landscape. "
)
PROMPTS = {
"kaffarah-v1.jpg": (
STYLE +
"Three children sit on a swept-dirt floor against a crumbling plastered wall eating from "
"shared metal thali plates. A boy around 8 is mid-chew, mouth slightly open, looking "
"sideways at something outside the frame. His faded blue cotton kurta has a torn collar. "
"Next to him a younger girl scoops rice with her right hand, not looking up. Her hair is "
"tangled and hasn't been brushed. Behind them, a wooden charpai with sagging rope webbing, "
"a plastic water jug, and a torn calendar hanging crooked on the wall. Afternoon sun comes "
"through a doorway on the left, casting a hard beam across the floor — the far wall stays "
"in deep shadow. Someone's bare foot and ankle are visible at the bottom-right edge of the "
"frame, cropped off. Dust motes visible in the light beam. The floor has a cracked cement "
"patch and a worn woven mat. Muted desaturated color with visible grain."
),
"kaffarah-v2.jpg": (
STYLE +
"A boy around 6 sits at a rough wooden bench eating rice and dal from a dented steel plate. "
"His hand is in the food, fingers pressing rice together. He is looking down at his plate, "
"not at the camera. His dark hair sticks up on one side where he slept on it. He wears a "
"faded brown cotton shirt buttoned wrong — one side hangs lower than the other. His "
"fingernails have dirt under them. The bench has deep scratches and a water ring stain. "
"Behind him, a plastered wall with a long crack running diagonally, a nail with nothing "
"on it, and a small high window letting in a hard shaft of light from the right. Two "
"other children are visible in the mid-ground, slightly out of focus, also eating. "
"An adult's elbow and forearm in a grey cotton sleeve intrudes into the left edge of "
"frame. On the bench next to the boy: a scratched steel cup with water. The light "
"illuminates only the right side of his face. The left side falls into shadow. "
"Muted color, visible grain, slight chromatic aberration at contrast edges."
),
"kaffarah-v3.jpg": (
STYLE +
"Seen from slightly behind and to the side of a woman in a faded cream dupatta who is "
"setting down a metal plate of food in front of a small child seated on a woven mat. "
"We see the woman's hands and forearms — veins visible, a thin glass bangle on one wrist. "
"The child, about 5, reaches for the plate with both small hands. The child's face is in "
"three-quarter profile, slightly blurred because the focus is on the hands and the plate. "
"The food is simple — a mound of rice, yellow dal, a piece of flatbread folded on the side. "
"The mat has fraying edges and a cigarette burn mark. Against the wall behind them: a "
"stacked row of steel plates, a plastic bag hanging on a nail, peeling turquoise paint "
"revealing brown plaster underneath. Hard afternoon light from a window on the right. "
"Another child sits further back, eating, almost lost in the dim background. A power "
"cable runs along the top of the wall. Muted, slightly desaturated, dusty color. "
"Fine grain throughout. This is a REAL moment, not posed."
),
}
def generate_and_save(filename, prompt, max_retries=3):
for attempt in range(max_retries):
try:
t0 = time.time()
print(f" [{attempt+1}/{max_retries}] {filename}...")
resp = client.models.generate_content(
model=MODEL,
contents=prompt,
config=types.GenerateContentConfig(
response_modalities=["IMAGE", "TEXT"],
temperature=1.0,
),
)
for part in resp.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))
if img.mode != "RGB":
img = img.convert("RGB")
path = os.path.join(OUT, filename)
# Compress to stay under 2 MB
for q in [88, 82, 75, 65]:
img.save(path, "JPEG", quality=q, optimize=True, progressive=True)
if os.path.getsize(path) < 2_000_000:
break
sz = os.path.getsize(path)
print(f" [OK] {filename} -- {img.width}x{img.height}, {sz//1024} KB, {time.time()-t0:.1f}s")
return True
print(f" [WARN] no image in response")
except Exception as e:
print(f" [ERR] {str(e)[:200]}")
if attempt < max_retries - 1:
time.sleep(5 * (attempt + 1))
print(f" [FAIL] {filename}")
return False
if __name__ == "__main__":
print(f"Generating {len(PROMPTS)} kaffarah replacements -> {os.path.abspath(OUT)}\n")
ok = 0
for fn, prompt in PROMPTS.items():
if generate_and_save(fn, prompt):
ok += 1
time.sleep(2)
print(f"\nDone: {ok}/{len(PROMPTS)}")
for f in sorted(os.listdir(OUT)):
sz = os.path.getsize(os.path.join(OUT, f))
print(f" {f} -- {sz//1024} KB")

View File

@@ -0,0 +1,5 @@
node_modules
.next
.git
brand
shots

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,629 @@
{
"totalSessions": 4,
"totalEvents": 1539,
"totalToolCalls": 704,
"totalAgentTurns": 67,
"totalErrors": 0,
"totalBlocked": 0,
"totalTokensIn": 9949,
"totalTokensOut": 65517,
"totalCost": 10.289527999999995,
"toolCounts": {
"bash": 284,
"read": 274,
"write": 23,
"edit": 123
},
"toolDurations": {
"bash": [
80,
22554,
28417,
31752,
12155,
31018,
29238,
23209,
116,
92,
92,
95,
30195,
31334,
31809,
32722,
12438,
12724,
18027,
234,
26520,
15779,
13584,
12063,
11889,
31800,
31495,
114,
26556,
106,
125,
110,
58,
79,
92,
102,
131,
115,
106,
90,
100,
4112,
2374,
122,
87,
2360,
89,
1419,
251,
90,
92,
103,
2365,
75,
304,
122,
567,
774,
104,
782,
175,
702,
163,
238,
1479,
322,
409,
149,
144,
85,
2416,
102,
76,
85,
2385,
111,
108,
108,
2412,
115,
2372,
104,
68,
82,
114,
69,
2386,
86,
63,
82,
2346,
141,
2537,
2387,
2390,
110,
133,
75,
88,
90,
2328,
2356,
2383,
2351,
2370,
2368,
2307,
2332,
2362,
2353,
11793,
2377,
2260,
2275,
3295,
850,
15197,
88,
480,
606,
82,
105,
2303,
2354,
2409,
2333,
2433,
2363,
2285,
1779,
15165,
2401,
2779,
474,
490,
96,
4529,
91,
91,
120,
111,
459,
1155,
4729,
464,
2467,
2397,
2368,
2515,
90,
3085,
461,
2506,
2521,
108,
2433,
5339,
2386,
2349,
2333,
2348,
2340,
10149,
2494,
2452,
2335,
2328,
2417,
2449,
3537,
2386,
15127,
2361,
2321,
4433,
3043,
4861,
3690,
3553,
3867,
10120,
2307,
23217,
2494,
3349,
2354,
7740,
1573,
10377,
92,
93,
76,
1615,
109,
2205,
2273,
600,
48957,
796,
128
],
"read": [
25,
26,
28,
36,
44,
39,
40,
37,
40,
28,
27,
27,
36,
44,
40,
35,
42,
40,
36,
40,
40,
66,
38,
39,
38,
44,
37,
40,
53,
40,
39,
43,
41,
39,
43,
53,
42,
43,
40,
25,
27,
26,
35,
41,
66,
39,
53,
42,
45,
59,
48,
51,
24,
25,
27,
30,
30,
33,
28,
25,
30,
29,
5,
46,
19,
4,
14,
12,
24,
27,
27,
29,
29,
29,
3,
5,
5,
40,
43,
40,
41,
44,
57,
52,
41,
6,
3,
58,
5,
24,
29,
16,
6,
14,
5,
35,
46,
41,
51,
43,
54,
37,
4,
3,
7,
5,
3,
3,
3,
9,
6,
5,
4,
3,
9,
5,
12,
17,
5,
9,
4,
3,
3,
4,
10,
4,
7,
5,
6,
3,
7,
4,
4,
6,
3,
3,
4,
5,
6,
5,
6,
5,
5,
3,
3,
4,
7,
3,
4,
4,
5,
4,
5,
2,
3,
18,
53,
2,
25,
45,
40,
5,
12,
22,
21,
3,
18,
18,
11,
3,
16,
6,
2,
12,
13,
2,
8,
3,
5,
5,
6,
4,
10,
9,
6,
13,
7,
10,
19,
10,
19,
5,
5,
5,
13,
3,
8,
29,
3,
5
],
"write": [
15,
22,
7,
18,
9,
7,
15,
33,
8,
30,
6,
14,
8,
9,
6,
7,
6,
19,
12,
9,
10,
7,
3
],
"edit": [
147,
13,
13,
19,
22,
14,
16,
6,
9,
6,
10,
18,
13,
14,
13,
24,
11,
32,
35,
30,
16,
32,
9,
9,
10,
7,
8,
9,
8,
8,
8,
9,
6,
6,
5,
6,
6,
5,
23,
9,
9,
10,
8,
7,
8,
6,
4,
8,
28,
10,
6,
16,
9,
21,
29,
17,
14,
11,
6,
8,
7,
6,
8,
16,
38,
12,
24,
14,
11,
14,
16,
21,
10,
10,
10,
15,
16,
16,
36,
15,
31,
25,
7,
15,
16,
10,
15,
17,
18,
14,
14,
21,
8,
18,
10,
37,
11,
17,
14,
13,
22,
15,
20,
9,
11,
12,
10,
11,
9,
11,
8,
11,
9,
15,
9,
21,
8,
8,
33,
24,
6,
12,
4
]
},
"toolBlocked": {},
"sessions": [
{
"sessionId": "zlkjkn",
"startedAt": 1772554827283,
"model": "claude-opus-4-6",
"toolCalls": 390,
"agentTurns": 43,
"errors": 0,
"blocked": 0,
"tokensIn": 2192,
"tokensOut": 57348,
"cost": 8.716851999999998,
"peakContextPercent": 92
},
{
"sessionId": "tu9mo8",
"startedAt": 1772569015383,
"model": "claude-opus-4-6",
"toolCalls": 213,
"agentTurns": 21,
"errors": 0,
"blocked": 0,
"tokensIn": 2071,
"tokensOut": 6552,
"cost": 1.3847744999999998,
"peakContextPercent": 94
},
{
"sessionId": "yemv0x",
"startedAt": 1772573646207,
"model": "claude-opus-4-6",
"toolCalls": 94,
"agentTurns": 1,
"errors": 0,
"blocked": 0,
"tokensIn": 0,
"tokensOut": 0,
"cost": 0,
"peakContextPercent": 21
},
{
"sessionId": "n1rfud",
"startedAt": 1772574770468,
"model": "claude-opus-4-6",
"toolCalls": 7,
"agentTurns": 2,
"errors": 0,
"blocked": 0,
"tokensIn": 5686,
"tokensOut": 1617,
"cost": 0.18790150000000003,
"peakContextPercent": 9
}
],
"lastUpdated": 1772603919532
}

View File

@@ -11,7 +11,7 @@ WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/node_modules ./node_modules
COPY . . COPY . .
RUN npx prisma generate RUN npx prisma generate
RUN --mount=type=cache,target=/app/.next/cache npm run build RUN npm run build
FROM base AS runner FROM base AS runner
WORKDIR /app WORKDIR /app

View File

@@ -0,0 +1,98 @@
# Photography Generation Prompts
> Style reference: Young, candid, shallow DoF, cinematic. Like documentary wedding/event photography.
> Camera: Shot on Sony A7III or Canon R5, 35mm85mm, f/1.4f/2.8, available light.
> Subjects: Young (20s30s), British-diverse (South Asian, Black British, Arab, white British). Never looking at camera.
> RULE: NO visible phone/laptop screens. Show PEOPLE and EMOTION, not UI.
---
## 01 — Hero (replace 00-hero.jpg)
**Filename:** `hero-gala-moment.jpg`
**Aspect:** 3:4 portrait (mobile) / crops to 16:9 on desktop
**Purpose:** The emotional peak — a pledge just landed.
```
Young South Asian woman, mid-20s, elegant black dress, sitting at a charity gala dinner table. She's just glanced at her phone (screen facing away from camera, NOT visible) and has a subtle, private smile — the kind you get when unexpected good news arrives. Warm tungsten chandelier lighting, extreme bokeh from candles and glassware on table. Other guests blurred in background, evening formal wear. Shot on 85mm f/1.4, available light only. Documentary candid. Warm, intimate, celebratory. 3:4 portrait aspect ratio.
```
## 02 — Persona: Fundraiser (replace persona-02-phone.jpg)
**Filename:** `persona-fundraiser-street.jpg`
**Aspect:** 16:9 landscape
**Purpose:** The personal fundraiser — young, on the move, connected.
```
Young Black British man, early 20s, grey crewneck sweatshirt, walking on a London terraced street (Hackney/Brixton style). One hand holding phone at waist level (screen NOT visible), other hand in pocket. Confident, relaxed stride. Looking slightly down, focused expression. Overcast London sky, muted tones. Victorian terraced houses blurred behind. Shot on 50mm f/1.8, natural overcast light. Documentary street style. Cool, understated. 16:9 landscape aspect ratio.
```
## 03 — Persona: Treasurer (replace persona-04-desk.jpg)
**Filename:** `persona-treasurer-community.jpg`
**Aspect:** 16:9 landscape
**Purpose:** The person who reconciles — focused, competent, at a real desk.
```
Young British-Arab woman, late 20s, hijab, sitting at a cluttered desk in a community centre office. She's looking at a printed spreadsheet with a pen in hand, marking something off. No laptop screen visible — the camera focuses on HER face and expression (concentration, slight frown). Papers, a mug of tea, a box file visible on desk. Fluorescent office lighting mixed with window daylight. Shot on 35mm f/2.0, shallow depth of field on her face. Documentary candid. Unglamorous but real. 16:9 landscape aspect ratio.
```
## 04 — How It Works Step 1: Create a link (replace 01-main-dashboard-hero.jpg)
**Filename:** `step-create-link.jpg`
**Aspect:** 16:9 landscape (crops to square on mobile)
**Purpose:** The setup moment — printing QR codes before an event.
```
Two young volunteers (one South Asian man, one white British woman, both early 20s) standing at a folding table in a community hall, preparing for an event. One is cutting printed QR code cards with scissors, the other is stacking them into piles. Table has tablecloths, a banner partially visible. Hall is being set up — chairs stacked in background. Overhead fluorescent + window light. Shot on 35mm f/2.0. Documentary candid, like a behind-the-scenes photo. Industrious, purposeful energy. 16:9 landscape.
```
## 05 — How It Works Step 2: Donor pledges (replace 09-charities-amount-selection.jpg)
**Filename:** `step-donor-pledges.jpg`
**Aspect:** 16:9 landscape
**Purpose:** The pledge moment — donor scanning QR at an event table.
```
Young Black British woman, mid-20s, smart casual (blazer, no tie), seated at a round charity dinner table. She's holding her phone up near a small QR code card on the table, about to scan it. Phone screen NOT visible — shot from behind/side angle focusing on her profile and the moment of action. Other guests chatting blurred in background. Warm tungsten gala lighting, white tablecloth, wine glasses. Shot on 85mm f/1.4, shallow DoF. Cinematic, warm. 16:9 landscape.
```
## 06 — How It Works Step 3: Automatic follow-up (replace 10-charities-whatsapp.jpg)
**Filename:** `step-followup-notification.jpg`
**Aspect:** 16:9 landscape
**Purpose:** The day after — a donor getting a gentle reminder in their real life.
```
Young South Asian man, late 20s, casual clothes (hoodie), sitting in a London café. He's just picked up his phone from the table and is glancing at the screen (screen NOT visible to camera — shot from behind his shoulder or from the side). Coffee cup and laptop on table. Morning light through café window, warm tones. Other patrons blurred. Shot on 50mm f/1.8. Relaxed, everyday moment. 16:9 landscape.
```
## 07 — How It Works Step 4: Money arrives (replace 13-fundraisers-dashboard.jpg)
**Filename:** `step-money-arrives.jpg`
**Aspect:** 16:9 landscape
**Purpose:** The payoff — the fundraising team seeing results come in.
```
Small group of three young people (diverse — one hijabi woman, one Black British man, one white British woman, all 20s30s) in a community centre meeting room. They're leaning over a table looking at something together (papers/printouts, NOT a screen), one person pointing, expressions of pleased surprise — like they just hit a target. Casual clothes, lanyards. Fluorescent + window light. Shot on 35mm f/2.0. Documentary candid. Energetic, collaborative, real. 16:9 landscape.
```
## 08 — Compliance section (replace 06-main-pledge-form.jpg)
**Filename:** `compliance-mosque-hall.jpg`
**Aspect:** 21:9 ultrawide
**Purpose:** Shows the SCALE of events where compliance matters.
```
Wide interior shot of a mosque community hall during a large fundraising dinner. 200+ guests seated at round tables with white tablecloths. Warm tungsten chandeliers, ornate ceiling details. Camera positioned at the back of the hall, capturing the depth and scale. Blurred figures in foreground, sharp middle ground showing the crowd and volunteers moving between tables. Shot on 24mm f/2.8. Grand, warm, communal. 21:9 ultrawide cinematic crop.
```
## 09 — Payment Flexibility (replace 07-main-schedule-step.jpg)
**Filename:** `payment-flex-kitchen.jpg`
**Aspect:** 1:1 square
**Purpose:** Paying at home, on your own time, no pressure.
```
Young couple (mixed heritage, late 20s) sitting at a kitchen table in the evening. One person is looking at their phone (screen NOT visible), the other is pouring tea. Warm domestic lighting from a pendant lamp above. Kitchen shelves, mugs, a plant visible in background. Relaxed evening atmosphere — pyjamas or loungewear. Shot on 50mm f/1.8, shallow DoF on the phone-holding person. Intimate, cosy, unhurried. 1:1 square.
```
---
## Generation Settings (Gemini 3 Pro / Nano Banana Pro)
- Aspect ratio: specified per image
- Style: `photorealistic, documentary, candid`
- Negative: `stock photo, staged, looking at camera, visible screen UI, text on screen, smiling at camera, posed, bright studio lighting`
- Quality: High
- Save to: `brand/photography/` AND `public/images/landing/`

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 KiB

View File

@@ -0,0 +1,359 @@
# Pledge Now, Pay Later — Homepage Conversion Strategy
> Produced: March 2026
> Goal: Maximize free account signups from mixed-intent traffic
---
## 1. PAGE STRATEGY
### Target Persona + Emotional State on Arrival
**Primary persona:** Fatima, 38, Fundraising Manager at a mid-size UK Islamic charity (£200k£2M annual income). She just finished a gala dinner where £48,000 was pledged. She's sitting at home on Sunday night, dreading Monday. She knows from experience that 3050% of those pledges will vanish. She's Googling "how to collect charity pledges" or heard about PNPL from another charity manager at the event.
**Emotional state:** Frustrated, slightly anxious, skeptical of yet another tool. She's been burned by CRMs that cost £500/month and require 3 months of setup. She needs something that works *tonight*, not next quarter. She's on her phone.
**Secondary personas:** Personal fundraisers (sharing links on WhatsApp), event volunteers (want credit for their work), treasurers (need compliant records).
### Single Core Promise
**Every pledge tracked. Every donor reminded. Every penny accounted for. Free.**
### 3 Supporting Pillars
1. **60-second mobile pledge flow** — Donor scans QR → picks amount → done. No app, no account, no friction.
2. **Automated follow-up that doesn't feel awkward** — 4-step reminder sequence via WhatsApp/email. Donors pay when ready. You never chase.
3. **Complete visibility + compliance** — Live dashboard, Gift Aid declarations, Zakat tracking, HMRC-ready CSV export. One click.
### Top 5 Friction Points + Design Solutions
| # | Friction Point | How the Design Removes It |
|---|---------------|--------------------------|
| 1 | "What's the catch? Free = limited or sketchy" | Explicit "Free forever — no tiers, no card" messaging in hero. FAQ explains the business model transparently (lead gen for consultancy). |
| 2 | "I don't have time to set up another tool" | "2 minutes to your first pledge link" — specificity beats claims. How-it-works section shows 4 steps with real time estimates. |
| 3 | "My donors are older / not tech-savvy" | Show the 3-screen pledge flow visually. Emphasize: no app download, no account needed, 60 seconds. Address this directly in FAQ. |
| 4 | "Is this legit? Is my data safe?" | HMRC compliance, GDPR, ICO references. UK-based company registration. No vague "enterprise security" — name the specific regulations. |
| 5 | "We already use spreadsheets / JustGiving / LaunchGood" | Position as the *missing layer* between platforms, not a replacement. "Works with your existing setup" section with named platforms. |
---
## 2. WIREFRAME (Section-by-Section)
### Section 1: HERO (Dark — bg-gray-950)
**Goal:** Instant message match + primary CTA within 3 seconds.
**Key message:** You raise pledges. We make sure the money arrives.
**Components:**
- Eyebrow: `Pledge collection for UK charities` (border-l-2 accent, promise-blue)
- H1 (Display): `Turn "I'll donate" into money in the bank.`
- Subhead: `People pledge at events, over dinner, on WhatsApp. We make sure the money actually arrives.`
- Primary CTA: `Start free — takes 2 minutes` (white bg, dark text — high contrast)
- Secondary CTA: `See live demo` (outline, ghost)
- Trust micro-strip: `No card required · HMRC compliant · Free forever`
- Hero image: Documentary photo of charity event (right column on desktop, below on mobile)
**Interaction notes:**
- CTAs use `stagger-children` fade-up on load
- Hero image uses `fadeUp` with 250ms delay
- Primary CTA is white-on-dark for maximum pop (not blue — blue recedes on dark bg)
### Section 2: STAT STRIP (Dark — continuation of hero)
**Goal:** Anchor the problem with specific numbers before the visitor scrolls.
**Key message:** The pledge gap is real, measurable, and expensive.
**Components:**
- 4-column gap-px grid (signature pattern 2)
- Stats: `3050%` pledges never collected | `60s` pledge flow | `£0` cost | `2 min` setup
**Interaction notes:**
- Numbers use `font-black text-xl md:text-2xl` for visual weight
- Labels are `text-[11px] text-gray-500` — subordinate
### Section 3: PROBLEM AGITATION ("The Pledge Gap")
**Goal:** Make the visitor feel seen. Mirror their exact pain so they think "this is for me."
**Key message:** People don't break promises. Systems do.
**Components:**
- Eyebrow: `The pledge gap` (border-l-2 accent)
- H2: `People don't break promises.` + gray follow: `Systems do.`
- Subhead: `We built the missing system between "I'll donate" and the money arriving.`
- 4 sticky persona cards (image left, text right):
- Charity organizer: £50k pledged → £22k collected
- Fundraiser: 23 promised → 8 paid
- Volunteer: 40 pledges → 0 updates
- Treasurer: 200 rows, 47 typos, 6 hours
**Interaction notes:**
- Sticky scroll effect on desktop (cards stack with 28px offset)
- Mobile: standard vertical stack (no sticky)
- Each card links to `/for/{persona}` detail page
- Concrete numbers, not vague "lose donations"
### Section 4: HOW IT WORKS (Light bg — gray-50)
**Goal:** Make the mechanism feel simple and inevitable. Remove "is this complicated?" objection.
**Key message:** Four steps. Zero pledges lost.
**Components:**
- H2: `Four steps. Zero pledges lost.`
- 4-column numbered grid (01-04 pattern):
1. Create a pledge link — "One link per campaign, table, or WhatsApp group."
2. Donor pledges — "Amount, Gift Aid, schedule. 60-second mobile flow. No app."
3. Automatic follow-up — "Reminders with bank details. They pay when ready."
4. Money arrives — "Live dashboard. Who pledged, who paid, who needs a nudge."
**Interaction notes:**
- Numbers use `text-4xl font-black text-gray-200` (signature numbered steps)
- Copy is ruthlessly short — one line title, two line description max
### Section 5: SOCIAL PROOF / TRUST BLOCK
**Goal:** Transfer trust from known entities to PNPL. Answer "who else uses this?"
**Key message:** Built for the charities that can't afford to lose a single pledge.
**Components:**
- H2: `Built for UK charity compliance`
- Image: phone showing pledge form with checkboxes
- 4 border-l-2 items:
- Gift Aid — HMRC model declaration, timestamped CSV
- Zakat tracking — per-campaign, separate reporting
- Email consent — GDPR, never pre-ticked, audit trail
- WhatsApp consent — PECR, reply STOP, no sends without permission
**Interaction notes:**
- This section doubles as social proof (regulatory bodies = authority proof) AND objection handling
- Specific regulation names (HMRC, GDPR, PECR, ICO) act as trust anchors
### Section 6: BENEFIT STACK — Payment Flexibility
**Goal:** Show outcome-oriented benefits. Answer "but my donors want flexibility."
**Key message:** Donors pay when they're ready. You don't chase.
**Components:**
- H2: `Donors pay when they're ready`
- 3 border-l-2 items:
- Pay now — bank transfer or redirect to existing page
- Pick a date — "I'll pay on payday" with auto reminder
- Monthly instalments — 212 payments, each tracked separately
- Image: phone showing schedule options
### Section 7: PLATFORM COMPATIBILITY
**Goal:** Remove "but we already use X" objection. Position as additive, not replacement.
**Key message:** Works alongside what you already have.
**Components:**
- H2: `Works with your existing platform`
- Platform pills: Bank Transfer (UK), LaunchGood, Enthuse, JustGiving, GoFundMe, Any URL
### Section 8: FAQ / OBJECTION HANDLING
**Goal:** Kill remaining objections. Reduce "I'll think about it" exits.
**Key message:** No catch, no risk, no setup headaches.
**Components:**
- H2: `Questions we hear at every charity dinner`
- 6 Q&A items (accordion or simple expand):
1. "How is this free? What's the catch?"
2. "Will my donors actually use this?"
3. "Is this GDPR compliant?"
4. "We already have a CRM / use JustGiving"
5. "How long does setup take?"
6. "What happens to donor data?"
**Interaction notes:**
- Questions written in first person ("Will MY donors...") — similarity principle
- Answers are 23 sentences max. Specific. No corporate waffle.
### Section 9: FINAL CTA (Dark — bg-gray-950)
**Goal:** Strong close. Create urgency without fake scarcity.
**Key message:** Every day without this, you're losing pledges.
**Components:**
- H2: `Every day without this, you're losing pledges.`
- Subhead: `Free forever. Two-minute setup. Works tonight.`
- Primary CTA: `Create free account`
- Secondary CTA: `See live demo`
**Interaction notes:**
- No nav links, no footer links visible — minimal distraction
- CTA buttons are larger here (py-4 px-8) — commitment escalation
---
## 3. UI DIRECTION (Design System Guidance)
### Layout Grid + Spacing
- Max content width: `max-w-7xl` (hero), `max-w-5xl` (content sections)
- Section padding: `py-20 md:py-24 px-6`
- Mobile: single column, `gap-8`
- Desktop: `grid md:grid-cols-2` or `md:grid-cols-4`
- Consistent internal spacing: `space-y-6` for text blocks, `gap-10` for grid cards
### Type Scale
| Level | Size | Weight | Tailwind |
|-------|------|--------|----------|
| Display/H1 | 44px / 60-72px | 900 | `text-[2.75rem] md:text-6xl lg:text-7xl font-black tracking-tighter` |
| H2 | 36-48px | 900 | `text-4xl md:text-5xl font-black tracking-tight` |
| H3 | 18-24px | 700 | `text-base font-bold` or `text-xl font-black` |
| Body | 14-16px | 400 | `text-sm` or `text-base` |
| Eyebrow | 11px | 600 | `text-[11px] font-semibold tracking-[0.15em] uppercase` |
| Caption | 11-12px | 500 | `text-[11px] text-gray-500` |
### Button Hierarchy
| Level | Style | Use |
|-------|-------|-----|
| Primary (dark bg) | `bg-white text-gray-900 font-bold px-7 py-3.5` | Hero CTA, final CTA |
| Primary (light bg) | `bg-gray-900 text-white font-bold px-8 py-4` | Mid-page CTAs |
| Secondary | `border border-gray-700 text-gray-400 font-bold px-7 py-3.5` | Demo links |
| Ghost | `text-sm font-semibold text-promise-blue` | "Learn more" inline |
### Form Design
- Signup page (not on landing): email + password only. Name optional. Org name on next screen.
- No forms on the landing page itself — CTA buttons route to `/signup`
### Visual Style
- **Photography:** Documentary candid, shallow DoF, diverse British subjects, never stock
- **Icons:** Not used as section headers. Numbers (01, 02, 03) replace icons.
- **Illustrations:** None. Photography + typography only.
- **Sharp edges everywhere.** Max `rounded-lg` on interactive elements.
### Trust Design
- Named regulations (HMRC, GDPR, PECR, ICO) instead of generic "secure" badges
- Specific numbers instead of vague claims
- Company registration visible in footer (© QuikCue Ltd)
- "Free forever — no card required" repeated 2x on page
---
## 4. CONVERSION PSYCHOLOGY MAPPING
| Section | Component | Principle | Implementation |
|---------|-----------|-----------|---------------|
| Hero | Headline | **Clarity > Persuasion** | "Turn 'I'll donate' into money in the bank" — no jargon, instant understanding |
| Hero | Stat strip | **Anchoring** | "3050% of pledges never collected" anchors the cost of inaction |
| Hero | Trust line | **Risk Reversal** | "No card · HMRC compliant · Free forever" — 3 objections killed in 8 words |
| Pledge Gap | Persona stats | **Loss Aversion** | "£50k pledged. £22k collected." — gap framing triggers loss aversion |
| Pledge Gap | "Systems do" | **External Attribution** | Blame the system, not the donor — removes shame, creates solvable problem |
| How It Works | 4 steps | **Commitment/Consistency** | Small, numbered steps make action feel inevitable (foot-in-door) |
| How It Works | "60 seconds" | **Specificity = Credibility** | Specific time beats "quick and easy" |
| Compliance | HMRC, GDPR names | **Authority Proof** | Regulatory body names transfer institutional trust |
| Payment Flex | 3 options | **Autonomy** | Giving donors control reduces reactance, increases completion |
| Platforms | Named logos | **Social Proof (similarity)** | "They use LaunchGood too" — similarity reduces perceived risk |
| FAQ | First-person Qs | **Social Proof (similarity)** | "Will MY donors use this?" mirrors exact internal dialogue |
| FAQ | Business model | **Reciprocity + Transparency** | Explaining why it's free creates trust debt |
| Final CTA | "Losing pledges" | **Loss Aversion** | Frame inaction as ongoing loss, not missed gain |
| Final CTA | "Works tonight" | **Immediacy** | Reduces "I'll do it later" deferral |
---
## 5. COPY (Ready to Paste)
### Hero
**Headline:** Turn "I'll donate" into money in the bank.
**Subhead:** People pledge at events, over dinner, on WhatsApp. We make sure the money actually arrives.
**Primary CTA:** Start free — takes 2 minutes
**Secondary CTA:** See live demo
**Trust strip:** No card required · HMRC compliant · Free forever
### 3 Pillar Stats
- `3050%` of pledges never collected
- `60s` to complete a pledge
- `£0` cost to charities
- `2 min` signup to first link
### Mechanism Section (How It Works)
**H2:** Four steps. Zero pledges lost.
**01 — Create a pledge link**
One link per campaign, table, volunteer, or WhatsApp group. Share anywhere.
**02 — Donor pledges in 60 seconds**
Amount, Gift Aid, Zakat, schedule — mobile flow. No app download. No account.
**03 — Automatic follow-up**
Reminders with your bank details. They pay when ready. You never chase.
**04 — Money arrives**
Live dashboard. Who pledged, who paid, who needs a nudge. Export for Gift Aid.
### Proof / Compliance Captions
- **Gift Aid:** HMRC model declaration, home address, timestamped. One-click CSV for claiming.
- **Zakat:** Per-campaign toggle. Donors tick one checkbox. Tracked separately in reports.
- **Email consent:** GDPR compliant. Separate opt-in, never pre-ticked. Full audit trail.
- **WhatsApp consent:** PECR compliant. Separate opt-in. Reply STOP to opt out.
### FAQ Answers
**Q: How is this free? What's the catch?**
No catch. No tiers. No "upgrade to unlock." The tool is genuinely free because it helps us identify charities that need broader technology support. If your org grows beyond pledge collection, we offer fractional Head of Technology services — but that's a separate conversation you'd start, not us.
**Q: Will my donors actually use this?**
They scan a QR code or tap a link. Three screens: amount, payment method, email or phone. 60 seconds, done. No app download, no account creation. We've designed it for the least tech-confident person at your event.
**Q: Is this GDPR and HMRC compliant?**
Yes. Gift Aid declarations use the exact HMRC model wording with timestamped consent. Email and WhatsApp opt-ins are separate, never pre-ticked, with full audit trails. Data is stored in UK-hosted infrastructure.
**Q: We already use JustGiving / LaunchGood / a CRM.**
We're not replacing any of those. We're the layer between "I'll donate" and the money reaching your platform. Donors can be redirected to your existing fundraising page to pay. We just make sure they don't forget.
**Q: How long does setup take?**
Two minutes. Create an account, name your first event, generate a pledge link. You can test the donor flow on your own phone immediately.
**Q: What happens to donor data?**
You own it. Export everything as CSV anytime. We never sell or share donor data. When you delete your account, the data goes with it.
### Final CTA
**H2:** Every day without this, you're losing pledges.
**Sub:** Free forever. Two-minute setup. Works tonight.
**Primary CTA:** Create free account
**Secondary CTA:** See live demo
---
## 6. EXPERIMENT PLAN (CRO)
### A/B Tests
| # | Hypothesis | Change | Expected Impact | Risk |
|---|-----------|--------|----------------|------|
| 1 | Loss-framed headline converts better than gain-framed | A: "Turn 'I'll donate' into money in the bank" vs B: "Stop losing 40% of your pledged donations" | +1525% CTA clicks | Low — both on-brand |
| 2 | Single CTA in hero outperforms dual CTA | A: Two buttons vs B: One primary button only | +10% primary clicks, -20% demo clicks | Medium — lose demo traffic |
| 3 | Sticky persona cards hurt mobile conversion (scroll jank) | A: Sticky scroll vs B: Standard card stack on all devices | +5% scroll-to-CTA on mobile | Low — simpler is safer |
| 4 | FAQ section increases signup rate | A: With FAQ vs B: Without FAQ | +812% conversion (objection removal) | Low — only adds content |
| 5 | Social proof with specific charity names beats generic compliance | A: Compliance features vs B: "Trusted by 40+ UK charities" with named logos | +1020% trust signal impact | Medium — need real logos |
| 6 | "Works tonight" urgency in final CTA beats neutral | A: "Works tonight" vs B: "Get started today" | +5% final CTA clicks | Low |
### Tracking Plan
| Event | Trigger | Properties |
|-------|---------|-----------|
| `page_view` | Landing page loads | `source`, `utm_*`, `device` |
| `scroll_25` | 25% scroll depth | `time_on_page` |
| `scroll_50` | 50% scroll depth | `time_on_page` |
| `scroll_75` | 75% scroll depth | `time_on_page` |
| `scroll_100` | Bottom of page reached | `time_on_page` |
| `hero_cta_click` | Primary CTA in hero | `cta_text` |
| `hero_demo_click` | Secondary CTA in hero | — |
| `persona_card_click` | Any persona card tapped | `persona` |
| `faq_expand` | FAQ question opened | `question_index` |
| `final_cta_click` | Bottom CTA clicked | `cta_text` |
| `signup_start` | `/signup` page loads (from landing) | `referrer_section` |
| `signup_complete` | Account created | `time_to_signup` |
### Diagnostic Checklist (If Conversion Is Low)
1. **Hero bounce rate > 60%?** → Message mismatch with traffic source. Check ad copy vs headline alignment.
2. **Scroll depth < 50% for 70%+ visitors?** → Hero isn't compelling enough or page loads slow. Check LCP.
3. **Hero CTA click rate < 3%?** → CTA copy or placement issue. Test button color, copy, position.
4. **Persona cards getting 0 clicks?** → Cards aren't engaging or sticky scroll is broken on mobile. Simplify.
5. **FAQ section has 0 expansions?** → Either placed too low (people leave before reaching it) or questions aren't matching real objections. Move higher or rewrite.
6. **Demo clicks > signup clicks (3:1)?** → Visitors don't trust enough to commit. Add more proof, reduce signup friction.
7. **Signup starts >> signup completes?** → Form friction. Check field count, validation errors, load time.
8. **Mobile conversion < 50% of desktop?** → Touch target issues, slow images, broken layout. Audit on real device.
9. **High time-on-page but low conversion?** → Content is engaging but CTA isn't clear or compelling enough. Make CTAs stickier.
10. **Organic traffic converts but paid doesn't?** → Ad targeting or messaging mismatch. Align ad creative with landing page promise.

View File

@@ -3,7 +3,7 @@ const nextConfig = {
output: "standalone", output: "standalone",
images: { images: {
formats: ["image/webp"], formats: ["image/webp"],
deviceSizes: [640, 828, 1080, 1200], deviceSizes: [640, 828, 1080, 1200, 1920, 2560],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 31536000, // 1 year — images are immutable, filename changes on update minimumCacheTTL: 31536000, // 1 year — images are immutable, filename changes on update
}, },

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1002 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 759 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 776 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 KiB

Some files were not shown because too many files have changed in this diff Show More