MVP fertig

This commit is contained in:
2025-09-04 14:55:04 +02:00
parent bccaefedb3
commit fc62302f97
11 changed files with 515 additions and 223 deletions

View File

@@ -32,11 +32,6 @@ export default function ClientSidePage() {
title: "Zero Data Storage",
description: "We don't store any passwords, user data, or personal information. Everything is processed locally and immediately discarded."
},
{
icon: Shield,
title: "Open Source Verification",
description: "All code is publicly available and auditable. You can verify our security claims by reviewing the source code."
}
]
const technicalDetails = [
@@ -98,7 +93,7 @@ export default function ClientSidePage() {
className="flex items-center text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors"
>
<ArrowLeft className="h-5 w-5 mr-2" />
Zurück zu PassMaster
Back to PassMaster
</Link>
</div>
</div>
@@ -118,10 +113,10 @@ export default function ClientSidePage() {
</div>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
Client-Side Sicherheit
Client-Side Security
</h1>
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto">
Maximale Sicherheit durch lokale Verarbeitung. Ihre Passwörter werden ausschließlich in Ihrem Browser generiert und verlassen niemals Ihr Gerät.
Maximum security through local processing. Your passwords are generated exclusively in your browser and never leave your device.
</p>
</motion.div>
@@ -135,14 +130,14 @@ export default function ClientSidePage() {
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Sicherheits-Features
Security Features
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300">
Jeder Aspekt von PassMaster ist darauf ausgelegt, Ihre Sicherheit zu maximieren.
Every aspect of PassMaster is designed to maximize your security.
</p>
</motion.div>
<div className="grid md:grid-cols-2 gap-8">
<div className="grid md:grid-cols-3 gap-8">
{securityFeatures.map((feature, index) => (
<motion.div
key={feature.title}
@@ -182,10 +177,10 @@ export default function ClientSidePage() {
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Warum Client-Side Sicherheit?
Why Client-Side Security?
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300">
Die Vorteile der lokalen Passwort-Generierung.
The benefits of local password generation.
</p>
</motion.div>
@@ -225,10 +220,10 @@ export default function ClientSidePage() {
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Technische Details
Technical Details
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300">
Wie PassMaster Ihre Sicherheit gewährleistet.
How PassMaster ensures your security.
</p>
</motion.div>
@@ -270,28 +265,24 @@ export default function ClientSidePage() {
<div className="flex items-center mb-6">
<FileText className="h-8 w-8 text-green-600 mr-3" />
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
Technische Implementierung
Technical Implementation
</h2>
</div>
<div className="prose dark:prose-invert max-w-none">
<h3 className="text-lg font-semibold mb-4">Wie PassMaster funktioniert</h3>
<h3 className="text-lg font-semibold mb-4">How PassMaster Works</h3>
<ul className="space-y-3 text-gray-600 dark:text-gray-300">
<li className="flex items-start space-x-3">
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
<span><strong>Lokale Verarbeitung:</strong> Alle Passwort-Generierung erfolgt in Ihrem Browser mit JavaScript</span>
<span><strong>Local Processing:</strong> All password generation happens in your browser using JavaScript</span>
</li>
<li className="flex items-start space-x-3">
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
<span><strong>Keine Netzwerk-Anfragen:</strong> Die App funktioniert nach dem ersten Laden vollständig offline</span>
<span><strong>No Network Requests:</strong> The app works completely offline after initial load</span>
</li>
<li className="flex items-start space-x-3">
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
<span><strong>Open Source:</strong> Der gesamte Code ist öffentlich auf GitHub verfügbar zur Überprüfung</span>
</li>
<li className="flex items-start space-x-3">
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
<span><strong>Keine Abhängigkeiten:</strong> Wir verwenden keine externen Services oder Drittanbieter-Bibliotheken</span>
<span><strong>No Dependencies:</strong> We don't use external services or third-party libraries</span>
</li>
</ul>
</div>
@@ -308,26 +299,18 @@ export default function ClientSidePage() {
className="bg-green-50 dark:bg-green-900/20 rounded-lg p-8"
>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-4">
Fragen zur Sicherheit?
Questions About Security?
</h2>
<p className="text-gray-600 dark:text-gray-300 mb-6">
Wir sind verpflichtet zu Transparenz. Wenn Sie Fragen zu unseren Sicherheitspraktiken haben,
überprüfen Sie unseren Quellcode oder kontaktieren Sie uns.
We are committed to transparency. If you have questions about our security practices,
please contact us.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<a
href="https://github.com/your-repo/passmaster"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-green-600 hover:bg-green-700 transition-colors"
>
Quellcode ansehen
</a>
<div className="flex justify-center">
<Link
href="/"
className="inline-flex items-center justify-center px-6 py-3 border border-gray-300 dark:border-gray-600 text-base font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
Zum Generator
Back to Generator
</Link>
</div>
</motion.div>

View File

@@ -17,88 +17,88 @@ export default function ExcludeSimilarPage() {
const readabilityFeatures = [
{
icon: Eye,
title: "Ähnliche Zeichen ausschließen",
description: "Verwirrende Zeichen wie 0/O, 1/l/I werden automatisch ausgeschlossen, um Lesbarkeit zu verbessern."
title: "Exclude Similar Characters",
description: "Confusing characters like 0/O, 1/l/I are automatically excluded to improve readability."
},
{
icon: BookOpen,
title: "Bessere Lesbarkeit",
description: "Passwörter sind leichter zu lesen und zu tippen, ohne die Sicherheit zu beeinträchtigen."
title: "Better Readability",
description: "Passwords are easier to read and type without compromising security."
},
{
icon: Target,
title: "Weniger Fehler",
description: "Reduziert Tippfehler beim manuellen Eingeben von Passwörtern erheblich."
title: "Fewer Errors",
description: "Significantly reduces typing errors when manually entering passwords."
},
{
icon: Users,
title: "Benutzerfreundlich",
description: "Besonders nützlich für ältere Benutzer oder bei der Eingabe auf mobilen Geräten."
title: "User-Friendly",
description: "Especially useful for older users or when typing on mobile devices."
}
]
const excludedCharacters = [
{
category: "Zahlen und Buchstaben",
characters: ["0 (Null)", "O (Großes O)", "1 (Eins)", "l (kleines L)", "I (Großes i)"],
reason: "Diese Zeichen sehen in vielen Schriftarten identisch aus"
category: "Numbers and Letters",
characters: ["0 (Zero)", "O (Capital O)", "1 (One)", "l (lowercase L)", "I (Capital I)"],
reason: "These characters look identical in many fonts"
},
{
category: "Sonderzeichen",
characters: ["| (Pipe)", "` (Backtick)", "' (Apostroph)", "\" (Anführungszeichen)"],
reason: "Können in verschiedenen Kontexten verwirrend sein"
category: "Special Characters",
characters: ["| (Pipe)", "` (Backtick)", "' (Apostrophe)", "\" (Quotation marks)"],
reason: "Can be confusing in different contexts"
},
{
category: "Leerzeichen",
characters: [" (Leerzeichen)", " (Mehrfache Leerzeichen)"],
reason: "Können beim Kopieren/Einfügen Probleme verursachen"
category: "Spaces",
characters: [" (Space)", " (Multiple spaces)"],
reason: "Can cause problems when copying/pasting"
}
]
const benefits = [
{
icon: Zap,
title: "Schnellere Eingabe",
description: "Weniger Verwirrung beim manuellen Tippen von Passwörtern."
title: "Faster Input",
description: "Less confusion when manually typing passwords."
},
{
icon: CheckCircle,
title: "Weniger Fehler",
description: "Reduziert Tippfehler und damit verbundene Frustration."
title: "Fewer Errors",
description: "Reduces typing errors and associated frustration."
},
{
icon: Eye,
title: "Bessere UX",
description: "Verbessert die Benutzererfahrung ohne Sicherheitsverlust."
title: "Better UX",
description: "Improves user experience without security loss."
}
]
const securityImpact = [
{
title: "Sicherheit bleibt hoch",
title: "Security Remains High",
items: [
"Entropie wird nur minimal reduziert",
"Noch immer über 80 Zeichen verfügbar",
"Kryptographisch sichere Generierung",
"Ausreichend für alle praktischen Zwecke"
"Entropy is only minimally reduced",
"Still over 80 characters available",
"Cryptographically secure generation",
"Sufficient for all practical purposes"
]
},
{
title: "Praktische Vorteile",
title: "Practical Benefits",
items: [
"Einfachere manuelle Eingabe",
"Weniger Support-Anfragen",
"Bessere Benutzerakzeptanz",
"Reduzierte Fehlerrate"
"Easier manual input",
"Fewer support requests",
"Better user acceptance",
"Reduced error rate"
]
},
{
title: "Empfohlene Verwendung",
title: "Recommended Usage",
items: [
"Für manuell eingegebene Passwörter",
"Bei älteren Benutzern",
"Auf mobilen Geräten",
"In Umgebungen mit schlechter Sichtbarkeit"
"For manually entered passwords",
"For older users",
"On mobile devices",
"In environments with poor visibility"
]
}
]
@@ -114,7 +114,7 @@ export default function ExcludeSimilarPage() {
className="flex items-center text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors"
>
<ArrowLeft className="h-5 w-5 mr-2" />
Zurück zu PassMaster
Back to PassMaster
</Link>
</div>
</div>
@@ -134,11 +134,11 @@ export default function ExcludeSimilarPage() {
</div>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
Lesbarkeit & Benutzerfreundlichkeit
Readability & User-Friendliness
</h1>
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto">
Verbessern Sie die Lesbarkeit Ihrer Passwörter ohne Sicherheit zu opfern.
Ähnliche Zeichen werden automatisch ausgeschlossen.
Improve the readability of your passwords without sacrificing security.
Similar characters are automatically excluded.
</p>
</motion.div>
@@ -152,10 +152,10 @@ export default function ExcludeSimilarPage() {
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Lesbarkeits-Features
Readability Features
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300">
Wie PassMaster die Benutzerfreundlichkeit verbessert.
How PassMaster improves user-friendliness.
</p>
</motion.div>
@@ -199,10 +199,10 @@ export default function ExcludeSimilarPage() {
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Ausgeschlossene Zeichen
Excluded Characters
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300">
Diese Zeichen werden automatisch ausgeschlossen, um Verwirrung zu vermeiden.
These characters are automatically excluded to avoid confusion.
</p>
</motion.div>
@@ -245,10 +245,10 @@ export default function ExcludeSimilarPage() {
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Vorteile der Lesbarkeit
Benefits of Readability
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300">
Warum lesbare Passwörter wichtig sind.
Why readable passwords are important.
</p>
</motion.div>
@@ -288,10 +288,10 @@ export default function ExcludeSimilarPage() {
className="text-center mb-12"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Sicherheit vs. Lesbarkeit
Security vs. Readability
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300">
Wie wir das perfekte Gleichgewicht finden.
How we find the perfect balance.
</p>
</motion.div>
@@ -331,20 +331,20 @@ export default function ExcludeSimilarPage() {
className="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border border-gray-200 dark:border-gray-700"
>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-6 text-center">
Beispiel-Vergleich
Example Comparison
</h2>
<div className="grid md:grid-cols-2 gap-8">
<div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
<XCircle className="h-5 w-5 text-red-500 mr-2" />
Ohne Lesbarkeits-Filter
Without Readability Filter
</h3>
<div className="bg-gray-100 dark:bg-gray-700 p-4 rounded-lg font-mono text-sm">
<div className="text-red-600 dark:text-red-400 mb-2">Schwer lesbar:</div>
<div className="text-red-600 dark:text-red-400 mb-2">Hard to read:</div>
<div>K9mP0lI|nQ2v</div>
<div className="text-xs text-gray-500 dark:text-gray-400 mt-2">
Verwirrende Zeichen: 0, l, I, |
Confusing characters: 0, l, I, |
</div>
</div>
</div>
@@ -352,13 +352,13 @@ export default function ExcludeSimilarPage() {
<div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
<CheckCircle className="h-5 w-5 text-green-500 mr-2" />
Mit Lesbarkeits-Filter
With Readability Filter
</h3>
<div className="bg-gray-100 dark:bg-gray-700 p-4 rounded-lg font-mono text-sm">
<div className="text-green-600 dark:text-green-400 mb-2">Leicht lesbar:</div>
<div className="text-green-600 dark:text-green-400 mb-2">Easy to read:</div>
<div>K9mP3nQ2vX7w</div>
<div className="text-xs text-gray-500 dark:text-gray-400 mt-2">
Keine verwirrenden Zeichen
No confusing characters
</div>
</div>
</div>
@@ -376,24 +376,24 @@ export default function ExcludeSimilarPage() {
className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-8"
>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-4">
Bereit für bessere Lesbarkeit?
Ready for Better Readability?
</h2>
<p className="text-gray-600 dark:text-gray-300 mb-6">
Aktivieren Sie die Lesbarkeits-Option in PassMaster und generieren Sie
benutzerfreundliche, aber dennoch sichere Passwörter.
Enable the readability option in PassMaster and generate
user-friendly, yet secure passwords.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link
href="/"
className="inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 transition-colors"
>
Jetzt ausprobieren
Try Now
</Link>
<Link
href="/client-side"
className="inline-flex items-center justify-center px-6 py-3 border border-gray-300 dark:border-gray-600 text-base font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
Sicherheit erfahren
Learn About Security
</Link>
</div>
</motion.div>

346
app/offline/page.tsx Normal file
View File

@@ -0,0 +1,346 @@
"use client"
import { useState, useEffect } from 'react'
import { motion } from 'framer-motion'
import {
Wifi,
WifiOff,
Download,
Shield,
CheckCircle,
AlertCircle,
Smartphone,
Monitor
} from 'lucide-react'
export default function OfflinePage() {
const [isOnline, setIsOnline] = useState(true)
const [isInstallable, setIsInstallable] = useState(false)
const [deferredPrompt, setDeferredPrompt] = useState<any>(null)
useEffect(() => {
setIsOnline(navigator.onLine)
const handleOnline = () => setIsOnline(true)
const handleOffline = () => setIsOnline(false)
window.addEventListener('online', handleOnline)
window.addEventListener('offline', handleOffline)
// PWA install prompt
const handleBeforeInstallPrompt = (e: any) => {
e.preventDefault()
setDeferredPrompt(e)
setIsInstallable(true)
}
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
return () => {
window.removeEventListener('online', handleOnline)
window.removeEventListener('offline', handleOffline)
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
}
}, [])
const handleInstallClick = async () => {
if (deferredPrompt) {
deferredPrompt.prompt()
const { outcome } = await deferredPrompt.userChoice
if (outcome === 'accepted') {
setDeferredPrompt(null)
setIsInstallable(false)
}
}
}
const offlineFeatures = [
{
icon: Shield,
title: "Complete Offline Functionality",
description: "All password generation features work without internet connection. Service Worker ensures local availability."
},
{
icon: WifiOff,
title: "No Data Transmission",
description: "100% client-side processing. Your passwords never leave your device, even in online mode."
},
{
icon: Download,
title: "PWA Installation",
description: "Install PassMaster as a native app. Works on desktop, tablet and smartphone."
}
]
const installSteps = [
{
step: 1,
title: "Browser Installation",
description: "Click 'Install App' in the address bar or use the button below."
},
{
step: 2,
title: "Offline Test",
description: "Disable your internet connection and test password generation."
},
{
step: 3,
title: "App Icon",
description: "PassMaster appears as an app icon on your home screen or in the app list."
}
]
return (
<div className="min-h-screen py-12">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Header */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-12"
>
<div className="flex justify-center mb-6">
<div className="p-4 bg-primary-100 dark:bg-primary-900/20 rounded-full">
{isOnline ? (
<Wifi className="h-12 w-12 text-primary-600" />
) : (
<WifiOff className="h-12 w-12 text-primary-600" />
)}
</div>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
Offline Password Generator (PWA)
</h1>
<p className="text-xl text-gray-600 dark:text-gray-300 mb-6">
Install and use PassMaster completely offline. Service Worker and local storage for maximum independence.
</p>
{/* Connection Status */}
<div className={`inline-flex items-center px-4 py-2 rounded-full text-sm font-medium ${
isOnline
? 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-300'
: 'bg-orange-100 text-orange-800 dark:bg-orange-900/20 dark:text-orange-300'
}`}>
{isOnline ? (
<>
<CheckCircle className="h-4 w-4 mr-2" />
Online - Ready for Installation
</>
) : (
<>
<AlertCircle className="h-4 w-4 mr-2" />
Offline Mode Active
</>
)}
</div>
</motion.div>
{/* Install Button */}
{isInstallable && (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
className="text-center mb-12"
>
<button
onClick={handleInstallClick}
className="btn-primary text-lg px-8 py-4 inline-flex items-center space-x-2"
>
<Download className="h-5 w-5" />
<span>Install PassMaster as App</span>
</button>
</motion.div>
)}
{/* Features */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="mb-16"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-8 text-center">
Service Worker & Installation | FAQ | Security
</h2>
<div className="grid md:grid-cols-3 gap-8">
{offlineFeatures.map((feature, index) => (
<motion.div
key={feature.title}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 + index * 0.1 }}
className="card text-center"
>
<div className="flex justify-center mb-4">
<div className="p-3 bg-primary-100 dark:bg-primary-900/20 rounded-full">
<feature.icon className="h-8 w-8 text-primary-600" />
</div>
</div>
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
{feature.title}
</h3>
<p className="text-gray-600 dark:text-gray-300">
{feature.description}
</p>
</motion.div>
))}
</div>
</motion.div>
{/* Installation Steps */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
className="mb-16"
>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-8 text-center">
PWA Installation in 3 Steps
</h2>
<div className="space-y-6">
{installSteps.map((step, index) => (
<motion.div
key={step.step}
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.5 + index * 0.1 }}
className="flex items-start space-x-4 card"
>
<div className="flex-shrink-0 w-8 h-8 bg-primary-600 text-white rounded-full flex items-center justify-center font-semibold">
{step.step}
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
{step.title}
</h3>
<p className="text-gray-600 dark:text-gray-300">
{step.description}
</p>
</div>
</motion.div>
))}
</div>
</motion.div>
{/* Platform Support */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.6 }}
className="mb-16"
>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-8 text-center">
Platform Support
</h2>
<div className="grid md:grid-cols-2 gap-8">
<div className="card text-center">
<Monitor className="h-12 w-12 text-primary-600 mx-auto mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Desktop Browser
</h3>
<p className="text-gray-600 dark:text-gray-300">
Chrome, Firefox, Safari, Edge - All modern browsers support PWA installation
</p>
</div>
<div className="card text-center">
<Smartphone className="h-12 w-12 text-primary-600 mx-auto mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Mobile Devices
</h3>
<p className="text-gray-600 dark:text-gray-300">
iOS Safari, Android Chrome - Installation via "Add to Home Screen"
</p>
</div>
</div>
</motion.div>
{/* FAQ Section */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.7 }}
className="card"
>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">
Offline FAQ
</h2>
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
How do I install PassMaster as a PWA?
</h3>
<p className="text-gray-600 dark:text-gray-300">
On supported browsers, an installation icon automatically appears in the address bar.
Alternatively, use the "Install App" button on this page.
</p>
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
What offline features are available?
</h3>
<p className="text-gray-600 dark:text-gray-300">
All main functions: password generation, parameter customization, entropy calculation,
and copying to clipboard work completely offline.
</p>
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
What is stored locally?
</h3>
<p className="text-gray-600 dark:text-gray-300">
Only app files (HTML, CSS, JavaScript) are stored in the browser cache.
No passwords or personal data are ever stored.
</p>
</div>
</div>
</motion.div>
{/* JSON-LD for FAQ */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How do I install PassMaster as a PWA?",
"acceptedAnswer": {
"@type": "Answer",
"text": "On supported browsers, an installation icon automatically appears in the address bar. Alternatively, use the 'Install App' button."
}
},
{
"@type": "Question",
"name": "What offline features are available?",
"acceptedAnswer": {
"@type": "Answer",
"text": "All main functions: password generation, parameter customization, entropy calculation, and copying work completely offline."
}
},
{
"@type": "Question",
"name": "What is stored locally?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Only app files are stored in the browser cache. No passwords or personal data are ever stored."
}
}
]
})
}}
/>
</div>
</div>
)
}

View File

@@ -43,8 +43,8 @@ export default function HomePage() {
},
{
icon: Globe,
title: "100% Open Source",
description: "Transparent code that you can audit, modify, and contribute to on GitHub."
title: "100% Privacy-First",
description: "Transparent code that you can audit. No tracking, no data collection, no server communication."
}
]
@@ -68,7 +68,7 @@ export default function HomePage() {
Free Offline Secure Password Generator
</h1>
<p className="text-xl md:text-2xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
Generate strong, unique passwords in seconds fully client-side, private, and open-source.
Generate strong, unique passwords in seconds fully client-side, private, and secure.
</p>
</motion.div>

View File

@@ -29,11 +29,6 @@ export default function PrivacyPage() {
title: "No Server Storage",
description: "We don't store any passwords, user data, or personal information on our servers."
},
{
icon: Shield,
title: "Open Source",
description: "All code is publicly available and auditable. You can verify our privacy claims."
}
]
const dataPractices = [
@@ -227,10 +222,6 @@ export default function PrivacyPage() {
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
<span><strong>No Network Requests:</strong> The app works completely offline after initial load</span>
</li>
<li className="flex items-start space-x-3">
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
<span><strong>Open Source:</strong> All code is publicly available on GitHub for verification</span>
</li>
<li className="flex items-start space-x-3">
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
<span><strong>No Dependencies:</strong> We don't use external services or third-party libraries that could track you</span>
@@ -254,17 +245,9 @@ export default function PrivacyPage() {
</h2>
<p className="text-gray-600 dark:text-gray-300 mb-6">
We're committed to transparency. If you have any questions about our privacy practices,
please review our source code or contact us.
please contact us.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<a
href="https://github.com/your-repo/passmaster"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 transition-colors"
>
View Source Code
</a>
<div className="flex justify-center">
<Link
href="/"
className="inline-flex items-center justify-center px-6 py-3 border border-gray-300 dark:border-gray-600 text-base font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"