feat(landing): Marketing-Astro auf wordeck.com LIVE
Some checks are pending
CI / validate (push) Waiting to run

Astro-Landing als neuer Apex-Container (:3202), gebaut mit
@mana/marketing-kit. Probe-Cutover der Welle-1-Charge (niedrigstes
Compliance-Risiko, höchste Ship-Reife). Anki-Migration als
Akquise-Anker; /anki-import als dedicated Long-Tail-Page mit
3-Schritt-Anleitung + FAQ + JSON-LD FAQPage (Sitemap-Priorität 0.95).

- apps/landing/ — index, anki-import, ueber, mitwirken
  + robots/llms/sitemap-Endpoints
- infrastructure/macmini/docker-compose.landing.yml — Port 3202
- .gitignore += .astro

Cutover-Playbook: mana/docs/playbooks/LANDING_CUTOVER.md
Domain-Status:
  wordeck.com          → :3202  (Marketing, NEU)
  www.wordeck.com      → :3202  (Marketing, NEU)
  app.wordeck.com      → :5181  (Web-App, NEU als Subdomain)
  api.wordeck.com      → :3191  (API, unverändert)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-20 21:38:41 +02:00
parent 823560900c
commit e0605b2f2e
17 changed files with 638 additions and 0 deletions

1
.gitignore vendored
View file

@ -70,3 +70,4 @@ apps/landing/.astro
# NPM Auth — Verdaccio-Token soll nie in git
.npmrc
.astro

31
apps/landing/Dockerfile Normal file
View file

@ -0,0 +1,31 @@
# Multi-stage build for the wordeck-landing Astro surface.
#
# Build context is the repo root (set in
# infrastructure/macmini/docker-compose.landing.yml as `../..`).
#
# NPM_AUTH_TOKEN is required at build time (BuildKit secret) so pnpm
# can fetch @mana/marketing-kit from npm.mana.how (Verdaccio).
FROM node:20-alpine AS builder
WORKDIR /repo
RUN corepack enable && corepack prepare pnpm@9.15.9 --activate
# Workspace shell first (cache-friendly).
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml .npmrc ./
COPY apps/landing/package.json ./apps/landing/
RUN --mount=type=secret,id=npm_token,env=NPM_AUTH_TOKEN \
pnpm install --filter @wordeck/landing --frozen-lockfile 2>/dev/null \
|| pnpm install --filter @wordeck/landing
COPY apps/landing ./apps/landing
WORKDIR /repo/apps/landing
RUN pnpm build
FROM nginx:1.27-alpine AS production
COPY --from=builder /repo/apps/landing/dist /usr/share/nginx/html
COPY apps/landing/infrastructure/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD wget -qO- http://127.0.0.1/ >/dev/null 2>&1 || exit 1

View file

@ -0,0 +1,14 @@
import { defineConfig } from 'astro/config'
// wordeck-Marketing-Landing.
//
// Statisch, prerendered. Apex `wordeck.com` serviert das Build-Output;
// `app.wordeck.com` läuft separat (SvelteKit-App in `apps/web/`).
export default defineConfig({
site: 'https://wordeck.com',
output: 'static',
trailingSlash: 'never',
build: {
format: 'file',
},
})

View file

@ -0,0 +1,30 @@
# wordeck-landing — Marketing-Astro auf wordeck.com.
#
# Eigenständiger Compose-Stack neben dem App-Stack
# (apps/api + apps/web). Nutzt das gleiche `wordeck`-COMPOSE_PROJECT_NAME,
# damit die Container-Namen im selben Namespace landen.
#
# Cutover-Plan: mana/docs/playbooks/LANDING_CUTOVER.md
# Port: 3202 (siehe mana/docs/PORTS.md → Marketing-Landings)
#
# Cloudflared-Tunnel (in ~/projects/managarten/cloudflared-config.yml):
# wordeck.com → http://localhost:3202 (NEU, nach Cutover)
# www.wordeck.com → http://localhost:3202 (NEU, nach Cutover)
# app.wordeck.com → http://localhost:5181 (NEU — App-Subdomain)
# api.wordeck.com → http://localhost:3191 (unverändert)
services:
wordeck-landing:
build:
context: ../../../..
dockerfile: apps/landing/Dockerfile
secrets: [npm_token]
image: wordeck-landing:latest
container_name: wordeck-landing
restart: unless-stopped
ports:
- '3202:80'
secrets:
npm_token:
file: ~/.npm_token

View file

@ -0,0 +1,41 @@
# nginx config für wordeck-landing Astro statisch, no SPA fallback.
#
# Astro baut mit format='file' und trailingSlash='never', d.h.
# /anki-import /anki-import.html. try_files-Kette deckt das ab.
server {
listen 80 default_server;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Plain-Text-Endpoints (Astro-API-Routes wurden als .txt/.xml gebaut).
location = /robots.txt {
default_type "text/plain; charset=utf-8";
try_files $uri =404;
}
location = /llms.txt {
default_type "text/plain; charset=utf-8";
try_files $uri =404;
}
location = /sitemap.xml {
default_type "application/xml; charset=utf-8";
try_files $uri =404;
}
# Canonical paths .html siblings; unknown paths 404.
location / {
try_files $uri $uri.html $uri/ =404;
}
# Astro asset bundles long-cache.
location /_astro/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Standard MIME-Optimierungen.
gzip on;
gzip_types text/plain text/css text/javascript application/javascript application/json application/xml application/manifest+json image/svg+xml;
gzip_min_length 1024;
}

20
apps/landing/package.json Normal file
View file

@ -0,0 +1,20 @@
{
"name": "@wordeck/landing",
"private": true,
"version": "0.1.0",
"type": "module",
"description": "Marketing-Landing für wordeck.com — Astro, statisch, SEO/LLM-optimiert. App selbst läuft auf app.wordeck.com.",
"scripts": {
"dev": "astro dev --port 4325",
"build": "astro build",
"preview": "astro preview --port 4326",
"check": "astro check"
},
"dependencies": {
"@mana/marketing-kit": "^0.1.0",
"astro": "^4.16.0"
},
"devDependencies": {
"typescript": "^5.9.3"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

1
apps/landing/src/env.d.ts vendored Normal file
View file

@ -0,0 +1 @@
/// <reference path="../.astro/types.d.ts" />

View file

@ -0,0 +1,87 @@
import type { AppMeta, FaqItem, Feature, Stat } from '@mana/marketing-kit'
/**
* Single Source of Truth für wordeck-Marketing-Daten.
*
* Hook ist Anki ohne Akrobatik" Anki-Migration als Akquise-Anker,
* analog zu pageta + Pocket-Import. Wordeck ist Welle-1-Position-2:
* höchste Ship-Reife, niedrigstes Compliance-Risiko der Welle.
*/
export const app: AppMeta = {
slug: 'wordeck',
domain: 'wordeck.com',
appDomain: 'app.wordeck.com',
hook: 'Anki ohne Akrobatik. Karten lernen in 30 Sekunden installiert.',
tagline:
'Spaced-Repetition-Karteikarten mit FSRS. Anki-Import inklusive Cloze. Web + iOS, vereinsgetragen.',
description:
'Wordeck ist die Karteikarten-App von mana e.V. — FSRS-Scheduler, .apkg-Anki-Import mit Cloze-Erkennung, drei Marketplace-Decks zum Start.',
theme: 'neutral',
}
export const stats: Stat[] = [
{ value: '.apkg', label: 'Anki-Import', hint: 'Inkl. Cloze' },
{ value: 'FSRS', label: 'Scheduler', hint: 'Nachfolger von SM-2' },
{ value: 648, label: 'Karten im Marketplace', hint: '3 Decks zum Start' },
{ value: 0, label: 'Tracker', hint: 'Versprochen' },
]
export const features: Feature[] = [
{
icon: '📦',
title: 'Anki-Import',
body: 'Deine .apkg-Decks aus Anki einlesen — Cloze-Karten werden als first-class behandelt, Duplikate dedupliziert per content-hash.',
},
{
icon: '🧠',
title: 'FSRS-Scheduler',
body: 'Free Spaced Repetition Scheduler — der wissenschaftlich nachgewiesene Nachfolger von Ankis SM-2. Weniger Wiederholungen bei gleichem Retention-Ziel.',
},
{
icon: '🛒',
title: 'Marketplace-Decks',
body: 'Drei kuratierte Decks (648 Karten) unter CC0/CC-BY-4.0 ready-to-import. Eigene Decks lassen sich teilen — kein Lock-in.',
},
{
icon: '✍️',
title: 'Cloze first-class',
body: 'Lückentext-Karten („Albert Einstein lebte von {{c1::1879}} bis {{c2::1955}}") sind nicht eine Notlösung, sondern erste Klasse.',
},
{
icon: '🌐',
title: 'Web + iOS',
body: 'Im Browser lernen, auf dem iPhone offline weiterlernen. Native-App auf TestFlight; Android über die PWA-Installation.',
},
{
icon: '🔓',
title: 'Export jederzeit',
body: 'Deine Decks bleiben deine Decks — Export zurück nach Anki-kompatiblem Format ist nicht „Premium-Feature", sondern Default.',
},
]
export const faq: FaqItem[] = [
{
q: 'Was unterscheidet Wordeck von Anki?',
a: 'Anki ist mächtig, aber die Mobile-Apps kosten 25€ einmalig und die UI ist 20 Jahre alt. Wordeck ist Web + Native, FSRS statt SM-2, ohne Werbung, ohne Tracker. Anki-Decks importierst du in 30 Sekunden.',
},
{
q: 'Was ist FSRS und warum ist das wichtig?',
a: 'Free Spaced Repetition Scheduler — Open-Source-Algorithmus, der empirisch belegt weniger Wiederholungen bei gleichem Lernerfolg braucht als SM-2 (Ankis Default). Anki selbst hat FSRS seit 2024 als Opt-in; Wordeck ist FSRS-only.',
},
{
q: 'Was passiert mit meinen Decks, wenn Wordeck verschwindet?',
a: 'Export als JSON oder Anki-.apkg ist jederzeit verfügbar. Wordeck ist vereinsgetragen, kein Exit-Risiko — aber die Export-Garantie steht davon unabhängig.',
},
{
q: 'Kostet Wordeck etwas?',
a: 'Die Basis-App und alle Marketplace-Decks sind kostenlos. Optionale KI-Funktionen (z.B. „Karten aus Text generieren") laufen über Mana-Credits zum Selbstkostenpreis — sichtbar pro Aktion, abschaltbar.',
},
{
q: 'Funktioniert Wordeck ohne Login?',
a: 'Marketplace-Decks ansehen und Demo-Lernen geht ohne Account. Eigene Decks anlegen und Sync zwischen Geräten brauchen einen Login.',
},
{
q: 'Welche Sprachen sind unterstützt?',
a: 'UI heute DE/EN. Karten selbst sind sprach-agnostisch — du lernst Latein, Japanisch, Code, Botanik oder was auch immer.',
},
]

View file

@ -0,0 +1,108 @@
---
import AppLanding from '@mana/marketing-kit/layouts/AppLanding.astro'
import Hero from '@mana/marketing-kit/components/Hero.astro'
import StorySection from '@mana/marketing-kit/components/StorySection.astro'
import FAQ from '@mana/marketing-kit/components/FAQ.astro'
import CTABanner from '@mana/marketing-kit/components/CTABanner.astro'
import { buildSeo, faqJsonLd } from '@mana/marketing-kit'
import { app } from '../lib/app.js'
/**
* Long-Tail-Page für „anki alternative", „anki deck import",
* „anki ios kostenlos", „fsrs scheduler". Eigene canonical,
* eigene FAQ. Höchste Akquise-Konversion der Welle nach pageta/
* pocket-import.
*/
const seo = buildSeo(app, {
path: '/anki-import',
title: 'Anki-Deck in Wordeck importieren — .apkg, Cloze, FSRS',
description:
'Schritt-für-Schritt: bestehende Anki-Decks samt Cloze-Karten und Tags nach Wordeck migrieren. FSRS statt SM-2, ohne 25€-iOS-Gebühr.',
})
const ankiFaq = [
{
q: 'Welche Anki-Versionen kann ich importieren?',
a: 'Wordeck liest .apkg-Dateien aus Anki 2.x (Desktop, AnkiDroid, AnkiMobile). Karten, Decks, Tags und Cloze-Notes werden übernommen. Add-on-spezifische Felder werden ignoriert, der Karten-Text bleibt unverändert.',
},
{
q: 'Was passiert mit meinen FSRS-Parametern aus Anki?',
a: 'FSRS-Optimizer-Parameter aus Anki werden bei Import übernommen, sofern im Deck enthalten. Wenn dein Anki-Deck noch auf SM-2 läuft, startest du in Wordeck mit den FSRS-Defaults — der erste Optimizer-Lauf nach ~1000 Reviews tuned das automatisch.',
},
{
q: 'Was ist mit meiner Lernhistorie?',
a: 'Reviews-Historie wird bei Import-Standard übernommen, damit FSRS daraus lernen kann. Du kannst optional „Frische Liste" wählen, wenn du das Deck neu starten willst.',
},
{
q: 'Sind Cloze-Karten unterstützt?',
a: 'Ja, first-class. Cloze-Marker ({{c1::...}}) werden korrekt erkannt und als eine Notiz mit mehreren Karten behandelt — wie in Anki.',
},
{
q: 'Was passiert mit Duplikaten?',
a: 'Dedupliziert per content-hash. Wenn du das gleiche Deck zweimal importierst, werden bereits importierte Karten übersprungen (Skip-Counter im Erfolgs-Report).',
},
{
q: 'Kann ich später zurück zu Anki?',
a: 'Ja. Wordeck exportiert .apkg-kompatibel jederzeit — inklusive Reviews-Historie, sofern du die behalten hast. Kein „Premium-Feature", kein „nach 30 Tagen weg".',
},
]
const jsonLd = [faqJsonLd(ankiFaq)]
---
<AppLanding {app} {seo} {jsonLd}>
<Hero
eyebrow="Anki-Import"
headline="Dein Anki-Deck, übernommen in 30 Sekunden."
sub=".apkg einlesen, Cloze und Tags bleiben drin, FSRS direkt aktiv."
ctas={[
{ href: `https://${app.appDomain}`, label: 'Jetzt importieren' },
]}
/>
<StorySection eyebrow="Schritt 1" title="Anki-Deck exportieren">
<p>
In Anki: <em>Datei → Exportieren</em> wählen, Deck auswählen, Format
„Anki Deck Package (.apkg)" — mit oder ohne Lernfortschritt, ganz wie
du magst. Funktioniert auch in AnkiDroid und AnkiMobile.
</p>
</StorySection>
<StorySection eyebrow="Schritt 2" title="Wordeck-Account anlegen" muted>
<p>
Auf <a href={`https://${app.appDomain}`}>app.wordeck.com</a> mit E-Mail
registrieren. Email-Verifikation, kein Telefon-Theater, keine
Social-OAuth-Pflicht. Account ist in unter zwei Minuten fertig.
</p>
</StorySection>
<StorySection eyebrow="Schritt 3" title=".apkg einlesen">
<p>
In Wordeck: Decks → „Importieren" → .apkg-Datei auswählen. Wordeck
parst das Paket, dedupliziert, übernimmt Tags und Cloze-Karten,
zeigt eine Live-Statistik (importiert / übersprungen / Fehler).
</p>
</StorySection>
<StorySection eyebrow="Was du bekommst" title="Übersicht nach dem Import" muted>
<ul>
<li><strong>Deck</strong> — alle Karten, Tags, Cloze-Notes</li>
<li><strong>FSRS-Scheduler</strong> aktiviert, mit deinen Anki-Parametern (falls vorhanden)</li>
<li><strong>Reviews-Historie</strong> übernommen (optional)</li>
<li><strong>Web + iOS</strong> — sofort auf beiden Plattformen lernbar</li>
<li><strong>Export</strong> jederzeit zurück nach .apkg verfügbar</li>
</ul>
</StorySection>
<FAQ title="Anki-Import-FAQ" items={ankiFaq} />
<CTABanner
title="Jetzt importieren"
sub="Account anlegen, .apkg einlesen, lernen. Bei Problemen: git.mana.how — wir antworten."
ctas={[
{ href: `https://${app.appDomain}`, label: 'Account anlegen' },
{ href: 'https://docs.ankiweb.net/exporting.html', label: 'Anki-Export-Doku', variant: 'secondary', external: true },
]}
/>
</AppLanding>

View file

@ -0,0 +1,88 @@
---
import AppLanding from '@mana/marketing-kit/layouts/AppLanding.astro'
import Hero from '@mana/marketing-kit/components/Hero.astro'
import StorySection from '@mana/marketing-kit/components/StorySection.astro'
import StatsRow from '@mana/marketing-kit/components/StatsRow.astro'
import FeatureGrid from '@mana/marketing-kit/components/FeatureGrid.astro'
import FAQ from '@mana/marketing-kit/components/FAQ.astro'
import CTABanner from '@mana/marketing-kit/components/CTABanner.astro'
import { buildSeo, faqJsonLd } from '@mana/marketing-kit'
import { app, stats, features, faq } from '../lib/app.js'
const seo = buildSeo(app, {
path: '/',
title: `wordeck — ${app.hook}`,
description: app.tagline,
})
const jsonLd = [faqJsonLd(faq)]
---
<AppLanding {app} {seo} {jsonLd}>
<Hero
eyebrow="Karteikarten · Spaced-Repetition"
headline={app.hook}
sub={app.tagline}
ctas={[
{ href: '/anki-import', label: 'Anki-Deck importieren' },
{ href: `https://${app.appDomain}`, label: 'App öffnen', variant: 'secondary' },
]}
/>
<StatsRow {stats} />
<StorySection eyebrow="Warum" title="Anki ist gut. Aber 25€ für die iOS-App und ein UI aus 2005 sind 2026 nicht zumutbar.">
<p>
Spaced Repetition funktioniert — das ist seit Jahrzehnten unstrittig.
Anki ist die offene Referenz-Implementierung, und sie ist großartig.
Aber: die iOS-App kostet einmalig 25€, das Web-UI ist optisch in der
Mitte der 2000er stehen geblieben, und die FSRS-Umstellung ist
optional und versteckt.
</p>
<p>
Wordeck nimmt dieselben Konzepte (Cards, Decks, Cloze, SRS), schreibt
die UI von 2026 her, setzt FSRS als Default — und importiert deine
bestehenden Anki-Decks in 30 Sekunden.
</p>
</StorySection>
<FeatureGrid eyebrow="Was geht" title="Sechs Versprechen" {features} />
<StorySection eyebrow="Was Wordeck NICHT macht" title="Anti-Features" muted>
<ul>
<li><strong>Keine Streak-Manipulation.</strong> Kein „du hast deine 47-Tage-Serie gebrochen"-Schmerz-Theater.</li>
<li><strong>Kein Algorithmus-Feed.</strong> Keine „Empfohlene Decks"-Endlos-Liste.</li>
<li><strong>Keine Werbung, kein Tracker.</strong> Auch nicht „nativ", auch nicht „kuratiert".</li>
<li><strong>Kein Lock-in.</strong> Export nach Anki-Format jederzeit.</li>
<li><strong>Kein Exit-Risiko.</strong> Wordeck gehört dem Verein — kein Käufer kann es abschalten.</li>
</ul>
</StorySection>
<StorySection eyebrow="Verein" title="mana e.V., nicht Startup">
<p>
Wordeck ist ein Projekt von <a href="https://mana-ev.ch">mana e.V.</a> —
Schweizer Verein in Gründung. Wir bauen 16 gemeinnützige Software-Werkzeuge
(Lesen, Lernen, Aufschreiben, Pflanzen, Spuren). Finanziert über
Mitgliedsbeiträge und einen
<a href="https://mana-ev.ch/mana">Selbstkostenpreis-Tarif</a> für optionale
KI-Funktionen.
</p>
<p>
Wordeck-Basis ist und bleibt kostenlos. Marketplace-Decks sind unter
freien Lizenzen (CC0, CC-BY-4.0) — du darfst kopieren, in deinen
Unterricht einbauen, weiterverwenden.
</p>
</StorySection>
<FAQ items={faq} />
<CTABanner
title="In 30 Sekunden anfangen"
sub="Anki-Deck importieren oder mit einem unserer Marketplace-Decks starten. Account anlegen, lernen, fertig."
ctas={[
{ href: '/anki-import', label: 'Anki importieren' },
{ href: `https://${app.appDomain}`, label: 'Marketplace ansehen', variant: 'secondary' },
]}
/>
</AppLanding>

View file

@ -0,0 +1,42 @@
import type { APIRoute } from 'astro'
import { llmsTxt } from '@mana/marketing-kit'
import { app } from '../lib/app.js'
// llms.txt für wordeck. Ziel: wenn jemand „Anki-Alternative" oder
// „karteikarten app open source" fragt, soll der AI-Assistent
// Wordeck finden — samt Anki-Import-Pfad und FSRS-Hinweis.
export const GET: APIRoute = () => {
const body = llmsTxt({
app,
what:
'Spaced-Repetition-Karteikarten-App mit FSRS-Scheduler. Anki-Deck-Import (.apkg) inkl. Cloze. Vereinsgetragen, Web + iOS, kostenlos.',
allmende: [
'3 Marketplace-Decks (648 Karten) unter CC0 / CC-BY-4.0',
'Anki-Import: .apkg-Pakete inkl. Cloze-Notes, Tags, optional Reviews-Historie',
'Export zurück nach Anki-kompatiblem Format jederzeit (kein Lock-in)',
'Source-Code auf https://git.mana.how/till/wordeck',
],
additionalSections: [
{
title: 'Wichtige Marketing-Seiten',
items: [
{ label: 'Anki-Import (Schritt-für-Schritt)', href: 'https://wordeck.com/anki-import' },
{ label: 'Über Wordeck (FSRS + Verein)', href: 'https://wordeck.com/ueber' },
{ label: 'Mitwirken', href: 'https://wordeck.com/mitwirken' },
],
},
{
title: 'App',
items: [
{ label: 'App öffnen', href: `https://${app.appDomain}/` },
{ label: 'Marketplace', href: `https://${app.appDomain}/marketplace` },
{ label: 'Anki-Import (direkt)', href: `https://${app.appDomain}/import` },
],
},
],
})
return new Response(body, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})
}

View file

@ -0,0 +1,62 @@
---
import AppLanding from '@mana/marketing-kit/layouts/AppLanding.astro'
import StorySection from '@mana/marketing-kit/components/StorySection.astro'
import CTABanner from '@mana/marketing-kit/components/CTABanner.astro'
import { buildSeo } from '@mana/marketing-kit'
import { app } from '../lib/app.js'
const seo = buildSeo(app, {
path: '/mitwirken',
title: 'Mitwirken bei Wordeck — Decks veröffentlichen, Code, Verein',
description:
'Drei Wege: eigene Decks im Marketplace veröffentlichen, Code-Beiträge auf git.mana.how, Vereinsmitgliedschaft.',
})
---
<AppLanding {app} {seo}>
<StorySection eyebrow="Mitwirken" title="Drei Wege, Wordeck zu stützen">
<p>
Wordeck wächst, wenn Menschen Decks teilen und Code beitragen. Drei
Ebenen, keine zwingt zur anderen.
</p>
</StorySection>
<StorySection eyebrow="1" title="Decks im Marketplace veröffentlichen">
<p>
Wenn du ein gutes Deck gebaut hast (Vokabeln, Anatomie, Code-Snippets,
Botanik, was auch immer): teile es im Wordeck-Marketplace, mit
Lizenz-Wahl beim Publish (CC0, CC-BY-4.0 empfohlen). Reviewer-Stop
vorher — wir prüfen Atomicity, Source-Coverage, kein Spam.
</p>
</StorySection>
<StorySection eyebrow="2" title="Code-Beiträge" muted>
<p>
Quellcode auf <a href="https://git.mana.how/till/wordeck">git.mana.how/till/wordeck</a>.
SvelteKit-Frontend, Hono+Bun-API, Drizzle/Postgres, FSRS in pure-TS.
Konventionen im
<a href="https://git.mana.how/till/wordeck/src/branch/main/CLAUDE.md">CLAUDE.md</a>.
</p>
<p>
Besonders willkommen: FSRS-Optimizer-Verbesserungen,
Marketplace-Curation, i18n (heute DE/EN, FR/IT/ES für Vereins-Sprachen
ergänzen).
</p>
</StorySection>
<StorySection eyebrow="3" title="Vereinsmitglied werden">
<p>
mana e.V. nimmt Fördermitglieder auf — der strukturellste Weg,
Wordeck plus die anderen 15 Apps zu tragen.
<a href="https://mana-ev.ch/mitgliedschaft">Mitgliedschafts-Infos</a>.
</p>
</StorySection>
<CTABanner
title="Anfangen"
ctas={[
{ href: `https://${app.appDomain}`, label: 'Eigenes Deck bauen' },
{ href: 'https://git.mana.how/till/wordeck', label: 'Repo öffnen', variant: 'secondary', external: true },
]}
/>
</AppLanding>

View file

@ -0,0 +1,8 @@
import type { APIRoute } from 'astro'
import { robotsTxt } from '@mana/marketing-kit'
import { app } from '../lib/app.js'
export const GET: APIRoute = () =>
new Response(robotsTxt(app), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})

View file

@ -0,0 +1,19 @@
import type { APIRoute } from 'astro'
import { sitemapXml } from '@mana/marketing-kit'
import { app } from '../lib/app.js'
export const GET: APIRoute = () => {
const today = new Date().toISOString().slice(0, 10)
const body = sitemapXml(app, [
{ path: '/', lastmod: today, changefreq: 'weekly', priority: 1.0 },
// anki-import bewusst hohe Priorität — Akquise-Page für
// „anki alternative" Long-Tail.
{ path: '/anki-import', lastmod: today, changefreq: 'weekly', priority: 0.95 },
{ path: '/ueber', lastmod: today, changefreq: 'monthly', priority: 0.8 },
{ path: '/mitwirken', lastmod: today, changefreq: 'monthly', priority: 0.7 },
])
return new Response(body, {
headers: { 'Content-Type': 'application/xml; charset=utf-8' },
})
}

View file

@ -0,0 +1,82 @@
---
import AppLanding from '@mana/marketing-kit/layouts/AppLanding.astro'
import StorySection from '@mana/marketing-kit/components/StorySection.astro'
import CTABanner from '@mana/marketing-kit/components/CTABanner.astro'
import { buildSeo } from '@mana/marketing-kit'
import { app } from '../lib/app.js'
const seo = buildSeo(app, {
path: '/ueber',
title: 'Über Wordeck — Verein, FSRS, Marketplace',
description:
'Hintergrund: warum FSRS statt SM-2, was die Marketplace-Decks bedeuten, warum Wordeck vereinsgetragen ist.',
})
---
<AppLanding {app} {seo}>
<StorySection eyebrow="Über" title="Warum noch eine Karteikarten-App?">
<p>
Spaced Repetition gibt es seit den 1970ern. Anki seit 2006. Die
Methode ist nicht das Problem — das Werkzeug ist es. Anki ist
mächtig, aber die Mobile-Variante kostet 25€ und die UI ist
zwei Jahrzehnte alt. Quizlet hat sich in eine SaaS-Falle
gepivotiert. Mochi und RemNote sind gut, aber Lock-in.
</p>
<p>
Wordeck nimmt das, was an Anki gut ist (SRS, Decks, Cloze, .apkg
als de-facto-Format) und kombiniert es mit dem, was bei den anderen
gut ist (UI von 2026, Mobile-First, kostenlos). Plus: FSRS als
Default, weil der Algorithmus empirisch besser ist.
</p>
</StorySection>
<StorySection eyebrow="Architektur" title="FSRS-only ist eine Entscheidung" muted>
<p>
Anki hat FSRS seit 2024 als Opt-in. Die meisten User wissen davon
nicht und bleiben auf SM-2 (Default). Das ist eine UX-Wahl, kein
technischer Engpass.
</p>
<p>
Wordeck ist FSRS-only — kein „du musst es in den Settings
aktivieren". Der Scheduler kalibriert sich nach ~1000 Reviews auf
deine persönliche Vergessens-Kurve. Bis dahin laufen sinnvolle
Defaults.
</p>
</StorySection>
<StorySection eyebrow="Marketplace" title="Drei Decks zum Start, CC0 / CC-BY">
<p>
Wordeck startet nicht leer. Drei kuratierte Decks (648 Karten gesamt)
sind ab Tag-1 verfügbar — unter CC0 oder CC-BY-4.0, also frei
weiterverwendbar. Eigene Decks kannst du im Marketplace teilen, mit
Lizenz-Auswahl beim Publish.
</p>
<p>
Wachstum kommt über Mitwirkende — der Marketplace ist Allmende,
nicht Plattform-Lock-in.
</p>
</StorySection>
<StorySection eyebrow="Verein" title="mana e.V., Schweizer Verein in Gründung" muted>
<p>
Hinter Wordeck steht <a href="https://mana-ev.ch">mana e.V.</a> Wir
bauen 16 gemeinnützige Software-Werkzeuge, finanziert über
Mitgliedsbeiträge und Selbstkostenpreis-Mana-Tarif für KI-Aktionen.
Wordeck-Basis ist und bleibt kostenlos; optionale KI-Funktionen
(„Karten aus Text generieren") sind transparent bepreist.
</p>
<p>
<a href="https://mana-ev.ch/mission">Mission und Werte</a> ·
<a href="https://mana-ev.ch/transparenz">Quartalsberichte</a> ·
<a href="https://git.mana.how/till/wordeck">Quellcode</a>
</p>
</StorySection>
<CTABanner
title="Wordeck ausprobieren"
ctas={[
{ href: `https://${app.appDomain}`, label: 'App öffnen' },
{ href: '/anki-import', label: 'Mit Anki-Import starten', variant: 'secondary' },
]}
/>
</AppLanding>

View file

@ -0,0 +1,4 @@
{
"extends": "astro/tsconfigs/strict",
"include": ["src/**/*", "astro.config.mjs"]
}