feat: Wordeck-Web-Branding + Manifest-Cutover
Some checks are pending
CI / validate (push) Waiting to run
Some checks are pending
CI / validate (push) Waiting to run
Cards-zu-Wordeck-Umbennung im Web-Layer komplett: - app-manifest.json: id, name, homepage, icon, base_url, deep_link_scheme, link_patterns alle auf wordeck. tools[].name auch (cards.create → wordeck.create — bei mana-mcp wird das beim re-upsert konsumiert). - 5 i18n-Files (de/en/fr/es/it): App-Beschreibung von Cardecky-zu-Wordeck- Wording, USP "text-first" wo es passt. - 11 Routes mit Page-<title>: Cardecky → Wordeck. - CSP connect-src ergänzt um api.wordeck.com (cardecky-api bleibt während Übergang). - AASA exposed jetzt BEIDE Bundle-IDs (ev.mana.cardecky alt + ev.mana.wordeck neu) — die alte Native bleibt während der Ω-3 Bauphase funktional. - UI-Slug-Vorschau (PublishDeckModal, +page, me/published): wordeck.com. DNS für wordeck.com + api.wordeck.com + www.wordeck.com sind als Cloudflare-Tunnel-CNAMEs angelegt; cloudflared-Ingress auf mana-server patched + reloaded. wordeck.com antwortet HTTP 200 mit Cards-Container (Branding-Update hier macht das jetzt zu Wordeck). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
22927fbe59
commit
39fe22a018
21 changed files with 58 additions and 52 deletions
|
|
@ -1,31 +1,31 @@
|
|||
{
|
||||
"$schema": "https://pkg.mana.how/@mana/shared-share-protocol/0.1/manifest.json",
|
||||
"schema_version": "0.1",
|
||||
"id": "cards",
|
||||
"name": "Cardecky",
|
||||
"id": "wordeck",
|
||||
"name": "Wordeck",
|
||||
"version": "1.0.0",
|
||||
"homepage": "https://cardecky.mana.how",
|
||||
"icon": "https://cardecky.mana.how/icon-512.png",
|
||||
"description": "Spaced-repetition flashcards with FSRS scheduling.",
|
||||
"description_de": "Lernkarten mit Spaced-Repetition (FSRS).",
|
||||
"homepage": "https://wordeck.com",
|
||||
"icon": "https://wordeck.com/icon-512.png",
|
||||
"description": "Spaced-repetition flashcards with FSRS scheduling — text-first, no images, no audio.",
|
||||
"description_de": "Spaced Repetition, text-first. Nur Worte, keine Bilder, kein Audio.",
|
||||
"ownership": { "kind": "verein" },
|
||||
"tier_required": "beta",
|
||||
"endpoints": {
|
||||
"base_url": "https://cardecky.mana.how",
|
||||
"base_url": "https://wordeck.com",
|
||||
"health": "/healthz",
|
||||
"dsgvo_export": "/api/v1/dsgvo/export",
|
||||
"search": "/api/v1/search",
|
||||
"share_receive": "/api/v1/share/receive",
|
||||
"tool_invoke": "/api/v1/tools/:name",
|
||||
"deep_link_scheme": "cards://",
|
||||
"deep_link_scheme": "wordeck://",
|
||||
"link_patterns": [
|
||||
{
|
||||
"pattern": "card/(?<id>[a-z0-9_-]+)",
|
||||
"template": "https://cardecky.mana.how/c/{id}"
|
||||
"template": "https://wordeck.com/c/{id}"
|
||||
},
|
||||
{
|
||||
"pattern": "deck/(?<id>[a-z0-9_-]+)",
|
||||
"template": "https://cardecky.mana.how/d/{id}"
|
||||
"template": "https://wordeck.com/d/{id}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -37,14 +37,14 @@
|
|||
],
|
||||
"tools": [
|
||||
{
|
||||
"name": "cards.create",
|
||||
"name": "wordeck.create",
|
||||
"description": "Erzeugt eine Lernkarte für den authentifizierten User.",
|
||||
"input_schema": { "$ref": "/payload-schemas/create-card-input.json" },
|
||||
"output_schema": { "$ref": "/payload-schemas/card.json" },
|
||||
"auth": "user_token"
|
||||
},
|
||||
{
|
||||
"name": "cards.search",
|
||||
"name": "wordeck.search",
|
||||
"description": "Sucht in den Lernkarten des authentifizierten Users.",
|
||||
"input_schema": { "$ref": "/payload-schemas/search-input.json" },
|
||||
"output_schema": { "$ref": "/payload-schemas/search-output.json" },
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const CSP_POLICY = [
|
|||
"img-src 'self' data: blob:",
|
||||
"font-src 'self' data:",
|
||||
// XHR/fetch-Ziele: eigene API + Auth-Portal + LLM/Share/MCP-Plattform.
|
||||
"connect-src 'self' https://cardecky-api.mana.how https://auth.mana.how https://share.mana.how https://mcp.mana.how",
|
||||
"connect-src 'self' https://api.wordeck.com https://cardecky-api.mana.how https://auth.mana.how https://share.mana.how https://mcp.mana.how",
|
||||
"media-src 'self' blob:",
|
||||
"frame-ancestors 'none'",
|
||||
"base-uri 'self'",
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@
|
|||
<div class="field">
|
||||
<label class="field-label" for="pub-slug">Marketplace-Slug</label>
|
||||
<div class="slug-row">
|
||||
<span class="slug-prefix">cardecky.mana.how/d/</span>
|
||||
<span class="slug-prefix">wordeck.com/d/</span>
|
||||
<input
|
||||
id="pub-slug"
|
||||
type="text"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export const de: TranslationNode = {
|
|||
landing: {
|
||||
welcome: 'Lernkarten mit Spaced-Repetition.',
|
||||
intro:
|
||||
'Cardecky ist die föderierte Karteikarten-App des Vereins mana e.V. — FSRS-Scheduler, Cloze-Karten, Anki-Import.',
|
||||
'Wordeck ist die föderierte Karteikarten-App des Vereins mana e.V. — FSRS-Scheduler, Cloze-Karten, Anki-Import.',
|
||||
cta_login: 'Login (dev)',
|
||||
dev_user_prompt: 'User-ID (dev):',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const en: TranslationNode = {
|
|||
landing: {
|
||||
welcome: 'Spaced-repetition flashcards.',
|
||||
intro:
|
||||
'Cardecky is the federated flashcard app of mana e.V. — FSRS scheduler, cloze cards, Anki import.',
|
||||
'Wordeck is the federated flashcard app of mana e.V. — FSRS scheduler, cloze cards, Anki import.',
|
||||
cta_login: 'Login (dev)',
|
||||
dev_user_prompt: 'User ID (dev):',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const es: TranslationNode = {
|
|||
landing: {
|
||||
welcome: 'Tarjetas de memoria con repetición espaciada.',
|
||||
intro:
|
||||
'Cardecky es la app federada de flashcards de mana e.V. — planificador FSRS, tarjetas cloze, importación Anki.',
|
||||
'Wordeck es la app federada de flashcards de mana e.V. — planificador FSRS, tarjetas cloze, importación Anki.',
|
||||
cta_login: 'Iniciar sesión (dev)',
|
||||
dev_user_prompt: 'ID de usuario (dev):',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const fr: TranslationNode = {
|
|||
landing: {
|
||||
welcome: 'Fiches de révision espacée.',
|
||||
intro:
|
||||
"Cardecky est l'application de fiches fédérée de mana e.V. — planificateur FSRS, cartes à trous, import Anki.",
|
||||
"Wordeck est l'application de fiches fédérée de mana e.V. — planificateur FSRS, cartes à trous, import Anki.",
|
||||
cta_login: 'Connexion (dev)',
|
||||
dev_user_prompt: 'ID utilisateur (dev) :',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const it: TranslationNode = {
|
|||
landing: {
|
||||
welcome: 'Flashcard con ripetizione spaziata.',
|
||||
intro:
|
||||
"Cardecky è l'app di flashcard federata di mana e.V. — pianificatore FSRS, carte cloze, importazione Anki.",
|
||||
"Wordeck è l'app di flashcard federata di mana e.V. — pianificatore FSRS, carte cloze, importazione Anki.",
|
||||
cta_login: 'Accesso (dev)',
|
||||
dev_user_prompt: 'ID utente (dev):',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
function callbackUrl(): string {
|
||||
const base =
|
||||
typeof window !== 'undefined' ? window.location.origin : 'https://cardecky.mana.how';
|
||||
typeof window !== 'undefined' ? window.location.origin : 'https://wordeck.com';
|
||||
const next = page.url.searchParams.get('next');
|
||||
const nextParam = next ? `?next=${encodeURIComponent(next)}` : '';
|
||||
return `${base}/auth/callback${nextParam}`;
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import { env } from '$env/dynamic/public';
|
|||
import type { RequestHandler } from './$types';
|
||||
|
||||
/**
|
||||
* Apple App-Site Association für die cards-native iOS-App.
|
||||
* Apple App-Site Association für die Wordeck-iOS-App.
|
||||
*
|
||||
* Apple holt diese Datei beim ersten App-Launch (und gelegentlich danach)
|
||||
* von `https://cardecky.mana.how/.well-known/apple-app-site-association`
|
||||
* und vergleicht sie mit dem `applinks:cardecky.mana.how`-Entitlement
|
||||
* der App. Bei Match werden Links auf `/d/<slug>` direkt in die App
|
||||
* geöffnet statt im Browser.
|
||||
* von `https://wordeck.com/.well-known/apple-app-site-association` (sowie
|
||||
* von der Legacy-Domain `https://cardecky.mana.how/...`) und vergleicht
|
||||
* sie mit dem `applinks:`-Entitlement der App. Bei Match werden Links
|
||||
* auf `/d/<slug>` direkt in die App geöffnet statt im Browser.
|
||||
*
|
||||
* **Pflichtbedingungen:**
|
||||
* 1. Antwort MUSS `Content-Type: application/json` haben (nicht
|
||||
|
|
@ -21,22 +21,28 @@ import type { RequestHandler } from './$types';
|
|||
* Developer-Accounts gesetzt werden, sonst akzeptiert Apple die AASA
|
||||
* nicht.
|
||||
*
|
||||
* Cross-Ref: `cards-native/docs/RELEASE_CHECKLIST.md` → "Server-seitige
|
||||
* Vorbedingungen".
|
||||
* Beide Bundle-IDs sind aktiv:
|
||||
* - `ev.mana.cardecky` (cards-native v0.9.4, End-of-Life)
|
||||
* - `ev.mana.wordeck` (Wordeck-Native ab Ω-3, neue ASC-Eintragung)
|
||||
*
|
||||
* Cross-Ref: `mana/docs/playbooks/WORDECK_REBRAND.md`,
|
||||
* `cards-native/docs/RELEASE_CHECKLIST.md` → "Server-seitige Vorbedingungen".
|
||||
*/
|
||||
export const GET: RequestHandler = async () => {
|
||||
const teamId = env.PUBLIC_APPLE_TEAM_ID ?? 'XXXXXXXXXX';
|
||||
const bundleId = 'ev.mana.cardecky';
|
||||
|
||||
const payload = {
|
||||
applinks: {
|
||||
apps: [],
|
||||
details: [
|
||||
{
|
||||
appID: `${teamId}.${bundleId}`,
|
||||
// `/d/*` Deck-Slugs, `/u/*` User-Profile, `/auth/*` für
|
||||
// Reset-/Verify-Mail-Klicks von mana-auth — der Mail-Link
|
||||
// öffnet damit direkt die App via Universal Link.
|
||||
// Legacy: cards-native v0.9.4 (End-of-Life nach Wordeck-Cutover)
|
||||
appID: `${teamId}.ev.mana.cardecky`,
|
||||
paths: ['/d/*', '/u/*', '/auth/*'],
|
||||
},
|
||||
{
|
||||
// Aktuell: Wordeck-Native (neuer Bundle ab Ω-3)
|
||||
appID: `${teamId}.ev.mana.wordeck`,
|
||||
paths: ['/d/*', '/u/*', '/auth/*'],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/**
|
||||
* Web-Fallback für die Reset-Password-Mail von mana-auth.
|
||||
*
|
||||
* Auf iOS-Geräten mit installierter Cardecky-App öffnet Apple den
|
||||
* Auf iOS-Geräten mit installierter Wordeck-App öffnet Apple den
|
||||
* Universal Link direkt in der App, diese Page wird nie gerendert.
|
||||
*
|
||||
* Für alle anderen User (kein iOS, App nicht installiert, Desktop)
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Passwort zurücksetzen — Cardecky</title>
|
||||
<title>Passwort zurücksetzen — Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<main class="container">
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/**
|
||||
* Web-Fallback für die Verify-Email-Mail von mana-auth.
|
||||
*
|
||||
* Auf iOS-Geräten mit installierter Cardecky-App öffnet Apple den
|
||||
* Auf iOS-Geräten mit installierter Wordeck-App öffnet Apple den
|
||||
* Universal Link direkt in der App. Für alle anderen User leiten
|
||||
* wir zum Better-Auth-Verify-Endpoint auf auth.mana.how weiter,
|
||||
* der den Token konsumiert und auf das Auth-Portal redirected.
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Email bestätigen — Cardecky</title>
|
||||
<title>Email bestätigen — Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<main class="container">
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{deck?.title ?? slug} · Cardecky</title>
|
||||
<title>{deck?.title ?? slug} · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if loading}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Meine Decks · Cardecky</title>
|
||||
<title>Meine Decks · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="space-y-10">
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{deck ? t('print.title', { deck: deck.name }) : t('print.loading')} · Cardecky</title>
|
||||
<title>{deck ? t('print.title', { deck: deck.name }) : t('print.loading')} · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="screen-controls">
|
||||
|
|
|
|||
|
|
@ -78,12 +78,12 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Explore · Cardecky</title>
|
||||
<title>Explore · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="space-y-10">
|
||||
<header>
|
||||
<h1 class="text-3xl font-semibold">Cardecky-Library</h1>
|
||||
<h1 class="text-3xl font-semibold">Wordeck-Library</h1>
|
||||
</header>
|
||||
|
||||
{#if loadingExplore}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<svelte:head>
|
||||
<title>Hilfe — Cardecky</title>
|
||||
<meta name="description" content="Hilfe und Support für Cardecky." />
|
||||
<title>Hilfe — Wordeck</title>
|
||||
<meta name="description" content="Hilfe und Support für Wordeck." />
|
||||
</svelte:head>
|
||||
|
||||
<main class="page">
|
||||
<h1>Hilfe & Support</h1>
|
||||
|
||||
<p class="lead">
|
||||
Cardecky wird vom Verein <strong>mana e.V.</strong> (i. G.) betrieben.
|
||||
Wordeck wird vom Verein <strong>mana e.V.</strong> (i. G.) betrieben.
|
||||
Bei Fragen oder Problemen melde dich direkt bei uns — wir antworten meist innerhalb
|
||||
eines Tages.
|
||||
</p>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<h3>Wie funktioniert das Lern-Schema?</h3>
|
||||
<p>
|
||||
Cardecky nutzt <a href="https://github.com/open-spaced-repetition/fsrs4anki">FSRS</a>
|
||||
Wordeck nutzt <a href="https://github.com/open-spaced-repetition/fsrs4anki">FSRS</a>
|
||||
(Free Spaced Repetition Scheduler), den genauesten offenen Algorithmus für
|
||||
Karteikarten. Karten kommen wieder, wenn deine Erinnerung sie braucht — und nicht
|
||||
nach starren Intervallen.
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
und beim nächsten Online-Moment synchronisiert.
|
||||
</p>
|
||||
|
||||
<h3>Was ist mit dem Marketplace (Cardecky)?</h3>
|
||||
<h3>Was ist mit dem Marketplace (Wordeck)?</h3>
|
||||
<p>
|
||||
Der Marketplace unter <a href="/explore">Entdecken</a> ist die offene
|
||||
Sammlung freigegebener Decks. Subscriben heißt: das Deck wird in deine eigene
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Meine Forks · Cardecky</title>
|
||||
<title>Meine Forks · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="mx-auto max-w-4xl space-y-6">
|
||||
|
|
|
|||
|
|
@ -96,12 +96,12 @@
|
|||
const pageSubtitle = $derived(
|
||||
author
|
||||
? `@${author.slug} · ${decks.length} Deck${decks.length !== 1 ? 's' : ''} veröffentlicht`
|
||||
: 'Lege dein Author-Profil an um eigene Decks im Cardecky-Marketplace zu veröffentlichen.'
|
||||
: 'Lege dein Author-Profil an um eigene Decks im Wordeck-Marketplace zu veröffentlichen.'
|
||||
);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle} · Cardecky</title>
|
||||
<title>{pageTitle} · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="page-shell">
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
<label class="field">
|
||||
<span class="field-label">
|
||||
Slug <span class="slug-preview"
|
||||
>{formSlug ? `cardecky.mana.how/a/${formSlug}` : 'url-safe, z. B. till-hoffmann'}</span
|
||||
>{formSlug ? `wordeck.com/a/${formSlug}` : 'url-safe, z. B. till-hoffmann'}</span
|
||||
>
|
||||
</span>
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Meine Abos · Cardecky</title>
|
||||
<title>Meine Abos · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="mx-auto max-w-4xl space-y-6">
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{author?.display_name ?? slug} · Cardecky</title>
|
||||
<title>{author?.display_name ?? slug} · Wordeck</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if loading}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue