Files
kashilo/docs/LAUNCH-PLAN.md

260 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Launch Plan kashilo.com
## Release-Phasen
| Phase | Preis pro Anzeige | Dauer | Zugang |
|-------|-------------------|-------|--------|
| **Closed Alpha** | 0,01 € / 0,01 USD / 0,01 CHF | 46 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
- **1020 Codes** mit je 510 max_uses → 50200 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
- [ ] 1020 Invite-Codes in Directus erstellen
- [ ] Codes verteilen (r/Monero, Matrix, persönlich)
- [ ] Feedback-Kanal einrichten (Matrix-Raum)