diff --git a/apps/todo/.env.example b/apps/todo/.env.example new file mode 100644 index 000000000..a1a204978 --- /dev/null +++ b/apps/todo/.env.example @@ -0,0 +1,25 @@ +# Todo Production Environment Variables +# Copy this file to .env and fill in the values for docker-compose.prod.yml + +# ============================================================================= +# Backend Configuration +# ============================================================================= + +# PostgreSQL connection string +DATABASE_URL=postgresql://todo_user:CHANGE_ME@postgres:5432/todo + +# Mana Core Auth URL for JWT validation +MANA_CORE_AUTH_URL=https://auth.mana.how + +# Allowed CORS origins (comma-separated) +CORS_ORIGINS=https://todo.mana.how + +# ============================================================================= +# Web Configuration +# ============================================================================= + +# Backend API URL (as seen from browser) +PUBLIC_BACKEND_URL=https://todo-api.mana.how + +# Auth URL (as seen from browser) +PUBLIC_MANA_CORE_AUTH_URL=https://auth.mana.how diff --git a/apps/todo/apps/backend/.env.production.example b/apps/todo/apps/backend/.env.production.example new file mode 100644 index 000000000..17900aaa3 --- /dev/null +++ b/apps/todo/apps/backend/.env.production.example @@ -0,0 +1,36 @@ +# Todo Backend - Production Environment Variables +# Copy this file to .env.production and fill in the values + +# ============================================================================= +# REQUIRED +# ============================================================================= + +# Database connection string (PostgreSQL) +DATABASE_URL=postgresql://todo_user:CHANGE_ME@localhost:5432/todo + +# Mana Core Auth URL for JWT validation +MANA_CORE_AUTH_URL=https://auth.mana.how + +# Allowed CORS origins (comma-separated) +# Include your frontend domains here +CORS_ORIGINS=https://todo.mana.how,https://todo-landing.mana.how + +# ============================================================================= +# OPTIONAL +# ============================================================================= + +# Server port (default: 3018) +PORT=3018 + +# Node environment (MUST be 'production' for security) +NODE_ENV=production + +# Logging level (default: info) +LOG_LEVEL=info + +# ============================================================================= +# SECURITY NOTES +# ============================================================================= +# - NEVER set DEV_BYPASS_AUTH=true in production +# - NEVER commit this file with real credentials +# - Use Docker secrets or environment injection for sensitive values diff --git a/apps/todo/apps/backend/docker-entrypoint.sh b/apps/todo/apps/backend/docker-entrypoint.sh index 29843bdc9..384449041 100644 --- a/apps/todo/apps/backend/docker-entrypoint.sh +++ b/apps/todo/apps/backend/docker-entrypoint.sh @@ -1,8 +1,46 @@ #!/bin/sh set -e -echo "Starting Todo Backend..." +echo "==========================================" +echo " Todo Backend Startup" +echo "==========================================" echo "Environment: ${NODE_ENV:-development}" echo "Port: ${PORT:-3018}" +# Wait for database to be ready +if [ -n "$DATABASE_URL" ]; then + echo "Waiting for database..." + + # Extract host and port from DATABASE_URL + DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p') + DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p') + + # Default port if not found + DB_PORT=${DB_PORT:-5432} + + # Wait for database to accept connections + max_attempts=30 + attempt=1 + while [ $attempt -le $max_attempts ]; do + if pg_isready -h "$DB_HOST" -p "$DB_PORT" > /dev/null 2>&1; then + echo "Database is ready!" + break + fi + echo "Waiting for database... (attempt $attempt/$max_attempts)" + sleep 2 + attempt=$((attempt + 1)) + done + + if [ $attempt -gt $max_attempts ]; then + echo "Warning: Could not connect to database after $max_attempts attempts" + fi +fi + +# Push database schema (safe for production - only adds missing tables/columns) +if [ "$RUN_DB_PUSH" = "true" ]; then + echo "Pushing database schema..." + npx drizzle-kit push --force || echo "Warning: db:push failed, continuing anyway..." +fi + +echo "Starting application..." exec "$@" diff --git a/apps/todo/apps/landing/.gitignore b/apps/todo/apps/landing/.gitignore new file mode 100644 index 000000000..cfb78c213 --- /dev/null +++ b/apps/todo/apps/landing/.gitignore @@ -0,0 +1,32 @@ +# build output +dist/ +.output/ + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production +.env.local + +# macOS-specific files +.DS_Store + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# Wrangler +.wrangler/ diff --git a/apps/todo/apps/landing/.prettierrc b/apps/todo/apps/landing/.prettierrc new file mode 100644 index 000000000..09cfb7d9d --- /dev/null +++ b/apps/todo/apps/landing/.prettierrc @@ -0,0 +1,15 @@ +{ + "useTabs": true, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-astro", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.astro", + "options": { + "parser": "astro" + } + } + ] +} diff --git a/apps/todo/apps/landing/astro.config.mjs b/apps/todo/apps/landing/astro.config.mjs new file mode 100644 index 000000000..83c9c822a --- /dev/null +++ b/apps/todo/apps/landing/astro.config.mjs @@ -0,0 +1,19 @@ +import { defineConfig } from 'astro/config'; +import tailwind from '@astrojs/tailwind'; + +// https://astro.build/config +export default defineConfig({ + integrations: [tailwind()], + output: 'static', + build: { + inlineStylesheets: 'auto', + }, + vite: { + resolve: { + alias: { + '@components': '/src/components', + '@layouts': '/src/layouts', + }, + }, + }, +}); diff --git a/apps/todo/apps/landing/package.json b/apps/todo/apps/landing/package.json new file mode 100644 index 000000000..a69235b12 --- /dev/null +++ b/apps/todo/apps/landing/package.json @@ -0,0 +1,34 @@ +{ + "name": "@todo/landing", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "astro dev --port 4323", + "start": "astro dev", + "build": "astro check && astro build", + "preview": "astro preview", + "astro": "astro", + "type-check": "astro check", + "format": "prettier --write .", + "clean": "rm -rf dist .astro node_modules" + }, + "dependencies": { + "@astrojs/check": "^0.9.0", + "@manacore/shared-landing-ui": "workspace:*", + "astro": "^5.16.0", + "typescript": "^5.9.2" + }, + "devDependencies": { + "@astrojs/tailwind": "^6.0.2", + "@tailwindcss/typography": "^0.5.18", + "@types/node": "^20.0.0", + "eslint": "^9.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-astro": "^1.0.0", + "prettier": "^3.6.2", + "prettier-plugin-astro": "^0.14.1", + "prettier-plugin-tailwindcss": "^0.6.14", + "tailwindcss": "^3.4.0" + } +} diff --git a/apps/todo/apps/landing/public/favicon.svg b/apps/todo/apps/landing/public/favicon.svg new file mode 100644 index 000000000..2a01e700a --- /dev/null +++ b/apps/todo/apps/landing/public/favicon.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/todo/apps/landing/src/components/CTA.astro b/apps/todo/apps/landing/src/components/CTA.astro new file mode 100644 index 000000000..571f542c7 --- /dev/null +++ b/apps/todo/apps/landing/src/components/CTA.astro @@ -0,0 +1,60 @@ +--- +// Call to Action section +--- + +
+ +
+
+ +
+
+

+ Bereit, produktiver zu werden? +

+

+ Starte kostenlos und erlebe, wie einfach Task-Management sein kann. Keine Kreditkarte + erforderlich. +

+ + + + +
+
+ + + + Kostenlos starten +
+
+ + + + Keine Kreditkarte +
+
+ + + + Jederzeit kündbar +
+
+
+
+
diff --git a/apps/todo/apps/landing/src/components/Features.astro b/apps/todo/apps/landing/src/components/Features.astro new file mode 100644 index 000000000..a5605804d --- /dev/null +++ b/apps/todo/apps/landing/src/components/Features.astro @@ -0,0 +1,84 @@ +--- +// Features section for Todo landing page + +const features = [ + { + icon: ` + + `, + title: 'Projekte & Ordner', + description: + 'Organisiere deine Aufgaben in farbcodierten Projekten. Behalte den Überblick über Arbeit, Privates und mehr.', + }, + { + icon: ` + + `, + title: 'Unteraufgaben', + description: + 'Teile grosse Aufgaben in handhabbare Schritte auf. Verfolge den Fortschritt mit Checklisten.', + }, + { + icon: ` + + `, + title: 'Kanban-Boards', + description: + 'Visualisiere deine Workflows mit Drag-and-Drop Kanban-Boards. Perfekt für agile Arbeitsweisen.', + }, + { + icon: ` + + `, + title: 'Wiederkehrende Tasks', + description: + 'Erstelle Tasks, die sich automatisch wiederholen - täglich, wöchentlich, monatlich oder nach deinen Regeln.', + }, + { + icon: ` + + `, + title: 'Smarte Erinnerungen', + description: + 'Verpasse nie wieder eine Deadline. Push-Benachrichtigungen und E-Mail-Erinnerungen zur rechten Zeit.', + }, + { + icon: ` + + `, + title: 'Labels & Tags', + description: + 'Kategorisiere deine Aufgaben mit farbigen Labels. Filtere und finde Tasks blitzschnell.', + }, +]; +--- + +
+
+ +
+ + Funktionen + +

Alles was du brauchst

+

+ Todo bietet alle Funktionen, die du für effektives Task-Management benötigst. +

+
+ + +
+ { + features.map((feature) => ( +
+
+ +
+

{feature.title}

+

{feature.description}

+
+ )) + } +
+
+
diff --git a/apps/todo/apps/landing/src/components/Footer.astro b/apps/todo/apps/landing/src/components/Footer.astro new file mode 100644 index 000000000..53d95e0ac --- /dev/null +++ b/apps/todo/apps/landing/src/components/Footer.astro @@ -0,0 +1,109 @@ +--- +// Footer component + +const currentYear = new Date().getFullYear(); + +const links = { + product: [ + { name: 'Funktionen', href: '#features' }, + { name: 'Preise', href: '#pricing' }, + { name: 'Changelog', href: '/changelog' }, + { name: 'Roadmap', href: '/roadmap' }, + ], + legal: [ + { name: 'Impressum', href: '/impressum' }, + { name: 'Datenschutz', href: '/datenschutz' }, + { name: 'AGB', href: '/agb' }, + ], + support: [ + { name: 'FAQ', href: '/faq' }, + { name: 'Kontakt', href: '/kontakt' }, + { name: 'Status', href: '/status' }, + ], +}; +--- + + diff --git a/apps/todo/apps/landing/src/components/Hero.astro b/apps/todo/apps/landing/src/components/Hero.astro new file mode 100644 index 000000000..61539d116 --- /dev/null +++ b/apps/todo/apps/landing/src/components/Hero.astro @@ -0,0 +1,146 @@ +--- +// Hero section for Todo landing page +--- + +
+ +
+ + +
+ +
+
+ +
+ + + + Smart Task-Management +
+ + +

+ Erledige mehr mit + weniger Stress +

+ + +

+ Projekte, Unteraufgaben, Kanban-Boards, wiederkehrende Tasks und smarte Erinnerungen - alles + an einem Ort. Behalte den Überblick über alles, was wichtig ist. +

+ + + + + +
+
+ { + [1, 2, 3, 4, 5].map((i) => ( +
+ )) + } +
+

+ 500+ Nutzer vertrauen Todo +

+
+
+ + +
+
+
+
+
+
+
+
+
+
+ +
+
+

Heute

+
+ +
+
+
+ { + [ + { title: 'Meeting mit Team vorbereiten', priority: 'high', done: true }, + { title: 'E-Mails beantworten', priority: 'medium', done: false }, + { title: 'Projekt-Dokumentation aktualisieren', priority: 'low', done: false }, + { title: 'Code-Review durchführen', priority: 'high', done: false }, + { title: 'Sprint Planning vorbereiten', priority: 'medium', done: false }, + ].map((task) => ( +
+
+ {task.done && ( + + + + )} +
+ + {task.title} + +
+ )) + } +
+
+
+
+
+
+
diff --git a/apps/todo/apps/landing/src/layouts/Layout.astro b/apps/todo/apps/landing/src/layouts/Layout.astro new file mode 100644 index 000000000..758461035 --- /dev/null +++ b/apps/todo/apps/landing/src/layouts/Layout.astro @@ -0,0 +1,48 @@ +--- +import '../styles/global.css'; + +interface Props { + title?: string; + description?: string; +} + +const { + title = 'Todo - Smart Task Management', + description = 'Organisiere deine Aufgaben intelligent. Projekte, Unteraufgaben, wiederkehrende Tasks, Kanban-Boards und mehr. Kostenlos starten.', +} = Astro.props; +--- + + + + + + + + + + + + + + + + + + + + + + + + + + + {title} + + + + + diff --git a/apps/todo/apps/landing/src/pages/index.astro b/apps/todo/apps/landing/src/pages/index.astro new file mode 100644 index 000000000..5eb9fd4bb --- /dev/null +++ b/apps/todo/apps/landing/src/pages/index.astro @@ -0,0 +1,253 @@ +--- +import Layout from '@layouts/Layout.astro'; +import Hero from '@components/Hero.astro'; +import Features from '@components/Features.astro'; +import CTA from '@components/CTA.astro'; +import Footer from '@components/Footer.astro'; + +// Try to import shared components if available +let StepsSection: any = null; +let PricingSection: any = null; +try { + const shared = await import('@manacore/shared-landing-ui/sections/StepsSection.astro'); + StepsSection = shared.default; +} catch { + // Shared component not available +} +try { + const shared = await import('@manacore/shared-landing-ui/sections/PricingSection.astro'); + PricingSection = shared.default; +} catch { + // Shared component not available +} + +// Steps data +const steps = [ + { + number: '1', + title: 'Aufgabe erfassen', + description: + 'Erstelle Aufgaben mit natürlicher Sprache. Füge Fälligkeiten, Prioritäten und Tags hinzu - alles in einem Schritt.', + image: '/screenshots/quick-add.png', + }, + { + number: '2', + title: 'Organisieren', + description: + 'Ordne Aufgaben in Projekte ein, füge Unteraufgaben hinzu und nutze das Kanban-Board für visuelle Workflows.', + image: '/screenshots/organize.png', + }, + { + number: '3', + title: 'Erledigen', + description: + 'Arbeite deine Tasks ab, verfolge deinen Fortschritt in Statistiken und feiere deine Erfolge.', + image: '/screenshots/complete.png', + }, +]; + +// Pricing data +const pricingPlans = [ + { + name: 'Free', + price: '0', + period: '/Monat', + description: 'Perfekt für Einzelpersonen', + features: [ + { text: '3 Projekte', included: true }, + { text: 'Unbegrenzte Aufgaben', included: true }, + { text: 'Labels & Tags', included: true }, + { text: 'Web-App Zugang', included: true }, + { text: 'Kanban-Boards', included: false }, + { text: 'Wiederkehrende Tasks', included: false }, + ], + cta: { + text: 'Kostenlos starten', + href: '#', + }, + }, + { + name: 'Pro', + price: '4,99', + period: '/Monat', + description: 'Für Power-User', + features: [ + { text: 'Unbegrenzte Projekte', included: true }, + { text: 'Unbegrenzte Aufgaben', included: true }, + { text: 'Kanban-Boards', included: true }, + { text: 'Wiederkehrende Tasks', included: true }, + { text: 'Statistiken & Heatmaps', included: true }, + { text: 'Priority Support', included: true }, + ], + cta: { + text: 'Pro starten', + href: '#', + }, + highlighted: true, + badge: 'Beliebt', + }, + { + name: 'Team', + price: '9,99', + period: '/Monat', + description: 'Für Teams & Unternehmen', + features: [ + { text: 'Alles aus Pro', included: true }, + { text: 'Team-Verwaltung', included: true }, + { text: 'Geteilte Projekte', included: true }, + { text: 'API-Zugang', included: true }, + { text: 'Admin-Dashboard', included: true }, + { text: 'SLA Garantie', included: true }, + ], + cta: { + text: 'Team erstellen', + href: '#', + }, + }, +]; +--- + + + + + + { + StepsSection && ( + + ) + } + + { + !StepsSection && ( +
+
+
+ + So funktioniert's + +

So einfach geht's

+

In drei Schritten zur Produktivität

+
+ +
+ {steps.map((step) => ( +
+
+ {step.number} +
+

{step.title}

+

{step.description}

+
+ ))} +
+
+
+ ) + } + + { + PricingSection && ( + + ) + } + + { + !PricingSection && ( +
+
+
+ + Preise + +

Einfache, transparente Preise

+

Starte kostenlos, upgrade wenn du mehr brauchst

+
+ +
+ {pricingPlans.map((plan) => ( +
+ {plan.badge && ( +
+ {plan.badge} +
+ )} +

{plan.name}

+

{plan.description}

+
+ {plan.price}€ + {plan.period} +
+
    + {plan.features.map((feature) => ( +
  • + {feature.included ? ( + + + + ) : ( + + + + )} + {feature.text} +
  • + ))} +
+ + {plan.cta.text} + +
+ ))} +
+
+
+ ) + } + + +