Files
kashilo/docs/LAUNCH-PLAN.md

8.5 KiB
Raw Blame History

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

// 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:

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:

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:

// 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.phpLISTING_FEE auf 0,10 setzen
  2. Invite-Code: REQUIRE_INVITE_CODEfalse
  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.phpLISTING_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.phpLISTING_FEE auf 0.01 setzen
  • PHP: config.phpREQUIRE_INVITE_CODE = true
  • Frontend: Invite-Code-Feld in auth-modal.js einbauen
  • Frontend: Meta-Description i18n-Keys in alle 7 Sprachen
  • Frontend: Impressum-Seite (Entwurf, alle 7 Sprachen, Platzhalter für Adressdaten)
  • 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)