Files
boc/quixzoom-market-pages/MARKET_TEMPLATE.md
T

240 lines
8.3 KiB
Markdown
Raw Normal View History

# quiXzoom Market Pages — Template System
> **Master template**: `se/index.html` (quiXzoom.se, Swedish market)
> **System**: 22-market ccTLD landing-page framework
> **Owner**: Wavult Group / AAMOS (aamos.systems)
> **Last updated**: 2026-06-07
---
## Architecture
Each market gets its own folder under `quixzoom-market-pages/<cc>/` containing:
```
markets/<cc>/
├── index.html ← Full HTML landing page (single-file, no build step)
├── robots.txt ← Market-specific robots with sitemap URL
└── sitemap.xml ← Market sitemap with full hreflang cross-links
```
Files are deployed to S3 `s3://quixzoom-landing-prod/markets/<cc>/` and served via CloudFront.
---
## Market Checklist
When creating a new market from the SE template, change every item below:
### `index.html`
| Element | SE value | Action |
|---------|----------|--------|
| `<html lang="...">` | `sv` | → market language code |
| `<title>` | Swedish title | → translate, keep ≤60 chars |
| `<meta name="description">` | Swedish description | → translate, keep ≤155 chars |
| `<link rel="canonical">` | `https://quixzoom.se/` | → market ccTLD |
| `<meta name="geo.region">` | `SE` | → ISO 3166-1 alpha-2 |
| `<meta name="geo.country">` | `Sweden` | → country name |
| `<meta name="language">` | `Swedish` | → language name |
| All `og:` and `twitter:` tags | Swedish copy | → translated copy |
| Schema.org `@id` URLs | `quixzoom.se` | → market ccTLD |
| Schema.org `areaServed` | `Sweden` | → market country |
| Schema.org `FAQPage` | Swedish FAQs | → 45 locally relevant FAQs |
| Schema.org `inLanguage` | `sv` | → BCP-47 code |
| H1 hero heading | Swedish copy | → translate/adapt for market |
| Hero subtext | Swedish | → translate/adapt |
| Hero badge | `🇸🇪 Lanseras i Sverige · Juni 2026` | → flag + country + date |
| Step descriptions | Swedish | → translate |
| Why-cards | Swedish | → translate |
| Business section | Swedish | → translate |
| FAQ answers | Swedish | → translate + localize (e.g. tax authority name) |
| Footer language switcher | Active = 🇸🇪 | → set correct active market |
| Footer copyright | Swedish | → translate |
| Footer AAMOS link | Swedish label | → translate |
| All internal links | `quixzoom.se/...` | → market ccTLD |
| CTA links | `app.quixzoom.com/join` | → keep (global app) |
### `robots.txt`
Change: `Sitemap: https://quixzoom.se/sitemap.xml``https://quixzoom.<cc>/sitemap.xml`
### `sitemap.xml`
Change all `<loc>` entries to the market ccTLD. The `<xhtml:link>` hreflang cross-links stay the same across all markets (they reference all ccTLDs).
---
## Localization Notes
### Language codes (hreflang)
| Market | ccTLD | hreflang | Active |
|--------|-------|----------|--------|
| Sweden | quixzoom.se | `sv` | ✅ Live template |
| Germany | quixzoom.de | `de` | ⏳ Pending |
| France | quixzoom.fr | `fr` | ⏳ Pending |
| Netherlands | quixzoom.nl | `nl` | ⏳ Pending |
| United Kingdom | quixzoom.co.uk | `en-gb` | ⏳ Pending |
| Italy | quixzoom.it | `it` | ⏳ Pending |
| Spain | quixzoom.es | `es` | ⏳ Pending |
| Finland | quixzoom.fi | `fi` | ⏳ Pending |
| Denmark | quixzoom.dk | `da` | ⏳ Pending |
| Belgium | quixzoom.be | `be` | ⏳ Pending |
| Default | quixzoom.com | `x-default` | ✅ Live |
> Add new markets to the hreflang list in **all** existing market pages when adding a new ccTLD.
### Pay rate localization
The `150500 kr` value in the stats section must be updated to local currency:
- 🇩🇪 `1550 €`
- 🇫🇷 `1550 €`
- 🇬🇧 `1242 £`
- etc.
### Tax/legal localization
The FAQ answer about taxation must reference the **local tax authority**:
- 🇸🇪 → Skatteverket
- 🇩🇪 → Finanzamt
- 🇫🇷 → Direction générale des Finances publiques (DGFiP)
- 🇬🇧 → HMRC
- etc.
### Launch badge
Update the `hero-badge` with the correct launch region and date for each market.
---
## Design System
All design tokens are defined as CSS custom properties in `:root{}` — no external frameworks.
| Token | Value | Usage |
|-------|-------|-------|
| `--qx-black` | `#0a0a0a` | Hero bg, nav, body text |
| `--qx-white` | `#FFFFFF` | Main bg, text on dark |
| `--qx-blue` | `#0066FF` | CTAs, accents, stats bg |
| `--qx-green` | `#00C853` | Success states (future use) |
| `--qx-gray` | `#F5F5F7` | Section backgrounds, cards |
| `--qx-dark-gray` | `#1a1a1a` | Footer background |
| `--qx-text-muted` | `#6e6e73` | Descriptive body copy |
Font stack: `-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', sans-serif`
→ System font stack — zero external requests, instant render, optimal CWV.
---
## Infrastructure: Deploying a Market Page
### Prerequisites
- AWS CLI configured with profile `platform-ai-agent`
- S3 bucket: `quixzoom-landing-prod`
- CloudFront distribution: `EE30B9WM5ZYM7` (serves quixzoom.com)
- For ccTLD: separate CloudFront distribution + Route53 A-record required (see below)
### Deploy command (served under quixzoom.com/markets/<cc>/)
```bash
CC=se # change per market
aws s3 cp /home/bernt/.openclaw/workspace/quixzoom-market-pages/$CC/index.html \
s3://quixzoom-landing-prod/markets/$CC/index.html \
--content-type "text/html; charset=utf-8" \
--cache-control "max-age=3600"
aws s3 cp /home/bernt/.openclaw/workspace/quixzoom-market-pages/$CC/robots.txt \
s3://quixzoom-landing-prod/markets/$CC/robots.txt \
--content-type "text/plain"
aws s3 cp /home/bernt/.openclaw/workspace/quixzoom-market-pages/$CC/sitemap.xml \
s3://quixzoom-landing-prod/markets/$CC/sitemap.xml \
--content-type "application/xml"
# Invalidate CloudFront cache
aws cloudfront create-invalidation \
--distribution-id EE30B9WM5ZYM7 \
--paths "/markets/$CC/*"
```
---
## How to Connect quixzoom.se → Its Own CloudFront
The SE market is currently served under `quixzoom.com/markets/se/`. To go fully live on `quixzoom.se`:
### Step 1 Request/verify SSL certificate in ACM
```
Region: us-east-1 (required for CloudFront)
Domain: quixzoom.se
Include SANs: www.quixzoom.se
Validation: DNS (add CNAME in Route53 zone quixzoom.se)
```
### Step 2 Create dedicated S3 bucket or path
Option A: Reuse `quixzoom-landing-prod` with a `se/` path prefix
Option B: Create `quixzoom-landing-se` bucket (cleaner separation)
### Step 3 Create CloudFront distribution
```
Origin: s3://quixzoom-landing-prod/markets/se/ (or new bucket)
Default root object: index.html
Alternate domain names: quixzoom.se, www.quixzoom.se
SSL certificate: (from Step 1)
HTTP→HTTPS redirect: Yes
Compress objects: Yes (gzip/brotli)
Price class: PriceClass_100 (EU + NA)
```
### Step 4 Route53: Add apex A-record (alias)
```
Zone: quixzoom.se (already exists)
Record type: A (Alias)
Alias target: <new CloudFront distribution domain>.cloudfront.net
TTL: 60s initially, then raise to 300s after verified
```
Also add AAAA alias record for IPv6.
### Step 5 Add www redirect (optional)
Create a CloudFront Function or use S3 redirect to send www → apex.
### Step 6 Deploy market files to new origin path
```bash
aws s3 cp .../se/index.html s3://quixzoom-landing-prod/markets/se/index.html ...
aws s3 cp .../se/robots.txt s3://quixzoom-landing-prod/markets/se/robots.txt ...
aws s3 cp .../se/sitemap.xml s3://quixzoom-landing-prod/markets/se/sitemap.xml ...
```
### Step 7 Verify
```bash
curl -sI https://quixzoom.se/ | head -10
# Expect: HTTP/2 200, x-cache: Hit from cloudfront
```
---
## SEO Validation Checklist
After deploying a market page, verify:
- [ ] `<html lang="">` correct for market
- [ ] Title ≤ 60 chars with primary keyword first
- [ ] Description ≤ 155 chars, includes key terms
- [ ] Canonical points to market ccTLD apex
- [ ] hreflang set complete (all 10 markets + x-default)
- [ ] Schema.org valid (test with Google Rich Results Test)
- [ ] OG image returns 200 (check og-image.jpg)
- [ ] robots.txt accessible at `/robots.txt`
- [ ] sitemap.xml accessible at `/sitemap.xml`
- [ ] Submit sitemap to Google Search Console for market domain
- [ ] Core Web Vitals: LCP < 2.5s, CLS < 0.1, INP < 200ms
---
## File Sizes (SE market, 2026-06-07)
| File | Size | Notes |
|------|------|-------|
| index.html | ~25 KB | Single-file, no deps, all inline CSS |
| robots.txt | ~142 B | Minimal |
| sitemap.xml | ~1.7 KB | 4 URLs + full hreflang cross-links |
LCP target: < 2s on 4G mobile (system fonts = zero font-fetch latency).