feat: implement author pages, app layout, and authentication client infrastructure

This commit is contained in:
Timo Knuth
2026-04-08 19:39:01 +02:00
parent 14c3cde7e6
commit cc4afb6f51
17 changed files with 115 additions and 100 deletions

BIN
public/favicon1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@@ -166,7 +166,7 @@ export default function AppLayout({
>
<div className="flex items-center justify-between p-4 border-b border-gray-200">
<Link href="/" className="flex items-center space-x-2">
<img src="/logo.svg" alt="QR Master" className="w-8 h-8" />
<img src="/favicon1.png" alt="QR Master" className="w-16 h-16 rounded-full object-cover" />
<span className="text-xl font-bold text-gray-900">QR Master</span>
</Link>
<button

View File

@@ -10,10 +10,10 @@ export const metadata: Metadata = {
robots: { index: false, follow: false },
icons: {
icon: [
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/logo.svg', type: 'image/svg+xml' },
{ url: '/favicon1.png', sizes: '2048x2048', type: 'image/png' },
],
apple: '/logo.svg',
shortcut: '/favicon1.png',
apple: '/favicon1.png',
},
};

View File

@@ -45,7 +45,7 @@ export default function ForgotPasswordPage() {
<div className="w-full max-w-md">
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center space-x-2 mb-6">
<img src="/logo.svg" alt="QR Master" className="w-10 h-10" />
<img src="/favicon1.png" alt="QR Master" className="w-10 h-10 rounded-full object-cover" />
<span className="text-2xl font-bold text-gray-900">QR Master</span>
</Link>
<h1 className="text-3xl font-bold text-gray-900">Check Your Email</h1>
@@ -99,7 +99,7 @@ export default function ForgotPasswordPage() {
<div className="w-full max-w-md">
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center space-x-2 mb-6">
<img src="/logo.svg" alt="QR Master" className="w-10 h-10" />
<img src="/favicon1.png" alt="QR Master" className="w-10 h-10 rounded-full object-cover" />
<span className="text-2xl font-bold text-gray-900">QR Master</span>
</Link>
<h1 className="text-3xl font-bold text-gray-900">Forgot Password?</h1>

View File

@@ -80,7 +80,7 @@ export default function LoginClient({ showPageHeading = true }: LoginClientProps
<div className="w-full max-w-md">
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center space-x-2 mb-6">
<img src="/logo.svg" alt="QR Master" className="w-10 h-10" />
<img src="/favicon1.png" alt="QR Master" className="w-10 h-10 rounded-full object-cover" />
<span className="text-2xl font-bold text-gray-900">QR Master</span>
</Link>
{showPageHeading ? (

View File

@@ -78,7 +78,7 @@ export default function ResetPasswordPage() {
<div className="w-full max-w-md">
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center space-x-2 mb-6">
<img src="/logo.svg" alt="QR Master" className="w-10 h-10" />
<img src="/favicon1.png" alt="QR Master" className="w-10 h-10 rounded-full object-cover" />
<span className="text-2xl font-bold text-gray-900">QR Master</span>
</Link>
<h1 className="text-3xl font-bold text-gray-900">Password Reset Successful</h1>
@@ -120,7 +120,7 @@ export default function ResetPasswordPage() {
<div className="w-full max-w-md">
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center space-x-2 mb-6">
<img src="/logo.svg" alt="QR Master" className="w-10 h-10" />
<img src="/favicon1.png" alt="QR Master" className="w-10 h-10 rounded-full object-cover" />
<span className="text-2xl font-bold text-gray-900">QR Master</span>
</Link>
<h1 className="text-3xl font-bold text-gray-900">Reset Your Password</h1>

View File

@@ -89,7 +89,7 @@ export default function SignupClient() {
<div className="w-full max-w-md">
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center space-x-2 mb-6">
<img src="/logo.svg" alt="QR Master" className="w-10 h-10" />
<img src="/favicon1.png" alt="QR Master" className="w-10 h-10 rounded-full object-cover" />
<span className="text-2xl font-bold text-gray-900">QR Master</span>
</Link>
<h1 className="text-3xl font-bold text-gray-900">Create Account</h1>

View File

@@ -6,11 +6,12 @@ import { usePathname } from 'next/navigation';
import { Button } from '@/components/ui/Button';
import { Footer } from '@/components/ui/Footer';
import en from '@/i18n/en.json';
import { ChevronDown, BookOpen, Building2, Wifi, Contact, MessageCircle, QrCode, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon, Star } from 'lucide-react';
import { ChevronDown, BookOpen, Building2, Wifi, Contact, MessageCircle, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon, Star } from 'lucide-react';
import { cn } from '@/lib/utils';
import { AnimatePresence, motion } from 'framer-motion';
import { allUseCases } from '@/lib/growth-pages';
import { industryPages } from '@/lib/industry-pages';
import Image from 'next/image';
export default function MarketingLayout({
children,
@@ -142,9 +143,16 @@ export default function MarketingLayout({
>
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl h-20 flex items-center justify-between">
{/* Logo */}
<Link href="/" className="flex items-center space-x-2.5 group">
<div className="relative w-9 h-9 flex items-center justify-center bg-indigo-600 rounded-lg shadow-indigo-200 shadow-lg group-hover:scale-105 transition-transform duration-200">
<QrCode className="w-5 h-5 text-white" />
<Link href="/" className="flex items-center space-x-3 group">
<div className="relative w-16 h-16 overflow-hidden rounded-full shadow-indigo-200 shadow-lg group-hover:scale-105 transition-transform duration-200">
<Image
src="/favicon1.png"
alt="QR Master"
fill
sizes="64px"
className="object-cover"
priority
/>
</div>
<span className="text-xl font-bold text-slate-900 tracking-tight group-hover:text-indigo-600 transition-colors">QR Master</span>
</Link>

View File

@@ -59,7 +59,7 @@ export default function AuthorPage({ params }: { params: { slug: string } }) {
<div className="space-y-3">
<div className="flex items-center gap-3">
<h1 className="text-3xl font-extrabold text-gray-900">{author.name}</h1>
<Image src="/logo.svg" alt="QR Master" width={24} height={24} className="opacity-80" />
<Image src="/favicon1.png" alt="QR Master" width={24} height={24} className="rounded-full object-cover opacity-90" />
</div>
<p className="text-lg text-blue-600 font-medium">{author.role}</p>
<p className="text-gray-600 max-w-xl">{author.bio}</p>

View File

@@ -19,10 +19,10 @@ export const metadata: Metadata = {
: { index: false, follow: false },
icons: {
icon: [
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/logo.svg', type: 'image/svg+xml' },
{ url: '/favicon1.png', sizes: '2048x2048', type: 'image/png' },
],
apple: '/logo.svg',
shortcut: '/favicon1.png',
apple: '/favicon1.png',
},
twitter: {
card: 'summary_large_image',

View File

@@ -20,11 +20,10 @@ export const metadata: Metadata = {
: { index: false, follow: false },
icons: {
icon: [
{ url: '/favicon.ico', type: 'image/x-icon' },
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/logo.svg', type: 'image/svg+xml' },
{ url: '/favicon1.png', sizes: '2048x2048', type: 'image/png' },
],
apple: '/logo.svg',
shortcut: '/favicon1.png',
apple: '/favicon1.png',
},
twitter: {
card: 'summary_large_image',

View File

@@ -6,10 +6,10 @@ export const metadata = {
description: 'Download contact information',
icons: {
icon: [
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/logo.svg', type: 'image/svg+xml' },
{ url: '/favicon1.png', sizes: '2048x2048', type: 'image/png' },
],
apple: '/logo.svg',
shortcut: '/favicon1.png',
apple: '/favicon1.png',
},
};

View File

@@ -6,9 +6,10 @@ import { usePathname } from 'next/navigation';
import { Button } from '@/components/ui/Button';
import { Footer } from '@/components/ui/Footer';
import de from '@/i18n/de.json';
import { ChevronDown, Wifi, Contact, MessageCircle, QrCode, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon } from 'lucide-react';
import { ChevronDown, Wifi, Contact, MessageCircle, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
import { AnimatePresence, motion } from 'framer-motion';
import Image from 'next/image';
export default function MarketingLayout({
children,
@@ -109,9 +110,16 @@ export default function MarketingLayout({
>
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl h-20 flex items-center justify-between">
{/* Logo */}
<Link href="/" className="flex items-center space-x-2.5 group">
<div className="relative w-9 h-9 flex items-center justify-center bg-indigo-600 rounded-lg shadow-indigo-200 shadow-lg group-hover:scale-105 transition-transform duration-200">
<QrCode className="w-5 h-5 text-white" />
<Link href="/" className="flex items-center space-x-3 group">
<div className="relative w-16 h-16 overflow-hidden rounded-full shadow-indigo-200 shadow-lg group-hover:scale-105 transition-transform duration-200">
<Image
src="/favicon1.png"
alt="QR Master"
fill
sizes="64px"
className="object-cover"
priority
/>
</div>
<span className="text-xl font-bold text-slate-900 tracking-tight group-hover:text-indigo-600 transition-colors">QR Master</span>
</Link>

View File

@@ -15,10 +15,10 @@ export const metadata: Metadata = {
metadataBase: new URL('https://www.qrmaster.net'),
icons: {
icon: [
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/logo.svg', type: 'image/svg+xml' },
{ url: '/favicon1.png', sizes: '2048x2048', type: 'image/png' },
],
apple: '/logo.svg',
shortcut: '/favicon1.png',
apple: '/favicon1.png',
},
openGraph: {
type: 'website',

View File

@@ -20,7 +20,7 @@ export function Footer({ variant = 'marketing', t }: FooterProps) {
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-8">
<div>
<Link href="/" className="flex items-center space-x-2 mb-4 hover:opacity-80 transition-opacity">
<img src="/logo.svg" alt="QR Master Logo" className="w-10 h-10" />
<img src="/favicon1.png" alt="QR Master Logo" className="w-[68px] h-[68px] rounded-full object-cover" />
<span className={`text-xl font-bold ${isDashboard ? 'text-gray-900' : ''}`}>QR Master</span>
</Link>
<p className={isDashboard ? 'text-gray-500' : 'text-gray-400'}>
@@ -136,7 +136,7 @@ export function Footer({ variant = 'marketing', t }: FooterProps) {
) : (
<div></div>
)}
<p>&copy; 2025 {translations.rights_reserved}</p>
<p>&copy; 2026 {translations.rights_reserved}</p>
<div className="w-12"></div>
</div>
</div>

View File

@@ -6,7 +6,7 @@ export const authors: AuthorProfile[] = [
name: "Timo Knuth",
role: "Founder, Growth & Product Marketing",
bio: "Building QR Master: dynamic QR management, tracking, and bulk ops for B2B teams.",
image: "/favicon.svg",
image: "/favicon1.png",
sameAs: [
"https://www.wikidata.org/wiki/Q137919835",
"https://www.linkedin.com/in/qr-master-44b6863a2/",

View File

@@ -154,7 +154,7 @@ export async function sendPasswordResetEmail(email: string, resetToken: string)
Secure QR Code Analytics & Management
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
© 2026 QR Master. All rights reserved.
</p>
<p style="margin: 15px 0 0 0; color: #aaaaaa; font-size: 11px;">
This is an automated security email. Please do not reply.
@@ -326,7 +326,7 @@ export async function sendNewsletterWelcomeEmail(email: string) {
<a href="https://www.qrmaster.net" style="color: #667eea; text-decoration: none;">www.qrmaster.net</a>
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
© 2026 QR Master. All rights reserved.
</p>
<p style="margin: 15px 0 0 0; color: #aaaaaa; font-size: 11px;">
You're receiving this because you signed up for AI feature notifications.
@@ -506,7 +506,7 @@ export async function sendAIFeatureLaunchEmail(email: string) {
<a href="https://www.qrmaster.net/faq" style="color: #667eea; text-decoration: none;">Help</a>
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
© 2026 QR Master. All rights reserved.
</p>
<p style="margin: 15px 0 0 0; color: #aaaaaa; font-size: 11px;">
You received this because you subscribed to AI feature launch notifications.
@@ -806,7 +806,7 @@ export async function sendWelcomeEmail(email: string, name: string) {
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="width:56px; height:56px; background-color:#0B0D14; border-radius:50%; text-align:center; vertical-align:middle; border:2px solid ${clr.border}; box-shadow:0 4px 10px rgba(0,0,0,0.05);">
<img src="${appUrl}/favicon.svg" width="32" height="32" alt="Timo" style="display:inline-block; vertical-align:middle;">
<img src="${appUrl}/favicon1.png" width="32" height="32" alt="Timo" style="display:inline-block; vertical-align:middle; border-radius:50%; object-fit:cover;">
</td>
</tr>
</table>