# Launch Plan – kashilo.com

## Release-Phasen

| Phase | Preis pro Anzeige | Dauer | Zugang |
|-------|-------------------|-------|--------|
| **Closed Alpha** | 0,01 € / 0,01 USD / 0,01 CHF | 4–6 Wochen | Nur mit Invite-Code |
| **Open Beta** | 0,10 € / 0,10 USD / 0,10 CHF | 3 Monate | Öffentlich, Beta-Banner |
| **Launch** | 1 € / 1 USD / 1 CHF | Dauerhaft | Öffentlich |

**Pricing-Philosophie:** Die Zahl **1** als magische Zahl — einfach, einprägsam, international gleich.
`1 listing = 1 month = 1`

---

## Phase 1: Closed Alpha

### Ziel
- Feedback von Crypto/Privacy-Enthusiasten
- Payment-Flow testen (1 Cent = echte Transaktion, minimale Kosten)
- Bugs finden, UX validieren

### Invite-Code System

#### Directus: Collection `invite_codes`

| Feld | Typ | Hinweise |
|------|-----|----------|
| `id` | UUID (auto) | Primary Key |
| `code` | String, unique | z.B. `ALPHA-XMR-2026` |
| `max_uses` | Integer | Max. Einlösungen (0 = unbegrenzt) |
| `used_count` | Integer, default 0 | Aktuelle Einlösungen |
| `expires_at` | DateTime, nullable | Optional: Ablaufdatum |
| `status` | String, default `active` | `active` / `disabled` |
| `date_created` | Timestamp (auto) | |

#### Directus: Permissions für `invite_codes`

| Rolle | Read | Create | Update |
|-------|------|--------|--------|
| Public | Nein | Nein | Nein |
| Admin | Ja | Ja | Ja |

Die Validierung passiert **serverseitig** im PoW-Server (PHP), nicht im Frontend.

#### PHP: Invite-Code Validierung

Neuer Endpoint: `POST /invite/validate`

```php
// pow.kashilo.com/invite/validate.php
<?php
require __DIR__ . '/config.php';

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: https://kashilo.com');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { exit; }
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
    exit;
}

$input = json_decode(file_get_contents('php://input'), true);
$code = trim($input['code'] ?? '');

if (!$code) {
    http_response_code(400);
    echo json_encode(['valid' => false, 'error' => 'Missing invite code']);
    exit;
}

// Query Directus for invite code
$url = DIRECTUS_URL . '/items/invite_codes?filter[code][_eq]=' . urlencode($code)
     . '&filter[status][_eq]=active&limit=1';

$context = stream_context_create([
    'http' => [
        'header' => "Authorization: Bearer " . DIRECTUS_TOKEN . "\r\n",
        'ignore_errors' => true,
    ],
]);

$response = file_get_contents($url, false, $context);
$data = json_decode($response, true);
$invite = $data['data'][0] ?? null;

if (!$invite) {
    echo json_encode(['valid' => false, 'error' => 'Invalid or expired invite code']);
    exit;
}

// Check max uses
if ($invite['max_uses'] > 0 && $invite['used_count'] >= $invite['max_uses']) {
    echo json_encode(['valid' => false, 'error' => 'Invite code fully redeemed']);
    exit;
}

// Check expiry
if ($invite['expires_at'] && strtotime($invite['expires_at']) < time()) {
    echo json_encode(['valid' => false, 'error' => 'Invite code expired']);
    exit;
}

// Increment used_count
$updateUrl = DIRECTUS_URL . '/items/invite_codes/' . $invite['id'];
$updateContext = stream_context_create([
    'http' => [
        'method' => 'PATCH',
        'header' => "Content-Type: application/json\r\nAuthorization: Bearer " . DIRECTUS_TOKEN . "\r\n",
        'content' => json_encode(['used_count' => $invite['used_count'] + 1]),
        'ignore_errors' => true,
    ],
]);
file_get_contents($updateUrl, false, $updateContext);

echo json_encode(['valid' => true]);
```

#### Frontend: Invite-Code bei Registrierung

In `js/components/auth-modal.js` — im Registrierungs-Flow ein Textfeld hinzufügen:

```
[Invite Code: _________ ]   ← nur in Alpha-Phase sichtbar
[UUID generieren]
```

Vor `createAccount()` den Code serverseitig validieren:

```js
const res = await fetch('https://pow.kashilo.com/invite/validate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ code: inviteCode })
})
const { valid, error } = await res.json()
if (!valid) { /* Fehlermeldung anzeigen */ return }
```

#### Feature-Flag

In `config.php` ein Flag, um Alpha-Modus zu steuern:

```php
define('REQUIRE_INVITE_CODE', true);  // false für Open Beta / Launch
```

Im Invoice-Endpoint kann optional der Invite-Code mitgesendet werden,
um Alpha-User zu tracken.

### Pricing-Änderung für Alpha

In `docs/pow-server/config.php`:

```php
// Alpha: 1 Cent
define('LISTING_FEE', ['EUR' => 0.01, 'USD' => 0.01, 'CHF' => 0.01, 'GBP' => 0.01, 'JPY' => 2]);
```

### Verteilung der Invite-Codes

- Manuell in Directus erstellen (Admin-Panel)
- Verteilen über:
  - r/Monero, r/privacy
  - Monero Matrix/IRC Channels
  - Persönliche Kontakte
- **10–20 Codes** mit je 5–10 max_uses → 50–200 Alpha-Tester

---

## Phase 2: Open Beta

### Änderungen

1. **Pricing**: `config.php` → `LISTING_FEE` auf 0,10 setzen
2. **Invite-Code**: `REQUIRE_INVITE_CODE` → `false`
3. **Beta-Banner**: Hinweis auf der Seite ("Beta — Feedback willkommen")
4. **Feedback-Kanal**: Link zu Matrix-Raum oder einfaches Kontaktformular

### Marketing

- **Show HN** Post auf Hacker News
- r/Monero, r/privacy, r/degoogle — organische Posts
- Privacy-Newsletter (PrivacyGuides, Techlore)
- Monero-Community (Matrix, IRC)

### Metriken tracken

- Anzahl Registrierungen
- Anzahl veröffentlichter Anzeigen
- Payment Completion Rate
- Chat-Nutzung (nur Anzahl, nicht Inhalt)

---

## Phase 3: Launch

### Änderungen

1. **Pricing**: `config.php` → `LISTING_FEE` auf 1 setzen (bereits Standard)
2. **Beta-Banner** entfernen
3. **Invite-Code-System** kann aktiv bleiben (für spätere Promo-Codes nutzbar)

### Kommunikation

**"1 listing = 1 month = 1"** — so simpel wie möglich.

---

## Meta-Tags (pro Sprache)

Die statischen Meta-Tags in `index.html` sind deutsch (Fallback).
Der OG-Proxy (`pow.kashilo.com/og-proxy.php`) liefert Listing-spezifische Tags.

### Umgesetzte Texte

**Title:** `kashilo.com – [Sprache]`

| Sprache | Title | Description |
|---------|-------|-------------|
| **de** | kashilo.com – Anonyme Kleinanzeigen | Kaufen und verkaufen ohne Konto, ohne E-Mail. Bezahlung mit Monero. Ende-zu-Ende verschlüsselter Chat. |
| **en** | kashilo.com – Private Classifieds | Buy and sell without an account, without email. Pay with Monero. End-to-end encrypted chat. |
| **fr** | kashilo.com – Petites annonces anonymes | Achetez et vendez sans compte, sans e-mail. Paiement en Monero. Chat chiffré de bout en bout. |
| **it** | kashilo.com – Annunci anonimi | Compra e vendi senza account, senza email. Pagamento in Monero. Chat crittografata end-to-end. |
| **es** | kashilo.com – Clasificados anónimos | Compra y vende sin cuenta, sin email. Pago con Monero. Chat cifrado de extremo a extremo. |
| **pt** | kashilo.com – Classificados anônimos | Compre e venda sem conta, sem email. Pagamento com Monero. Chat criptografado ponta a ponta. |
| **ru** | kashilo.com – Анонимные объявления | Покупайте и продавайте без аккаунта, без email. Оплата Monero. Сквозное шифрование чата. |

### Umsetzung

Die `index.html` enthält die Standard-Meta-Tags (de).
Für sprachspezifische OG-Tags bei Social-Media-Shares:
Der OG-Proxy kann um einen `?lang=` Parameter erweitert werden.

Die `i18n.js` `updateDOM()` Methode aktualisiert `document.title`, `og:title/description`
und `twitter:title/description` dynamisch bei jedem Sprachwechsel (i18n-Keys `meta.title`, `meta.description`).

---

## Checkliste vor Alpha-Start

- [ ] Directus: Collection `invite_codes` anlegen (Schema siehe oben)
- [ ] PHP: `invite/validate.php` deployen auf `pow.kashilo.com`
- [ ] PHP: `config.php` → `LISTING_FEE` auf 0.01 setzen
- [ ] PHP: `config.php` → `REQUIRE_INVITE_CODE = true`
- [ ] Frontend: Invite-Code-Feld in `auth-modal.js` einbauen
- [x] Frontend: Meta-Description i18n-Keys in alle 7 Sprachen
- [x] Frontend: Impressum-Seite (Entwurf, alle 7 Sprachen, Platzhalter für Adressdaten)
- [x] Frontend: Datenschutz, AGB, Über uns — alle 7 Sprachen
- [ ] Rechtliches: Impressum-Platzhalter ausfüllen (Name, Adresse, UID)
- [ ] Rechtliches: AGB + Datenschutz durch Fachperson prüfen lassen
- [ ] Rechtliches: Gewerbeanmeldung / Einzelunternehmen
- [ ] 10–20 Invite-Codes in Directus erstellen
- [ ] Codes verteilen (r/Monero, Matrix, persönlich)
- [ ] Feedback-Kanal einrichten (Matrix-Raum)
