feat(landing): add shared-landing-ui package and manadeck landing page

- Create @manacore/shared-landing-ui package with reusable components
  (FeatureSection, StepsSection, FAQSection, CTASection, Card atoms)
- Add complete landing page for manadeck app
- Refactor märchenzauber landing to use shared components
  (remove local CTA, FAQ, Features, HowItWorks sections)
- Add German localization for manacore and memoro landing pages
- Update workspace configuration and package dependencies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-11-25 03:03:41 +01:00
parent 4bdb5dea85
commit c6c4c5a552
52 changed files with 3519 additions and 381 deletions

View file

@ -0,0 +1,17 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import sitemap from '@astrojs/sitemap';
// https://astro.build/config
export default defineConfig({
site: 'https://manadeck.app',
integrations: [
tailwind(),
sitemap()
],
vite: {
ssr: {
noExternal: ['@manacore/shared-landing-ui']
}
}
});

View file

@ -0,0 +1,27 @@
{
"name": "@manadeck/landing",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro check && astro build",
"preview": "astro preview",
"astro": "astro",
"type-check": "astro check"
},
"dependencies": {
"@astrojs/check": "^0.9.0",
"@astrojs/sitemap": "^3.2.1",
"@manacore/shared-landing-ui": "workspace:*",
"astro": "^5.16.0",
"astro-icon": "^1.1.5",
"typescript": "^5.0.0"
},
"devDependencies": {
"@astrojs/tailwind": "^6.0.0",
"@tailwindcss/typography": "^0.5.16",
"tailwindcss": "^3.4.17"
}
}

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect width="100" height="100" rx="20" fill="#7C3AED"/>
<text x="50" y="70" font-size="60" text-anchor="middle" fill="white">🃏</text>
</svg>

After

Width:  |  Height:  |  Size: 211 B

View file

@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: https://manadeck.app/sitemap-index.xml

View file

@ -0,0 +1,78 @@
---
const footerLinks = {
product: [
{ href: '#features', label: 'Features' },
{ href: '#pricing', label: 'Preise' },
{ href: '#faq', label: 'FAQ' }
],
legal: [
{ href: '/privacy', label: 'Datenschutz' },
{ href: '/terms', label: 'AGB' },
{ href: '/imprint', label: 'Impressum' }
]
};
const currentYear = new Date().getFullYear();
---
<footer class="bg-background-card border-t border-border">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<!-- Brand -->
<div class="col-span-1 md:col-span-2">
<a href="/" class="flex items-center gap-2 mb-4">
<span class="text-2xl">🃏</span>
<span class="font-bold text-xl text-text-primary">ManaDeck</span>
</a>
<p class="text-text-secondary text-sm max-w-md">
Dein KI-gestützter Lernpartner. Erstelle intelligente Karteikarten aus deinen Notizen
und lerne effizienter mit Spaced Repetition.
</p>
</div>
<!-- Product Links -->
<div>
<h3 class="font-semibold text-text-primary mb-4">Produkt</h3>
<ul class="space-y-2">
{footerLinks.product.map(link => (
<li>
<a
href={link.href}
class="text-text-secondary hover:text-text-primary transition-colors text-sm"
>
{link.label}
</a>
</li>
))}
</ul>
</div>
<!-- Legal Links -->
<div>
<h3 class="font-semibold text-text-primary mb-4">Rechtliches</h3>
<ul class="space-y-2">
{footerLinks.legal.map(link => (
<li>
<a
href={link.href}
class="text-text-secondary hover:text-text-primary transition-colors text-sm"
>
{link.label}
</a>
</li>
))}
</ul>
</div>
</div>
<!-- Bottom -->
<div class="mt-12 pt-8 border-t border-border flex flex-col sm:flex-row justify-between items-center gap-4">
<p class="text-text-muted text-sm">
&copy; {currentYear} ManaDeck. Alle Rechte vorbehalten.
</p>
<p class="text-text-muted text-sm">
Made with 💜 in Germany
</p>
</div>
</div>
</footer>

View file

@ -0,0 +1,84 @@
---
const navLinks = [
{ href: '#features', label: 'Features' },
{ href: '#how-it-works', label: 'So funktioniert\'s' },
{ href: '#pricing', label: 'Preise' },
{ href: '#faq', label: 'FAQ' }
];
---
<nav class="fixed top-0 left-0 right-0 z-50 bg-background-page/80 backdrop-blur-lg border-b border-border">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<!-- Logo -->
<a href="/" class="flex items-center gap-2">
<span class="text-2xl">🃏</span>
<span class="font-bold text-xl text-text-primary">ManaDeck</span>
</a>
<!-- Desktop Navigation -->
<div class="hidden md:flex items-center gap-8">
{navLinks.map(link => (
<a
href={link.href}
class="text-text-secondary hover:text-text-primary transition-colors text-sm font-medium"
>
{link.label}
</a>
))}
</div>
<!-- CTA Button -->
<div class="flex items-center gap-4">
<a
href="#download"
class="btn-primary text-sm px-4 py-2"
>
App herunterladen
</a>
<!-- Mobile Menu Button -->
<button
type="button"
class="md:hidden p-2 text-text-secondary hover:text-text-primary"
aria-label="Menu"
id="mobile-menu-button"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
</div>
</div>
</div>
<!-- Mobile Menu -->
<div class="hidden md:hidden" id="mobile-menu">
<div class="px-4 py-4 space-y-2 bg-background-card border-t border-border">
{navLinks.map(link => (
<a
href={link.href}
class="block px-4 py-2 text-text-secondary hover:text-text-primary hover:bg-background-card-hover rounded-lg transition-colors"
>
{link.label}
</a>
))}
</div>
</div>
</nav>
<script>
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
mobileMenuButton?.addEventListener('click', () => {
mobileMenu?.classList.toggle('hidden');
});
// Close menu when clicking a link
mobileMenu?.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
mobileMenu?.classList.add('hidden');
});
});
</script>

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

@ -0,0 +1 @@
/// <reference types="astro/client" />

View file

@ -0,0 +1,47 @@
---
import '../styles/global.css';
interface Props {
title: string;
description?: string;
}
const {
title,
description = 'ManaDeck - Dein KI-gestützter Lernpartner für Karteikarten und effektives Lernen'
} = Astro.props;
---
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<meta name="generator" content={Astro.generator} />
<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<!-- Open Graph -->
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:locale" content="de_DE" />
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<title>{title}</title>
</head>
<body class="min-h-screen bg-background-page text-text-primary antialiased">
<slot />
</body>
</html>

View file

@ -0,0 +1,287 @@
---
import Layout from '../layouts/Layout.astro';
import Navigation from '../components/Navigation.astro';
import Footer from '../components/Footer.astro';
// Shared components
import HeroSection from '@manacore/shared-landing-ui/sections/HeroSection.astro';
import FeatureSection from '@manacore/shared-landing-ui/sections/FeatureSection.astro';
import StepsSection from '@manacore/shared-landing-ui/sections/StepsSection.astro';
import FAQSection from '@manacore/shared-landing-ui/sections/FAQSection.astro';
import CTASection from '@manacore/shared-landing-ui/sections/CTASection.astro';
import PricingSection from '@manacore/shared-landing-ui/sections/PricingSection.astro';
import Card from '@manacore/shared-landing-ui/atoms/Card.astro';
// Feature data
const features = [
{
icon: '🧠',
title: 'KI-generierte Karteikarten',
description: 'Lade deine Notizen, PDFs oder Texte hoch und lass die KI automatisch perfekte Karteikarten erstellen.'
},
{
icon: '🔄',
title: 'Spaced Repetition',
description: 'Unser intelligenter Algorithmus zeigt dir Karten genau dann, wenn du sie wiederholen solltest.'
},
{
icon: '📊',
title: 'Lernstatistiken',
description: 'Verfolge deinen Fortschritt mit detaillierten Statistiken und optimiere dein Lernen.'
},
{
icon: '📱',
title: 'Überall lernen',
description: 'Synchronisiere deine Decks auf allen Geräten und lerne, wo immer du bist.'
},
{
icon: '🎯',
title: 'Personalisiertes Lernen',
description: 'Die KI passt sich deinem Lernstil an und erstellt maßgeschneiderte Wiederholungspläne.'
},
{
icon: '🤝',
title: 'Decks teilen',
description: 'Teile deine Karteikarten-Decks mit Freunden oder entdecke öffentliche Sammlungen.'
}
];
// Steps data
const steps = [
{
number: '1',
title: 'Inhalte hochladen',
description: 'Lade deine Notizen, PDFs oder Texte hoch. ManaDeck unterstützt verschiedene Formate.',
image: '/screenshots/upload.png'
},
{
number: '2',
title: 'KI erstellt Karten',
description: 'Unsere KI analysiert deine Inhalte und erstellt automatisch strukturierte Karteikarten.',
image: '/screenshots/generate.png'
},
{
number: '3',
title: 'Effizient lernen',
description: 'Lerne mit Spaced Repetition und behalte das Gelernte langfristig im Gedächtnis.',
image: '/screenshots/learn.png'
}
];
// Pricing data
const pricingPlans = [
{
name: 'Free',
price: '0',
period: '/Monat',
description: 'Perfekt zum Ausprobieren',
features: [
{ text: '50 Karteikarten', included: true },
{ text: '3 Decks', included: true },
{ text: 'Basis-KI-Generierung', included: true },
{ text: 'Spaced Repetition', included: true },
{ text: 'Unbegrenzte Karten', included: false },
{ text: 'Deck-Sharing', included: false }
],
cta: {
text: 'Kostenlos starten',
href: '#download'
}
},
{
name: 'Pro',
price: '9,99',
period: '/Monat',
description: 'Für ambitionierte Lerner',
features: [
{ text: 'Unbegrenzte Karteikarten', included: true },
{ text: 'Unbegrenzte Decks', included: true },
{ text: 'Erweiterte KI-Funktionen', included: true },
{ text: 'Spaced Repetition', included: true },
{ text: 'Deck-Sharing', included: true },
{ text: 'Prioritäts-Support', included: true }
],
cta: {
text: 'Pro werden',
href: '#download'
},
highlighted: true,
badge: 'Beliebt'
},
{
name: 'Team',
price: '24,99',
period: '/Monat',
description: 'Für Gruppen und Klassen',
features: [
{ text: 'Alles aus Pro', included: true },
{ text: 'Team-Verwaltung', included: true },
{ text: 'Gemeinsame Decks', included: true },
{ text: 'Fortschritts-Tracking', included: true },
{ text: 'Admin-Dashboard', included: true },
{ text: 'Dedizierter Support', included: true }
],
cta: {
text: 'Team starten',
href: '#download'
}
}
];
// FAQ data
const faqs = [
{
question: 'Wie funktioniert die KI-Karteikarten-Generierung?',
answer: 'ManaDeck verwendet fortschrittliche KI-Modelle, um deine Texte zu analysieren und die wichtigsten Konzepte zu extrahieren. Daraus werden automatisch Frage-Antwort-Paare erstellt, die du als Karteikarten lernen kannst.'
},
{
question: 'Was ist Spaced Repetition?',
answer: 'Spaced Repetition ist eine wissenschaftlich bewährte Lernmethode, bei der Karten in optimalen Zeitabständen wiederholt werden. Karten, die du gut kennst, siehst du seltener, während schwierige Karten häufiger erscheinen.'
},
{
question: 'Kann ich meine eigenen Karteikarten erstellen?',
answer: 'Ja! Du kannst sowohl KI-generierte Karten nutzen als auch komplett eigene Karteikarten erstellen. Beide Varianten lassen sich beliebig kombinieren und bearbeiten.'
},
{
question: 'Welche Dateiformate werden unterstützt?',
answer: 'ManaDeck unterstützt PDF, Word-Dokumente (.docx), Textdateien (.txt) und Markdown (.md). Du kannst auch direkt Text in die App einfügen.'
},
{
question: 'Sind meine Daten sicher?',
answer: 'Ja, alle Daten werden verschlüsselt übertragen und gespeichert. Wir verkaufen keine Nutzerdaten an Dritte und sind DSGVO-konform.'
},
{
question: 'Kann ich offline lernen?',
answer: 'Ja! Du kannst deine Decks für den Offline-Modus herunterladen und überall lernen, auch ohne Internetverbindung.'
}
];
---
<Layout title="ManaDeck - KI-gestützte Karteikarten für effektives Lernen">
<Navigation />
<main class="pt-16">
<HeroSection
title="Lerne smarter, nicht härter"
subtitle="ManaDeck verwandelt deine Notizen in intelligente Karteikarten. Mit KI-Generierung und Spaced Repetition lernst du effizienter als je zuvor."
variant="default"
primaryCta={{
text: 'Jetzt kostenlos starten',
href: '#download'
}}
secondaryCta={{
text: 'Features entdecken',
href: '#features',
variant: 'secondary'
}}
trustBadges={[
{ icon: '✓', text: 'Kostenlos testen' },
{ icon: '🔒', text: 'DSGVO-konform' },
{ icon: '📱', text: 'iOS & Android' }
]}
/>
<FeatureSection
id="features"
title="Alles was du zum Lernen brauchst"
subtitle="ManaDeck kombiniert KI-Technologie mit bewährten Lernmethoden für maximalen Lernerfolg."
features={features}
columns={3}
variant="cards"
class="bg-[var(--color-background-card)]"
>
<!-- Mana System Highlight -->
<div class="mt-12 md:mt-16 px-4" slot="highlight">
<Card variant="glow" class="max-w-4xl mx-auto" padding="lg">
<div class="flex flex-col md:flex-row items-center gap-6 md:gap-8">
<div class="text-5xl sm:text-6xl">⚡</div>
<div class="flex-1 text-center md:text-left">
<h3 class="font-bold text-xl sm:text-2xl text-[var(--color-text-primary)] mb-2 sm:mb-3">
Mana-System
</h3>
<p class="text-[var(--color-text-secondary)] text-sm sm:text-base leading-relaxed">
Nutze Mana-Punkte für KI-Generierungen. Starte kostenlos mit 100 Mana
und verdiene mehr durch regelmäßiges Lernen.
</p>
</div>
<div class="flex items-center gap-2">
<div class="w-10 h-10 sm:w-12 sm:h-12 bg-[var(--color-primary)] rounded-full flex items-center justify-center">
<span class="text-white font-bold text-sm sm:text-base">M</span>
</div>
<div class="text-left">
<div class="text-[var(--color-text-primary)] font-semibold text-sm sm:text-base">100 Mana</div>
<div class="text-[var(--color-text-secondary)] text-xs sm:text-sm">zum Start</div>
</div>
</div>
</div>
</Card>
</div>
</FeatureSection>
<StepsSection
id="how-it-works"
title="So einfach geht's"
subtitle="In nur drei Schritten zum effektiven Lernen"
steps={steps}
showImages={false}
alternateLayout={true}
/>
<PricingSection
id="pricing"
title="Wähle deinen Plan"
subtitle="Starte kostenlos und upgrade, wenn du bereit bist"
plans={pricingPlans}
class="bg-[var(--color-background-card)]"
/>
<FAQSection
id="faq"
title="Häufig gestellte Fragen"
subtitle="Alles was du über ManaDeck wissen musst"
faqs={faqs}
/>
<CTASection
id="download"
title="Bereit, smarter zu lernen?"
subtitle="Lade ManaDeck jetzt herunter und erstelle deine ersten KI-generierten Karteikarten. Kostenlos und ohne Kreditkarte."
primaryCta={{ text: 'App herunterladen', href: '#' }}
variant="highlighted"
>
<!-- App Store Buttons -->
<div class="flex flex-wrap items-center justify-center gap-4 mt-8">
<a href="#" class="inline-block hover:opacity-80 transition-opacity">
<img src="/app-store-badge.svg" alt="Download im App Store" class="h-12" />
</a>
<a href="#" class="inline-block hover:opacity-80 transition-opacity">
<img src="/google-play-badge.svg" alt="Jetzt bei Google Play" class="h-12" />
</a>
</div>
<!-- Trust Indicators -->
<div class="flex flex-wrap items-center justify-center gap-4 sm:gap-6 mt-8">
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-[var(--color-primary)]" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
</svg>
<span class="text-[var(--color-text-secondary)] text-sm">100% Kostenlos starten</span>
</div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-[var(--color-primary)]" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"></path>
</svg>
<span class="text-[var(--color-text-secondary)] text-sm">DSGVO-konform</span>
</div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-[var(--color-primary)]" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 2a8 8 0 100 16 8 8 0 000-16zm1 11H9v-2h2v2zm0-4H9V5h2v4z"></path>
</svg>
<span class="text-[var(--color-text-secondary)] text-sm">Keine Kreditkarte nötig</span>
</div>
</div>
</CTASection>
</main>
<Footer />
</Layout>

View file

@ -0,0 +1,103 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* ManaDeck Theme CSS Variables */
:root {
/* Primary colors - ManaDeck Purple */
--color-primary: #7C3AED;
--color-primary-hover: #8B5CF6;
--color-primary-glow: rgba(124, 58, 237, 0.3);
/* Text colors */
--color-text-primary: #f9fafb;
--color-text-secondary: #d1d5db;
--color-text-muted: #6b7280;
/* Background colors */
--color-background-page: #0f0a1a;
--color-background-card: #1a1625;
--color-background-card-hover: #2d2640;
/* Border colors */
--color-border: #3d3555;
--color-border-hover: #4d4570;
}
/* Base styles */
html {
scroll-behavior: smooth;
}
body {
font-family: 'Inter', system-ui, sans-serif;
background-color: var(--color-background-page);
color: var(--color-text-primary);
line-height: 1.6;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--color-background-card);
}
::-webkit-scrollbar-thumb {
background: var(--color-border);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--color-border-hover);
}
/* Selection */
::selection {
background-color: var(--color-primary);
color: white;
}
/* Focus styles */
:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* Gradient text */
.text-gradient {
background: linear-gradient(135deg, #7C3AED 0%, #A78BFA 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Animation utilities */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fadeIn {
animation: fadeIn 0.6s ease-out forwards;
}
/* Button styles */
.btn-primary {
@apply inline-flex items-center justify-center px-6 py-3 bg-primary text-white font-semibold rounded-lg transition-all duration-200;
@apply hover:bg-primary-hover hover:shadow-lg hover:shadow-primary-glow;
}
.btn-secondary {
@apply inline-flex items-center justify-center px-6 py-3 border border-border text-text-primary font-semibold rounded-lg transition-all duration-200;
@apply hover:border-border-hover hover:bg-background-card;
}

View file

@ -0,0 +1,39 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
'../../packages/shared-landing-ui/src/**/*.{astro,html,js,jsx,ts,tsx}'
],
theme: {
extend: {
colors: {
// ManaDeck Purple Theme
primary: {
DEFAULT: '#7C3AED',
hover: '#8B5CF6',
glow: 'rgba(124, 58, 237, 0.3)'
},
background: {
page: '#0f0a1a',
card: '#1a1625',
'card-hover': '#2d2640'
},
text: {
primary: '#f9fafb',
secondary: '#d1d5db',
muted: '#6b7280'
},
border: {
DEFAULT: '#3d3555',
hover: '#4d4570'
}
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif']
}
}
},
plugins: [
require('@tailwindcss/typography')
]
};

View file

@ -0,0 +1,9 @@
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}