Initial: RAPPORT-HOST Iteration 1 (proprietär)
Kommerzielle Hosting-/Abo-Plattform für Rapport-Instanzen. - React-Frontend (Vite/JSX): Landing, Register, Login, Plans, Dashboard - Node/Express-Backend: Auth (bcrypt+JWT), Stripe-Billing, Provisioning - HOST-Postgres-Schema: accounts, subscriptions, instances - Provisioning-Interface + Modell-A-Adapter (Studio im geteilten Stack) - MOCK-Modus: voller End-to-End-Flow ohne Stripe/Rapport-Stack testbar - Idempotentes Fulfillment (Upsert auf stripe_subscription_id) - docker-compose für lokale host-db; identisch auf Hetzner deploybar E2E lokal verifiziert: Register -> Checkout(mock) -> Instanz -> Idempotenz. Lizenz: proprietär (kein AGPL-Code eingebunden, nur Netzwerk-API zur Familie). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import React from "react";
|
||||
import { auth } from "../api.js";
|
||||
|
||||
export default function Landing({ navigate }) {
|
||||
return (
|
||||
<div className="wrap">
|
||||
<div className="nav">
|
||||
<div className="brand">RAPPORT</div>
|
||||
<div style={{ display: "flex", gap: 16, alignItems: "center" }}>
|
||||
<button className="ghost" onClick={() => navigate("/plans")}>Preise</button>
|
||||
{auth.isLoggedIn ? (
|
||||
<button className="primary" style={{ width: "auto", padding: "8px 18px" }} onClick={() => navigate("/dashboard")}>
|
||||
Dashboard
|
||||
</button>
|
||||
) : (
|
||||
<button className="primary" style={{ width: "auto", padding: "8px 18px" }} onClick={() => navigate("/login")}>
|
||||
Anmelden
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: "80px 0", maxWidth: 620 }}>
|
||||
<h1 style={{ fontSize: 44, lineHeight: 1.1, margin: 0 }}>
|
||||
Ihre eigene Rapport-Instanz.<br />In Minuten startklar.
|
||||
</h1>
|
||||
<p className="muted" style={{ fontSize: 15, lineHeight: 1.6, marginTop: 20 }}>
|
||||
Studio-Management für Architekturbüros — gehostet, gewartet und
|
||||
gesichert. Registrieren, Abo wählen, loslegen. Ihre Daten in der
|
||||
Schweiz.
|
||||
</p>
|
||||
<div style={{ display: "flex", gap: 12, marginTop: 28 }}>
|
||||
<button className="primary" style={{ width: "auto", padding: "13px 28px" }} onClick={() => navigate("/register")}>
|
||||
Jetzt starten
|
||||
</button>
|
||||
<button className="primary" style={{ width: "auto", padding: "13px 28px", background: "transparent", color: "var(--ink)", border: "1px solid var(--line)" }} onClick={() => navigate("/plans")}>
|
||||
Preise ansehen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user