ClaudeandClaude Opus 5.5 3e4bc21f00 feat(account): Benutzername beim Registrieren, im Konto-Menü und als einmalige Abfrage
- Neu `account/profile.ts`: Muster, Sperrliste und Schlüssel (ein Test vergleicht
  sie mit `deploy/api/common.js`), Profile lesen (`getUsername`, `usernamesFor`
  gesammelt in einer Abfrage und zwischengespeichert, bei einem Fehler nur die
  bekannten Namen), `isUsernameTaken`, `saveUsername` (POST /api/profil,
  Zwischenspeicher + `onUsernameChange`), `myUsername`/`loadMyUsername` und der
  Merker `aircard.usernamePrompted`. `IDS.profiles`.
- Neu `account/username-dialog.ts`: Dialog „Benutzername wählen“ in den Modi
  prompt („Später“), required („Abbrechen“) und change (vorbelegt), Fehler am
  Feld, Busy-Sperre, höchstens ein Dialog zur Zeit; dazu `requireUsername()`.
- Registrieren: Pflichtfeld „Benutzername“ vor der E-Mail. Muster, Sperrliste und
  Verfügbarkeit werden vor dem Anlegen des Kontos geprüft (kein halbes Konto);
  danach wird der Name gespeichert, scheitert das, schließt der Login-Dialog und
  der Namensdialog fragt.
- Konto-Menü: „@name“ oben, die E-Mail klein darunter, Eintrag „Benutzername
  ändern“ bzw. „Benutzername wählen“.
- main.ts: Name nach Start und Anmeldung lesen; ohne Namen einmal pro Sitzung der
  Dialog „prompt“ (nicht, wenn der Name nicht lesbar ist).
- Texte in `en.ts`, Stile in `account.css`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 07:22:15 +00:00
2026-10-05 06:23:08 +00:00

AirCard-IOS

Inoffizielles Hobbyprojekt, mit dem man eigene Kartenmotive für Apple Wallet unter https://aircard-ios.org gestalten kann. Bild hochladen, Vorlage und Community-Logo wählen, als PNG herunterladen – oder mit Konto speichern und in der Community-Galerie veröffentlichen. Keine Verbindung zu Apple, Visa, Mastercard, UnionPay, American Express, JCB oder Discover; Logos und Motive stammen von Nutzern, alle Marken gehören ihren Inhabern.

Funktionen

  • Editor (/gestalten): Bild hochladen, Vorlage, Ausschnitt, Details (Hell/Dunkel) und das Logo oben links (AirCard-IOS) wählen, als PNG herunterladen oder mit Konto speichern („Meine Karten“, /karten).
  • Community-Logos unten rechts auf der Karte: Angemeldete laden Logos hoch (PNG, JPG, WebP oder SVG; der Browser schneidet sie zu, verkleinert sie auf höchstens 720 × 250 px und lädt ein PNG hoch), alle können sie wählen. Eingebaute Marken-Logos gibt es nicht. Je Konto und Logo gibt es ein Herz (nur angemeldet); die Herzen bestimmen die Sortierung „Beliebt“. Logos lassen sich melden (ab 3 Meldern aus verschiedenen Netzen werden sie ausgeblendet) und vom Hochlader löschen; Admins (Label admin) sehen zusätzlich „Gemeldet“ und „Ausgeblendet“.
  • Community-Galerie (Startseite / und /community/<id>): Karten veröffentlichen, ansehen, melden und zurückziehen.
  • Deutsch und Englisch: Die Sprache folgt der Browsersprache; der Sprachknopf in der Kopfzeile schaltet ohne Neuladen um und merkt sich die Wahl. Daneben steht ein GitHub-Link zum Original-Projekt AirCard-iOS.

Aufbau

web/ – Vite + TypeScript ohne Framework. Frontend-Module in src/:

  • card/ – Geometrie, Zuschnitt, Canvas-Rendering (keine DOM-Abhängigkeiten, einzeln testbar)
  • editor/ – UI (Vorlagen, Vorschau, Download, Speichern)
  • logos/ – Community-Logos: Lesen aus Appwrite, Auswahl mit Herzen und Infozeile (Melden, Löschen, Admin), Hochladen mit Aufbereitung im Browser (Zuschnitt, Verkleinern, PNG)
  • community/ – Galerie: Lesen, Veröffentlichen, Melden, Aufrufe des API-Dienstes
  • account/ – Appwrite-Client, Auth, Kartenverwaltung
  • i18n/ – Deutsch und Englisch: t('Deutscher Text') und msg('…'), Wörterbuch Deutsch → Englisch in en.ts (ein Test verlangt für jeden Text einen Eintrag)
  • pages/ – Routen (/, /gestalten, /karten, /community/<id>, /passwort-neu via History-API)
  • shell/ – Kopfzeile (GitHub-Link, Sprachknopf, Hell/Dunkel), Fußzeile, Spenden-Banner

deploy/ – Webhook-Router (Port 8087), Build-Skript (deploy.sh), nginx-Config, Traefik-Route für Appwrite.

docs/ – Spec, Plan, Appwrite-Konfiguration.

Lokal entwickeln

cd web
npm ci
npm run dev          # Entwicklungsserver http://localhost:5173

Login und Speichern brauchen die Appwrite-API. Ohne Einstellung gilt als Endpoint ${location.origin}/v1 (der Entwicklungsserver hat keinen Proxy dafür, es würde also der Vite-Server selbst gefragt). Für die lokale Entwicklung deshalb in web/.env.local (steht über .env* in .gitignore) den Endpoint setzen:

VITE_APPWRITE_ENDPOINT=https://appwrite.webklar.com/v1

Die Projekt-ID ist als Standard im Code hinterlegt (6ac2130a00289343d6d5, VITE_APPWRITE_PROJECT_ID überschreibt sie). Damit Appwrite den lokalen Host akzeptiert, muss die Web-Plattform localhost in der Appwrite-Console eingetragen sein (Projekt → Overview → Integrations → Platforms). Der Produktions-Build bekommt VITE_APPWRITE_ENDPOINT=https://aircard-ios.org/v1 aus der Container-Umgebung (deploy/compose-snippet.yml).

Tests

Im Frontend (web/):

cd web
npx vitest run               # Unit-Tests (alle Module unter src/)
npx tsc --noEmit             # TypeScript-Prüfung, auch der Tests
npm run build                # Produktions-Build; die Prüfung davor nutzt tsconfig.build.json (ohne Tests)

Im Repo-Wurzelverzeichnis:

node --test deploy/webhook-server.test.js        # Webhook-Server (deploy.sh wird dort durch einen Stub ersetzt)
node --test deploy/deploy.test.js                # deploy.sh (echtes Skript, lokaler git-Remote, npm-Stub)
node --test "deploy/api/*.test.js"               # API-Dienst (Glob in Anführungszeichen)
node --test web/scripts/appwrite-setup.test.mjs  # Appwrite-Schema-Skript

Deploy

Automatisch: Push auf main → Gitea-Webhook → Container webklar-aircard-build führt npm ci und npm run build (Typprüfung ohne Tests, dann vite build) aus → Ergebnis nach out/ → nginx webklar-aircard liefert.

Reihenfolge, wenn eine Änderung auch Schema und API braucht (wie die Community-Logos): erst das Schema anlegen, dann die API-Dateien ersetzen und neu starten, zuletzt main pushen. Die Schritte stehen in deploy/README.md, Abschnitt „Reihenfolge bei Änderungen an Schema, API und Seite“.

Manuell:

docker exec webklar-aircard-build sh /deploy.sh

Starten nur mit:

docker compose up -d aircard-build aircard aircard-api

aircard-api ist der kleine API-Dienst der Community-Galerie, der Community-Logos und der Benutzernamen (deploy/api/, Route aircard-ios.org/api, siehe deploy/api/README.md).

Die Appwrite-API wird über /home/webklar/apps/traefik/dynamic/aircard.yml geroutet (Vorlage: deploy/traefik/aircard.yml): Requests auf aircard-ios.org/v1 mit Header X-Appwrite-Project: 6ac2130a00289343d6d5 gehen an den Appwrite-Container. Ohne diesen Header antwortet der nginx der Seite mit 404.

Appwrite

Projekt „AirCard“ auf appwrite.webklar.com:

  • Projekt-ID (öffentlich, von Appwrite generiert): 6ac2130a00289343d6d5. Sie steht in deploy/traefik/aircard.yml, in /home/webklar/apps/.env (AIRCARD_APPWRITE_PROJECT_ID) und als Standard in web/src/account/appwrite.ts.
  • Datenbank: aircard; Tabellen: cards (private Karten), gallery und reports (Community-Galerie, Meldungen), logos, logo_likes und logo_reports (Community-Logos, Herzen, Meldungen) und profiles (Benutzernamen, eine Zeile je Konto, Unique-Index auf dem klein geschriebenen Namen); Buckets: card-images, gallery-images und logo-images (das Skript unten legt sie an und prüft sie)
  • Console-Einstellungen laut docs/appwrite-console.md (Soll-Stand, nicht maschinell geprüft; --check prüft nur das Schema): Auth mit E-Mail + Passwort, Sitzungsdauer 30 Tage, max. 5 Sitzungen pro Nutzer, Nutzerlimit 2000, Web-Plattformen aircard-ios.org und localhost. Schritte 3 und 4 dort (Auth-Härtung, Dienste abschalten) sind optional und am Live-Projekt unbestätigt.

Schema prüfen:

node --env-file=/home/webklar/apps/.env web/scripts/appwrite-setup.mjs --check

Schema erstmalig anlegen:

node --env-file=/home/webklar/apps/.env web/scripts/appwrite-setup.mjs

Umgebungsvariablen (in /home/webklar/apps/.env):

  • AIRCARD_APPWRITE_PROJECT_ID – Projekt-ID (idempotent im Skript lesbar)
  • AIRCARD_APPWRITE_API_KEY – API-Key aircard-provision (nur für Setup)

Hinweis

Inoffizielles Hobbyprojekt. Alle Marken gehören ihren Inhabern.

S
Description
No description provided
Readme
1.9 MiB
0 Stars 1 Watchers 0 Forks
Languages
TypeScript 74.9%
JavaScript 21.8%
CSS 2.8%
Shell 0.4%
HTML 0.1%