create-frootkit 1.2.8 → 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/auth/src/app/dashboard/layout.tsx +14 -9
- package/templates/auth/src/app/dashboard/page.tsx +55 -24
- package/templates/auth/src/app/layout.tsx +3 -3
- package/templates/auth/src/app/login/page.tsx +5 -1
- package/templates/auth/src/app/page.tsx +103 -45
- package/templates/auth/src/app/signup/page.tsx +5 -1
- package/templates/auth/src/components/AuthForm.tsx +34 -19
- package/templates/auth/src/components/DashboardNav.tsx +97 -56
- package/templates/auth/src/components/MetricCard.tsx +13 -6
- package/templates/auth/src/components/Navbar.tsx +13 -12
- package/templates/auth/src/styles.css +27 -5
- package/templates/blog/src/app/blog/[slug]/page.tsx +19 -18
- package/templates/blog/src/app/layout.tsx +4 -4
- package/templates/blog/src/app/page.tsx +15 -14
- package/templates/blog/src/components/Footer.tsx +6 -6
- package/templates/blog/src/components/Navbar.tsx +17 -15
- package/templates/blog/src/components/Newsletter.tsx +11 -9
- package/templates/blog/src/components/PostCard.tsx +29 -27
- package/templates/blog/src/styles.css +14 -5
- package/templates/ecommerce/src/app/cart/page.tsx +3 -3
- package/templates/ecommerce/src/app/layout.tsx +2 -2
- package/templates/ecommerce/src/app/page.tsx +37 -15
- package/templates/ecommerce/src/app/products/[id]/page.tsx +34 -25
- package/templates/ecommerce/src/components/CartDrawer.tsx +20 -17
- package/templates/ecommerce/src/components/Footer.tsx +6 -6
- package/templates/ecommerce/src/components/Navbar.tsx +21 -14
- package/templates/ecommerce/src/components/ProductCard.tsx +22 -15
- package/templates/ecommerce/src/data/products.ts +17 -11
- package/templates/ecommerce/src/styles.css +29 -5
- package/templates/empty/src/app/layout.tsx +5 -5
- package/templates/empty/src/app/page.tsx +10 -9
- package/templates/empty/src/styles.css +13 -15
- package/templates/starter/src/app/layout.tsx +4 -4
- package/templates/starter/src/app/page.tsx +41 -33
- package/templates/starter/src/components/FeatureCard.tsx +5 -5
- package/templates/starter/src/components/Footer.tsx +6 -6
- package/templates/starter/src/components/Header.tsx +18 -14
- package/templates/starter/src/components/TerminalPreview.tsx +30 -30
- package/templates/starter/src/styles.css +14 -5
package/package.json
CHANGED
|
@@ -3,29 +3,34 @@ import { DashboardNav } from '../../components/DashboardNav.js';
|
|
|
3
3
|
|
|
4
4
|
export default function DashboardLayout({ children }: { children: ComponentChildren }) {
|
|
5
5
|
return (
|
|
6
|
-
<div class="min-h-screen flex bg-[#
|
|
6
|
+
<div class="min-h-screen flex bg-[#08090a] text-zinc-100 selection:bg-indigo-500/20 selection:text-indigo-300">
|
|
7
7
|
<DashboardNav />
|
|
8
8
|
<div class="flex-1 flex flex-col min-w-0">
|
|
9
|
-
<header class="h-
|
|
9
|
+
<header class="h-14 border-b border-white/[0.08] px-6 flex items-center justify-between bg-[#08090a]/80 backdrop-blur-md sticky top-0 z-40">
|
|
10
10
|
<div class="flex items-center gap-3">
|
|
11
|
-
<
|
|
12
|
-
<span class="
|
|
13
|
-
|
|
11
|
+
<span class="text-xs text-zinc-500">Workspace</span>
|
|
12
|
+
<span class="text-zinc-600 text-xs">/</span>
|
|
13
|
+
<h1 class="text-xs font-semibold text-zinc-200">Production Cluster</h1>
|
|
14
|
+
<span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 text-[10px] font-medium border border-emerald-500/20 ml-1">
|
|
15
|
+
<span class="w-1.5 h-1.5 rounded-full bg-emerald-400" />
|
|
16
|
+
99.99% Uptime
|
|
14
17
|
</span>
|
|
15
18
|
</div>
|
|
16
19
|
|
|
17
|
-
<div class="flex items-center gap-
|
|
18
|
-
<span class="text-slate-400">User: <strong class="text-white">admin@frootkit.dev</strong></span>
|
|
20
|
+
<div class="flex items-center gap-3 text-xs">
|
|
19
21
|
<a
|
|
20
22
|
href="/api/auth"
|
|
21
|
-
class="px-2.5 py-1 rounded bg-[
|
|
23
|
+
class="px-2.5 py-1 rounded-md bg-white/[0.04] border border-white/[0.08] text-zinc-400 hover:text-zinc-200 transition-colors font-mono text-[11px]"
|
|
22
24
|
>
|
|
23
25
|
/api/auth
|
|
24
26
|
</a>
|
|
27
|
+
<div class="hidden sm:flex items-center gap-1 text-[11px] text-zinc-500 border border-white/[0.06] bg-white/[0.02] px-2 py-0.5 rounded">
|
|
28
|
+
<span>⌘</span><span>K</span>
|
|
29
|
+
</div>
|
|
25
30
|
</div>
|
|
26
31
|
</header>
|
|
27
32
|
|
|
28
|
-
<div class="p-8 flex-1 overflow-y-auto">
|
|
33
|
+
<div class="p-6 sm:p-8 flex-1 overflow-y-auto">
|
|
29
34
|
{children}
|
|
30
35
|
</div>
|
|
31
36
|
</div>
|
|
@@ -13,20 +13,30 @@ export default function DashboardOverviewPage() {
|
|
|
13
13
|
];
|
|
14
14
|
|
|
15
15
|
const recentUsers = [
|
|
16
|
-
{ name: 'Sarah Connor', email: 'sarah@frootkit.dev', role: 'Owner', date: 'Just now' },
|
|
17
|
-
{ name: 'Marcus Chen', email: 'marcus@infra.org', role: 'Developer', date: '2 hours ago' },
|
|
18
|
-
{ name: 'Elena Rostova', email: 'elena@design.io', role: 'Staff Eng', date: '1 day ago' },
|
|
19
|
-
{ name: 'Alex Rivera', email: 'alex@systems.net', role: 'Admin', date: '3 days ago' },
|
|
16
|
+
{ name: 'Sarah Connor', email: 'sarah@frootkit.dev', role: 'Owner', date: 'Just now', status: 'online' },
|
|
17
|
+
{ name: 'Marcus Chen', email: 'marcus@infra.org', role: 'Developer', date: '2 hours ago', status: 'offline' },
|
|
18
|
+
{ name: 'Elena Rostova', email: 'elena@design.io', role: 'Staff Eng', date: '1 day ago', status: 'offline' },
|
|
19
|
+
{ name: 'Alex Rivera', email: 'alex@systems.net', role: 'Admin', date: '3 days ago', status: 'offline' },
|
|
20
20
|
];
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
|
-
<div class="space-y-8">
|
|
24
|
-
<div>
|
|
25
|
-
<
|
|
26
|
-
|
|
23
|
+
<div class="space-y-8 max-w-6xl">
|
|
24
|
+
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
|
25
|
+
<div>
|
|
26
|
+
<h2 class="text-xl sm:text-2xl font-semibold text-white tracking-tight">Metrics & Telemetry</h2>
|
|
27
|
+
<p class="text-xs sm:text-sm text-zinc-400 mt-1">Real-time throughput and workspace subscriber analytics.</p>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="flex items-center gap-2">
|
|
30
|
+
<button class="px-3 py-1.5 rounded-lg bg-white/[0.04] border border-white/[0.08] text-xs font-medium text-zinc-300 hover:text-white hover:bg-white/[0.08] transition-colors flex items-center gap-1.5">
|
|
31
|
+
<svg style="width: 12px; height: 12px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
32
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
|
33
|
+
</svg>
|
|
34
|
+
<span>Refresh</span>
|
|
35
|
+
</button>
|
|
36
|
+
</div>
|
|
27
37
|
</div>
|
|
28
38
|
|
|
29
|
-
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-
|
|
39
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
30
40
|
{metrics.map((m) => (
|
|
31
41
|
<MetricCard
|
|
32
42
|
key={m.label}
|
|
@@ -38,29 +48,50 @@ export default function DashboardOverviewPage() {
|
|
|
38
48
|
))}
|
|
39
49
|
</div>
|
|
40
50
|
|
|
41
|
-
<div class="rounded-xl border border-[
|
|
42
|
-
<
|
|
51
|
+
<div class="rounded-xl border border-white/[0.08] bg-[#0f1117] shadow-[inset_0_1px_0_0_rgba(255,255,255,0.05)] overflow-hidden">
|
|
52
|
+
<div class="p-5 border-b border-white/[0.06] flex items-center justify-between">
|
|
53
|
+
<div>
|
|
54
|
+
<h3 class="text-sm font-semibold text-white">Recent Workspace Activity</h3>
|
|
55
|
+
<p class="text-xs text-zinc-500 mt-0.5">Active team member sessions and authentication audits</p>
|
|
56
|
+
</div>
|
|
57
|
+
<span class="text-xs text-zinc-400 bg-white/[0.04] px-2.5 py-1 rounded-md border border-white/[0.06]">
|
|
58
|
+
{recentUsers.length} active sessions
|
|
59
|
+
</span>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
43
62
|
<div class="overflow-x-auto">
|
|
44
|
-
<table class="w-full text-left text-
|
|
63
|
+
<table class="w-full text-left text-xs">
|
|
45
64
|
<thead>
|
|
46
|
-
<tr class="border-b border-[
|
|
47
|
-
<th class="
|
|
48
|
-
<th class="
|
|
49
|
-
<th class="
|
|
50
|
-
<th class="
|
|
65
|
+
<tr class="border-b border-white/[0.06] text-zinc-400 font-medium bg-white/[0.01]">
|
|
66
|
+
<th class="py-3 px-5 font-medium">User</th>
|
|
67
|
+
<th class="py-3 px-5 font-medium">Email</th>
|
|
68
|
+
<th class="py-3 px-5 font-medium">Role</th>
|
|
69
|
+
<th class="py-3 px-5 font-medium text-right">Last Active</th>
|
|
51
70
|
</tr>
|
|
52
71
|
</thead>
|
|
53
|
-
<tbody class="divide-y divide-[
|
|
72
|
+
<tbody class="divide-y divide-white/[0.04]">
|
|
54
73
|
{recentUsers.map((u) => (
|
|
55
|
-
<tr key={u.email} class="hover:bg-[
|
|
56
|
-
<td class="py-3.5
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
74
|
+
<tr key={u.email} class="hover:bg-white/[0.02] transition-colors group">
|
|
75
|
+
<td class="py-3.5 px-5">
|
|
76
|
+
<div class="flex items-center gap-2.5">
|
|
77
|
+
<div class="w-6 h-6 rounded-full bg-white/[0.06] border border-white/[0.08] flex items-center justify-center text-[10px] font-medium text-zinc-300">
|
|
78
|
+
{u.name.charAt(0)}
|
|
79
|
+
</div>
|
|
80
|
+
<span class="font-medium text-zinc-200 group-hover:text-white transition-colors">{u.name}</span>
|
|
81
|
+
</div>
|
|
82
|
+
</td>
|
|
83
|
+
<td class="py-3.5 px-5 text-zinc-400">{u.email}</td>
|
|
84
|
+
<td class="py-3.5 px-5">
|
|
85
|
+
<span class={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md text-[11px] font-medium border ${
|
|
86
|
+
u.role === 'Owner'
|
|
87
|
+
? 'bg-indigo-500/10 text-indigo-400 border-indigo-500/20'
|
|
88
|
+
: 'bg-white/[0.04] text-zinc-300 border-white/[0.08]'
|
|
89
|
+
}`}>
|
|
90
|
+
{u.role === 'Owner' && <span class="w-1.5 h-1.5 rounded-full bg-indigo-400" />}
|
|
60
91
|
{u.role}
|
|
61
92
|
</span>
|
|
62
93
|
</td>
|
|
63
|
-
<td class="py-3.5 text-
|
|
94
|
+
<td class="py-3.5 px-5 text-zinc-500 text-right tabular-nums">{u.date}</td>
|
|
64
95
|
</tr>
|
|
65
96
|
))}
|
|
66
97
|
</tbody>
|
|
@@ -9,7 +9,7 @@ export interface RootLayoutProps {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export default function RootLayout({ children, metadata }: RootLayoutProps) {
|
|
12
|
-
const title = metadata?.title || '
|
|
12
|
+
const title = metadata?.title || 'FrootAuth — Modern Cloud Platform';
|
|
13
13
|
const description =
|
|
14
14
|
metadata?.description ||
|
|
15
15
|
'Fullstack SaaS application with authentication and real-time dashboard powered by Preact and FrootKit.';
|
|
@@ -24,12 +24,12 @@ export default function RootLayout({ children, metadata }: RootLayoutProps) {
|
|
|
24
24
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
25
25
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
26
26
|
<link
|
|
27
|
-
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700
|
|
27
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
|
|
28
28
|
rel="stylesheet"
|
|
29
29
|
/>
|
|
30
30
|
<link rel="stylesheet" href="/styles.css" />
|
|
31
31
|
</head>
|
|
32
|
-
<body class="bg-[#
|
|
32
|
+
<body class="bg-[#08090a] text-zinc-100 min-h-screen antialiased selection:bg-indigo-500/20 selection:text-indigo-300 font-sans">
|
|
33
33
|
{children}
|
|
34
34
|
</body>
|
|
35
35
|
</html>
|
|
@@ -7,12 +7,16 @@ export const metadata = {
|
|
|
7
7
|
|
|
8
8
|
export default function LoginPage() {
|
|
9
9
|
return (
|
|
10
|
-
<div class="min-h-screen bg-[#
|
|
10
|
+
<div class="min-h-screen bg-[#08090a] text-zinc-100 flex flex-col justify-between selection:bg-indigo-500/20 selection:text-indigo-300">
|
|
11
11
|
<Navbar />
|
|
12
12
|
|
|
13
13
|
<main class="max-w-md mx-auto px-6 py-16 flex-1 w-full flex flex-col justify-center">
|
|
14
14
|
<AuthForm mode="login" />
|
|
15
15
|
</main>
|
|
16
|
+
|
|
17
|
+
<footer class="py-6 text-center text-xs text-zinc-600">
|
|
18
|
+
FrootAuth • Web Crypto PBKDF2 Authentication
|
|
19
|
+
</footer>
|
|
16
20
|
</div>
|
|
17
21
|
);
|
|
18
22
|
}
|
|
@@ -7,92 +7,150 @@ export const metadata = {
|
|
|
7
7
|
|
|
8
8
|
export default function SaaSMarketingPage() {
|
|
9
9
|
return (
|
|
10
|
-
<div class="min-h-screen bg-[#
|
|
10
|
+
<div class="min-h-screen bg-[#08090a] text-zinc-100 flex flex-col justify-between selection:bg-indigo-500/20 selection:text-indigo-300">
|
|
11
11
|
<Navbar />
|
|
12
12
|
|
|
13
|
-
<main class="max-w-6xl mx-auto px-6 py-16 flex-1 flex flex-col justify-center">
|
|
14
|
-
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 items-center">
|
|
13
|
+
<main class="max-w-6xl mx-auto px-6 py-16 sm:py-24 flex-1 flex flex-col justify-center w-full">
|
|
14
|
+
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16 items-center">
|
|
15
15
|
{/* Left Column (7 cols) */}
|
|
16
16
|
<div class="lg:col-span-7">
|
|
17
|
-
<div class="
|
|
18
|
-
|
|
17
|
+
<div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 text-xs font-medium mb-6">
|
|
18
|
+
<span class="w-1.5 h-1.5 rounded-full bg-indigo-400 animate-pulse" />
|
|
19
|
+
<span>Pure Web Crypto Architecture</span>
|
|
19
20
|
</div>
|
|
20
21
|
|
|
21
|
-
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-
|
|
22
|
+
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-semibold text-white tracking-[-0.03em] leading-[1.1] mb-6">
|
|
22
23
|
Fullstack Authentication & Administration.
|
|
23
24
|
</h1>
|
|
24
25
|
|
|
25
|
-
<p class="text-base sm:text-lg text-
|
|
26
|
-
Zero external C++ dependencies. Real PBKDF2 password hashing (100,000 iterations), cryptographically random session tokens, protected
|
|
26
|
+
<p class="text-base sm:text-lg text-zinc-400 leading-relaxed mb-8 max-w-xl">
|
|
27
|
+
Zero external C++ dependencies. Real PBKDF2 password hashing (100,000 iterations), cryptographically random session tokens, protected layouts, and high-density telemetry.
|
|
27
28
|
</p>
|
|
28
29
|
|
|
29
|
-
<div class="flex flex-wrap items-center gap-
|
|
30
|
+
<div class="flex flex-wrap items-center gap-3.5 mb-8">
|
|
30
31
|
<a
|
|
31
32
|
href="/signup"
|
|
32
|
-
class="px-
|
|
33
|
+
class="px-4 py-2.5 rounded-lg bg-white text-zinc-950 font-medium hover:bg-zinc-200 transition-all text-sm shadow-sm flex items-center gap-2 group"
|
|
33
34
|
>
|
|
34
35
|
<span>Create Account</span>
|
|
35
|
-
<span>→</span>
|
|
36
|
+
<span class="text-zinc-500 group-hover:translate-x-0.5 transition-transform">→</span>
|
|
36
37
|
</a>
|
|
37
38
|
<a
|
|
38
39
|
href="/dashboard"
|
|
39
|
-
class="px-
|
|
40
|
+
class="px-4 py-2.5 rounded-lg bg-white/[0.04] border border-white/[0.08] text-zinc-300 font-medium hover:bg-white/[0.08] hover:text-white transition-all text-sm"
|
|
40
41
|
>
|
|
41
|
-
|
|
42
|
+
Open Dashboard
|
|
42
43
|
</a>
|
|
43
44
|
</div>
|
|
44
45
|
|
|
45
|
-
<div class="
|
|
46
|
-
<span class="
|
|
47
|
-
<span>Demo Account ready
|
|
46
|
+
<div class="inline-flex items-center gap-2.5 px-3 py-1.5 rounded-md bg-white/[0.03] border border-white/[0.06] text-xs text-zinc-400">
|
|
47
|
+
<span class="w-2 h-2 rounded-full bg-emerald-400" />
|
|
48
|
+
<span>Demo Account ready:</span>
|
|
49
|
+
<code class="text-zinc-200 font-mono text-[11px] bg-white/[0.04] px-1.5 py-0.5 rounded">admin@frootkit.dev</code>
|
|
50
|
+
<span class="text-zinc-600">/</span>
|
|
51
|
+
<code class="text-zinc-200 font-mono text-[11px] bg-white/[0.04] px-1.5 py-0.5 rounded">password123</code>
|
|
48
52
|
</div>
|
|
49
53
|
</div>
|
|
50
54
|
|
|
51
|
-
{/* Right Column:
|
|
55
|
+
{/* Right Column: Linear-Grade Security Inspector Card (5 cols) */}
|
|
52
56
|
<div class="lg:col-span-5">
|
|
53
|
-
<div class="rounded-xl border border-[
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
<div class="rounded-xl border border-white/[0.08] bg-[#0f1117] p-6 shadow-2xl shadow-black/40 relative overflow-hidden">
|
|
58
|
+
{/* Subtle top edge highlight */}
|
|
59
|
+
<div class="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-indigo-500/40 to-transparent" />
|
|
60
|
+
|
|
61
|
+
<div class="flex items-center justify-between pb-4 border-b border-white/[0.06] mb-5">
|
|
62
|
+
<div class="flex items-center gap-2">
|
|
63
|
+
<div class="w-2 h-2 rounded-full bg-emerald-400" />
|
|
64
|
+
<span class="text-xs font-medium text-zinc-300">Security Subsystem</span>
|
|
65
|
+
</div>
|
|
66
|
+
<span class="text-[11px] text-indigo-400 font-medium px-2 py-0.5 rounded-full bg-indigo-500/10 border border-indigo-500/20">
|
|
67
|
+
SubtleCrypto Active
|
|
58
68
|
</span>
|
|
59
69
|
</div>
|
|
60
70
|
|
|
61
|
-
<div class="space-y-3
|
|
62
|
-
<div class="flex justify-between">
|
|
63
|
-
<span class="text-
|
|
64
|
-
<span class="text-
|
|
71
|
+
<div class="space-y-3.5 text-xs">
|
|
72
|
+
<div class="flex justify-between items-center py-1">
|
|
73
|
+
<span class="text-zinc-400">Algorithm</span>
|
|
74
|
+
<span class="text-zinc-200 font-medium">PBKDF2-SHA256</span>
|
|
65
75
|
</div>
|
|
66
|
-
<div class="flex justify-between">
|
|
67
|
-
<span class="text-
|
|
68
|
-
<span class="text-
|
|
76
|
+
<div class="flex justify-between items-center py-1 border-t border-white/[0.04]">
|
|
77
|
+
<span class="text-zinc-400">Iterations</span>
|
|
78
|
+
<span class="text-zinc-200 font-medium tabular-nums">100,000 rounds</span>
|
|
69
79
|
</div>
|
|
70
|
-
<div class="flex justify-between">
|
|
71
|
-
<span class="text-
|
|
72
|
-
<span class="text-
|
|
80
|
+
<div class="flex justify-between items-center py-1 border-t border-white/[0.04]">
|
|
81
|
+
<span class="text-zinc-400">Salt Length</span>
|
|
82
|
+
<span class="text-zinc-200 font-medium tabular-nums">128-bit (16 bytes)</span>
|
|
73
83
|
</div>
|
|
74
|
-
<div class="flex justify-between">
|
|
75
|
-
<span class="text-
|
|
76
|
-
<span class="text-
|
|
84
|
+
<div class="flex justify-between items-center py-1 border-t border-white/[0.04]">
|
|
85
|
+
<span class="text-zinc-400">Key Derivation</span>
|
|
86
|
+
<span class="text-zinc-200 font-medium">256-bit SubtleCrypto</span>
|
|
87
|
+
</div>
|
|
88
|
+
<div class="flex justify-between items-center py-1 border-t border-white/[0.04]">
|
|
89
|
+
<span class="text-zinc-400">Cookie Security</span>
|
|
90
|
+
<span class="text-emerald-400 font-medium">HttpOnly; SameSite=Lax</span>
|
|
77
91
|
</div>
|
|
78
92
|
</div>
|
|
79
93
|
|
|
80
|
-
<div class="pt-
|
|
81
|
-
<span class="text-
|
|
82
|
-
<code class="text-
|
|
94
|
+
<div class="mt-5 pt-4 border-t border-white/[0.06] flex justify-between items-center text-xs">
|
|
95
|
+
<span class="text-zinc-500">Auth Route</span>
|
|
96
|
+
<code class="text-indigo-400 font-mono text-[11px] bg-indigo-500/5 px-2 py-0.5 rounded border border-indigo-500/15">
|
|
97
|
+
/api/auth?action=login
|
|
98
|
+
</code>
|
|
83
99
|
</div>
|
|
84
100
|
</div>
|
|
85
101
|
</div>
|
|
86
102
|
</div>
|
|
103
|
+
|
|
104
|
+
{/* Feature Grid Below */}
|
|
105
|
+
<div class="mt-20 pt-12 border-t border-white/[0.06] grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
106
|
+
<div class="p-5 rounded-lg border border-white/[0.06] bg-white/[0.02]">
|
|
107
|
+
<div class="w-8 h-8 rounded-md bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-400 mb-3">
|
|
108
|
+
<svg style="width: 16px; height: 16px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
109
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
110
|
+
</svg>
|
|
111
|
+
</div>
|
|
112
|
+
<h3 class="text-sm font-semibold text-zinc-100 mb-1">Standard Web Crypto</h3>
|
|
113
|
+
<p class="text-xs text-zinc-400 leading-relaxed">
|
|
114
|
+
Native PBKDF2 key derivation using the Web Cryptography API. Zero C++ native rebuilds across any architecture.
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div class="p-5 rounded-lg border border-white/[0.06] bg-white/[0.02]">
|
|
119
|
+
<div class="w-8 h-8 rounded-md bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-400 mb-3">
|
|
120
|
+
<svg style="width: 16px; height: 16px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
121
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
|
|
122
|
+
<line x1="9" y1="3" x2="9" y2="21" />
|
|
123
|
+
</svg>
|
|
124
|
+
</div>
|
|
125
|
+
<h3 class="text-sm font-semibold text-zinc-100 mb-1">Protected Layouts</h3>
|
|
126
|
+
<p class="text-xs text-zinc-400 leading-relaxed">
|
|
127
|
+
Deterministic server-side session checks in nested Preact layout trees with instant redirect fallbacks.
|
|
128
|
+
</p>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<div class="p-5 rounded-lg border border-white/[0.06] bg-white/[0.02]">
|
|
132
|
+
<div class="w-8 h-8 rounded-md bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-400 mb-3">
|
|
133
|
+
<svg style="width: 16px; height: 16px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
134
|
+
<line x1="18" y1="20" x2="18" y2="10" />
|
|
135
|
+
<line x1="12" y1="20" x2="12" y2="4" />
|
|
136
|
+
<line x1="6" y1="20" x2="6" y2="14" />
|
|
137
|
+
</svg>
|
|
138
|
+
</div>
|
|
139
|
+
<h3 class="text-sm font-semibold text-zinc-100 mb-1">SQLite Session Cache</h3>
|
|
140
|
+
<p class="text-xs text-zinc-400 leading-relaxed">
|
|
141
|
+
Local persistent storage with sub-millisecond lookup latency, automatic expiry purging, and single-file portability.
|
|
142
|
+
</p>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
87
145
|
</main>
|
|
88
146
|
|
|
89
|
-
<footer class="border-t border-[
|
|
90
|
-
<div class="max-w-6xl mx-auto px-6 flex justify-between">
|
|
91
|
-
<div>FrootAuth © {new Date().getFullYear()} OrbitNorth LLC
|
|
92
|
-
<div class="flex gap-
|
|
93
|
-
<a href="/login" class="hover:text-
|
|
94
|
-
<a href="/signup" class="hover:text-
|
|
95
|
-
<a href="/dashboard" class="hover:text-
|
|
147
|
+
<footer class="border-t border-white/[0.06] bg-[#08090a] py-6 text-xs text-zinc-500">
|
|
148
|
+
<div class="max-w-6xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
|
|
149
|
+
<div>FrootAuth © {new Date().getFullYear()} OrbitNorth LLC. Built with FrootKit.</div>
|
|
150
|
+
<div class="flex gap-5">
|
|
151
|
+
<a href="/login" class="hover:text-zinc-300 transition-colors">Sign In</a>
|
|
152
|
+
<a href="/signup" class="hover:text-zinc-300 transition-colors">Sign Up</a>
|
|
153
|
+
<a href="/dashboard" class="hover:text-zinc-300 transition-colors">Dashboard</a>
|
|
96
154
|
</div>
|
|
97
155
|
</div>
|
|
98
156
|
</footer>
|
|
@@ -7,12 +7,16 @@ export const metadata = {
|
|
|
7
7
|
|
|
8
8
|
export default function SignupPage() {
|
|
9
9
|
return (
|
|
10
|
-
<div class="min-h-screen bg-[#
|
|
10
|
+
<div class="min-h-screen bg-[#08090a] text-zinc-100 flex flex-col justify-between selection:bg-indigo-500/20 selection:text-indigo-300">
|
|
11
11
|
<Navbar />
|
|
12
12
|
|
|
13
13
|
<main class="max-w-md mx-auto px-6 py-16 flex-1 w-full flex flex-col justify-center">
|
|
14
14
|
<AuthForm mode="signup" />
|
|
15
15
|
</main>
|
|
16
|
+
|
|
17
|
+
<footer class="py-6 text-center text-xs text-zinc-600">
|
|
18
|
+
FrootAuth • Web Crypto PBKDF2 Authentication
|
|
19
|
+
</footer>
|
|
16
20
|
</div>
|
|
17
21
|
);
|
|
18
22
|
}
|
|
@@ -6,24 +6,32 @@ export function AuthForm({ mode }: AuthFormProps) {
|
|
|
6
6
|
const isLogin = mode === 'login';
|
|
7
7
|
|
|
8
8
|
return (
|
|
9
|
-
<div class="rounded-xl border border-[
|
|
9
|
+
<div class="rounded-xl border border-white/[0.08] bg-[#0f1117] p-7 sm:p-8 shadow-2xl shadow-black/50 relative overflow-hidden">
|
|
10
|
+
{/* Top ambient highlight */}
|
|
11
|
+
<div class="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-indigo-500/40 to-transparent" />
|
|
12
|
+
|
|
10
13
|
<div class="mb-6">
|
|
11
|
-
<h1 class="text-
|
|
12
|
-
{isLogin ? 'Sign in to workspace' : 'Create
|
|
14
|
+
<h1 class="text-xl font-semibold text-white tracking-tight mb-1">
|
|
15
|
+
{isLogin ? 'Sign in to workspace' : 'Create your account'}
|
|
13
16
|
</h1>
|
|
14
|
-
<p class="text-
|
|
17
|
+
<p class="text-zinc-400 text-xs">
|
|
15
18
|
{isLogin ? 'Need an account? ' : 'Already registered? '}
|
|
16
|
-
<a href={isLogin ? '/signup' : '/login'} class="text-
|
|
19
|
+
<a href={isLogin ? '/signup' : '/login'} class="text-indigo-400 font-medium hover:text-indigo-300 transition-colors">
|
|
17
20
|
{isLogin ? 'Sign up' : 'Sign in'}
|
|
18
21
|
</a>
|
|
19
22
|
</p>
|
|
20
23
|
</div>
|
|
21
24
|
|
|
22
25
|
{isLogin && (
|
|
23
|
-
<div class="mb-
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
<div class="mb-5 p-3 rounded-lg bg-white/[0.02] border border-white/[0.06] text-xs">
|
|
27
|
+
<div class="flex items-center gap-1.5 text-zinc-400 text-[11px] mb-1">
|
|
28
|
+
<span class="w-1.5 h-1.5 rounded-full bg-emerald-400" />
|
|
29
|
+
<span class="font-medium text-zinc-300">Quick Demo Credentials:</span>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="font-mono text-zinc-300 text-[11px] bg-white/[0.03] px-2 py-1 rounded flex items-center justify-between">
|
|
32
|
+
<span>admin@frootkit.dev</span>
|
|
33
|
+
<span class="text-zinc-600">•</span>
|
|
34
|
+
<span>password123</span>
|
|
27
35
|
</div>
|
|
28
36
|
</div>
|
|
29
37
|
)}
|
|
@@ -31,7 +39,7 @@ export function AuthForm({ mode }: AuthFormProps) {
|
|
|
31
39
|
<form action={`/api/auth?action=${mode}`} method="POST" class="space-y-4">
|
|
32
40
|
{!isLogin && (
|
|
33
41
|
<div>
|
|
34
|
-
<label class="block text-xs font-medium text-
|
|
42
|
+
<label class="block text-xs font-medium text-zinc-300 mb-1.5" for="name">
|
|
35
43
|
Full Name
|
|
36
44
|
</label>
|
|
37
45
|
<input
|
|
@@ -40,13 +48,13 @@ export function AuthForm({ mode }: AuthFormProps) {
|
|
|
40
48
|
name="name"
|
|
41
49
|
placeholder="Developer Name"
|
|
42
50
|
required
|
|
43
|
-
class="w-full px-3
|
|
51
|
+
class="w-full px-3 py-2 rounded-lg bg-[#08090a] border border-white/[0.08] text-white text-xs placeholder:text-zinc-600 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 transition-colors"
|
|
44
52
|
/>
|
|
45
53
|
</div>
|
|
46
54
|
)}
|
|
47
55
|
|
|
48
56
|
<div>
|
|
49
|
-
<label class="block text-xs font-medium text-
|
|
57
|
+
<label class="block text-xs font-medium text-zinc-300 mb-1.5" for="email">
|
|
50
58
|
Email Address
|
|
51
59
|
</label>
|
|
52
60
|
<input
|
|
@@ -56,14 +64,21 @@ export function AuthForm({ mode }: AuthFormProps) {
|
|
|
56
64
|
placeholder="admin@frootkit.dev"
|
|
57
65
|
defaultValue={isLogin ? 'admin@frootkit.dev' : ''}
|
|
58
66
|
required
|
|
59
|
-
class="w-full px-3
|
|
67
|
+
class="w-full px-3 py-2 rounded-lg bg-[#08090a] border border-white/[0.08] text-white text-xs placeholder:text-zinc-600 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 transition-colors"
|
|
60
68
|
/>
|
|
61
69
|
</div>
|
|
62
70
|
|
|
63
71
|
<div>
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
<div class="flex items-center justify-between mb-1.5">
|
|
73
|
+
<label class="block text-xs font-medium text-zinc-300" for="password">
|
|
74
|
+
Password
|
|
75
|
+
</label>
|
|
76
|
+
{isLogin && (
|
|
77
|
+
<span class="text-[11px] text-zinc-500">
|
|
78
|
+
min 8 characters
|
|
79
|
+
</span>
|
|
80
|
+
)}
|
|
81
|
+
</div>
|
|
67
82
|
<input
|
|
68
83
|
id="password"
|
|
69
84
|
type="password"
|
|
@@ -71,16 +86,16 @@ export function AuthForm({ mode }: AuthFormProps) {
|
|
|
71
86
|
placeholder="••••••••••••"
|
|
72
87
|
defaultValue={isLogin ? 'password123' : ''}
|
|
73
88
|
required
|
|
74
|
-
class="w-full px-3
|
|
89
|
+
class="w-full px-3 py-2 rounded-lg bg-[#08090a] border border-white/[0.08] text-white text-xs placeholder:text-zinc-600 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 transition-colors"
|
|
75
90
|
/>
|
|
76
91
|
</div>
|
|
77
92
|
|
|
78
93
|
<button
|
|
79
94
|
type="submit"
|
|
80
|
-
class="w-full py-2.5 rounded-lg bg-
|
|
95
|
+
class="w-full py-2.5 rounded-lg bg-white text-zinc-950 font-medium text-xs hover:bg-zinc-200 transition-all mt-3 flex items-center justify-center gap-2 group shadow-sm"
|
|
81
96
|
>
|
|
82
97
|
<span>{isLogin ? 'Sign In' : 'Create Account'}</span>
|
|
83
|
-
<span>→</span>
|
|
98
|
+
<span class="text-zinc-500 group-hover:translate-x-0.5 transition-transform">→</span>
|
|
84
99
|
</button>
|
|
85
100
|
</form>
|
|
86
101
|
</div>
|