# Landing Page

# Landing Page

## Overview

**URL:** [https://getdrop.no](https://getdrop.no)  
**Purpose:** Multi-language marketing landing page for Drop — fintech payment app  
**Target users:** All residents in Norway/Scandinavia (not diaspora-only)

## Architecture

- **Hosting:** Cloudflare Pages
- **Zone ID:** `0e4476892bfc1eaace41a80d6d060607`
- **Stack:** Static HTML + CSS (no build process)
- **Deployment:** `wrangler pages deploy` via GitHub Actions (`landing-deploy.yml`)
- **Database:** Cloudflare D1 (SQLite) for waitlist signups

## File Structure

```
landing/
├── index.html              # Main entry point (Norwegian default)
├── locales/                # 12 language JSON files (nb, en, sv, da, fi, bs, sr, hr, de, tr, sq, pl)
├── functions/
│   └── api/waitlist.js     # CF Function — waitlist signup endpoint
├── _headers                # Security headers (CSP, HSTS, X-Frame-Options)
├── wrangler.toml           # CF Pages + D1 config
├── package.json            # Dependencies (wrangler only)
├── manifest.json           # PWA manifest
├── sw.js                   # Service worker
├── favicon.svg             # Drop logo favicon
└── pages/                  # Static sub-pages (send-penger, qr-betaling, priser, etc.)
```

## Hero Design Decision (2026-04-22)

**Problem:** CEO feedback — landing page showed fake app demo mockup (SpareBank balance, fake transactions, "Mama Jasmina") instead of actual product information.

**Solution:** Replaced demo mockup with **info-first corridor card** showing:

- **Flow:** Norge 🇳🇴 → 30+ land 🌐
- **Destination grid:** Bosnia, Serbia, Croatia, Albania, Poland + 25 more
- **Key stats:** 0.5% fee / &lt;1 min transfer / BankID auth

**Code change:** Commit `dfa0b3b3` on `main`  
**MC task:** [\#8729](https://mc.alai.no/tasks/8729)  
**Files changed:** `landing/index.html` (155 insertions, 110 deletions)

**Visual proof:**

- Desktop: `/tmp/drop-screenshots/getdropno-desktop-waited.png`
- Mobile: `/tmp/drop-screenshots/getdropno-mobile-waited.png`

**Verification:**

```
curl https://getdrop.no | grep -c 'ps-balance'           # 0 (removed)
curl https://getdrop.no | grep -c 'phone-screen'         # 0 (removed)
curl https://getdrop.no | grep -c 'SpareBank'            # 0 (removed)
curl https://getdrop.no | grep -c 'Mama Jasmina'         # 0 (removed)
curl https://getdrop.no | grep -c 'corridor-card'        # 3 (present)
```

## Waitlist Flow

1. **User submits email** via form at `#cta` section
2. **POST /api/waitlist** → CF Function at `functions/api/waitlist.js`
3. **Validation:** Email regex + honeypot field (`website`)
4. **Storage:** CF D1 database (`drop-waitlist`, binding `DB`)
5. **Schema:** `waitlist_signups` table (id, email, source, created\_at)
6. **Response:** JSON `{ok: true, message: 'Registrert!'}`

**Admin access:** `GET /api/waitlist?key=<WAITLIST_ADMIN_KEY>` returns all signups (rate-limited, 5 attempts per 15 min)

## Internationalization (i18n)

**Languages:** 12 supported

<table id="bkmrk-codelanguagefilenbno"><thead><tr><th>Code</th><th>Language</th><th>File</th></tr></thead><tbody><tr><td>nb</td><td>Norsk (bokmål)</td><td>locales/no.json</td></tr><tr><td>en</td><td>English</td><td>locales/en.json</td></tr><tr><td>sv</td><td>Svenska</td><td>locales/sv.json</td></tr><tr><td>da</td><td>Dansk</td><td>locales/da.json</td></tr><tr><td>fi</td><td>Suomi</td><td>locales/fi.json</td></tr><tr><td>bs</td><td>Bosanski</td><td>locales/bs.json</td></tr><tr><td>sr</td><td>Srpski</td><td>locales/sr.json</td></tr><tr><td>hr</td><td>Hrvatski</td><td>locales/hr.json</td></tr><tr><td>de</td><td>Deutsch</td><td>locales/de.json</td></tr><tr><td>tr</td><td>Türkçe</td><td>locales/tr.json</td></tr><tr><td>sq</td><td>Shqip</td><td>locales/sq.json</td></tr><tr><td>pl</td><td>Polski</td><td>locales/pl.json</td></tr></tbody></table>

**Implementation:** Language switcher dropdown in nav, preference stored in localStorage

## Deployment

**Method:** GitHub Actions workflow (`.github/workflows/landing-deploy.yml`)

**Trigger:** Push to `main` with changes in `landing/**` path

**Process:**

1. Checkout repo
2. Setup Node.js 20
3. Install dependencies (`npm ci`)
4. Deploy via Wrangler: `wrangler pages deploy . --project-name=$CF_LANDING_PROJECT_NAME --branch=main`

**Secrets required:**

- `CLOUDFLARE_API_TOKEN` (CF Global API Key)
- `CLOUDFLARE_ACCOUNT_ID`
- `CF_LANDING_PROJECT_NAME` (project name in CF Pages)

**DNS:**

- `getdrop.no` → CF Pages (CNAME)
- `www.getdrop.no` → CF Pages (CNAME)
- `app.getdrop.no` → Azure Caddy reverse proxy (app backend)

## Security Headers

**File:** `_headers`

```
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
X-XSS-Protection: 1; mode=block
```

## Related Tasks

- **MC #8485** — CF Pages migration (completed)
- **MC #8537** — Waitlist PostgreSQL wire-up (completed)
- **MC #8729** — Info-first hero redesign (ready for review)
- **MC #8731** — Proveo validation (pending)
- **MC #8732** — Git config fix (completed)

## Key Metrics

- **Total locales:** 12 language files
- **Waitlist database:** CF D1 SQLite (auto-created table)
- **Current signups:** Query via admin endpoint
- **Deploy target:** Cloudflare Pages (CDN-backed, global edge)

## Future Improvements

- Add A/B testing for hero variants
- Integrate analytics (Plausible or CF Web Analytics)
- Expand corridor card with real-time exchange rates
- Add language auto-detection based on IP geolocation