feat(landing): Marketing-Astro auf wordeck.com LIVE
Some checks are pending
CI / validate (push) Waiting to run
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:
parent
823560900c
commit
e0605b2f2e
17 changed files with 638 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -70,3 +70,4 @@ apps/landing/.astro
|
|||
|
||||
# NPM Auth — Verdaccio-Token soll nie in git
|
||||
.npmrc
|
||||
.astro
|
||||
|
|
|
|||
31
apps/landing/Dockerfile
Normal file
31
apps/landing/Dockerfile
Normal 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
|
||||
14
apps/landing/astro.config.mjs
Normal file
14
apps/landing/astro.config.mjs
Normal 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',
|
||||
},
|
||||
})
|
||||
|
|
@ -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
|
||||
41
apps/landing/infrastructure/nginx.conf
Normal file
41
apps/landing/infrastructure/nginx.conf
Normal 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
20
apps/landing/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
BIN
apps/landing/public/icon.png
Normal file
BIN
apps/landing/public/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
1
apps/landing/src/env.d.ts
vendored
Normal file
1
apps/landing/src/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/// <reference path="../.astro/types.d.ts" />
|
||||
87
apps/landing/src/lib/app.ts
Normal file
87
apps/landing/src/lib/app.ts
Normal 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.',
|
||||
},
|
||||
]
|
||||
108
apps/landing/src/pages/anki-import.astro
Normal file
108
apps/landing/src/pages/anki-import.astro
Normal 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>
|
||||
88
apps/landing/src/pages/index.astro
Normal file
88
apps/landing/src/pages/index.astro
Normal 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>
|
||||
42
apps/landing/src/pages/llms.txt.ts
Normal file
42
apps/landing/src/pages/llms.txt.ts
Normal 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' },
|
||||
})
|
||||
}
|
||||
62
apps/landing/src/pages/mitwirken.astro
Normal file
62
apps/landing/src/pages/mitwirken.astro
Normal 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>
|
||||
8
apps/landing/src/pages/robots.txt.ts
Normal file
8
apps/landing/src/pages/robots.txt.ts
Normal 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' },
|
||||
})
|
||||
19
apps/landing/src/pages/sitemap.xml.ts
Normal file
19
apps/landing/src/pages/sitemap.xml.ts
Normal 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' },
|
||||
})
|
||||
}
|
||||
82
apps/landing/src/pages/ueber.astro
Normal file
82
apps/landing/src/pages/ueber.astro
Normal 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>
|
||||
4
apps/landing/tsconfig.json
Normal file
4
apps/landing/tsconfig.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": ["src/**/*", "astro.config.mjs"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue