create-frootkit 1.2.1 → 1.2.3
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/dist/index.js +1 -1
- package/package.json +2 -2
- package/templates/auth/src/app/dashboard/layout.tsx +9 -9
- package/templates/auth/src/app/dashboard/page.tsx +16 -16
- package/templates/auth/src/app/login/page.tsx +2 -2
- package/templates/auth/src/app/page.tsx +77 -37
- package/templates/auth/src/app/signup/page.tsx +2 -2
- package/templates/auth/src/components/AuthForm.tsx +25 -17
- package/templates/auth/src/components/DashboardNav.tsx +53 -29
- package/templates/auth/src/components/MetricCard.tsx +4 -4
- package/templates/auth/src/components/Navbar.tsx +10 -8
- package/templates/auth/src/styles.css +19 -11
- package/templates/blog/src/app/blog/[slug]/page.tsx +9 -9
- package/templates/blog/src/app/page.tsx +26 -12
- package/templates/blog/src/components/Footer.tsx +5 -5
- package/templates/blog/src/components/Navbar.tsx +8 -6
- package/templates/blog/src/components/Newsletter.tsx +16 -10
- package/templates/blog/src/components/PostCard.tsx +60 -13
- package/templates/blog/src/styles.css +19 -11
- package/templates/ecommerce/src/app/cart/page.tsx +2 -2
- package/templates/ecommerce/src/app/page.tsx +20 -29
- package/templates/ecommerce/src/app/products/[id]/page.tsx +19 -18
- package/templates/ecommerce/src/components/CartDrawer.tsx +12 -12
- package/templates/ecommerce/src/components/Footer.tsx +5 -5
- package/templates/ecommerce/src/components/Navbar.tsx +13 -8
- package/templates/ecommerce/src/components/ProductCard.tsx +14 -13
- package/templates/ecommerce/src/styles.css +19 -11
- package/templates/empty/src/app/page.tsx +9 -9
- package/templates/empty/src/styles.css +19 -11
- package/templates/starter/src/app/page.tsx +75 -74
- package/templates/starter/src/components/FeatureCard.tsx +10 -6
- package/templates/starter/src/components/Footer.tsx +5 -5
- package/templates/starter/src/components/Header.tsx +5 -5
- package/templates/starter/src/components/TerminalPreview.tsx +28 -28
- package/templates/starter/src/styles.css +19 -11
- package/dist/templates/auth.d.ts +0 -3
- package/dist/templates/auth.d.ts.map +0 -1
- package/dist/templates/auth.js +0 -487
- package/dist/templates/auth.js.map +0 -1
- package/dist/templates/blog.d.ts +0 -3
- package/dist/templates/blog.d.ts.map +0 -1
- package/dist/templates/blog.js +0 -369
- package/dist/templates/blog.js.map +0 -1
- package/dist/templates/common.d.ts +0 -5
- package/dist/templates/common.d.ts.map +0 -1
- package/dist/templates/common.js +0 -116
- package/dist/templates/common.js.map +0 -1
- package/dist/templates/ecommerce.d.ts +0 -3
- package/dist/templates/ecommerce.d.ts.map +0 -1
- package/dist/templates/ecommerce.js +0 -474
- package/dist/templates/ecommerce.js.map +0 -1
- package/dist/templates/empty.d.ts +0 -3
- package/dist/templates/empty.d.ts.map +0 -1
- package/dist/templates/empty.js +0 -85
- package/dist/templates/empty.js.map +0 -1
- package/dist/templates/starter.d.ts +0 -3
- package/dist/templates/starter.d.ts.map +0 -1
- package/dist/templates/starter.js +0 -308
- package/dist/templates/starter.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { scaffoldProject } from './scaffold.js';
|
|
|
11
11
|
export * from './template.js';
|
|
12
12
|
export * from './scaffold.js';
|
|
13
13
|
export * from './ui.js';
|
|
14
|
-
const VERSION = '1.2.
|
|
14
|
+
const VERSION = '1.2.3';
|
|
15
15
|
function parseCliArgs(argv) {
|
|
16
16
|
const raw = argv.slice(2);
|
|
17
17
|
const args = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-frootkit",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Interactive CLI for scaffolding high-performance FrootKit (Next.js Alternative) applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"main": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "tsc",
|
|
13
|
+
"build": "node -e \"const fs=require('fs'); fs.rmSync('dist', {recursive:true, force:true});\" && tsc",
|
|
14
14
|
"test": "node --test tests/*.test.ts"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [
|
|
@@ -3,24 +3,24 @@ 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-[#06090f] text-slate-100">
|
|
7
7
|
<DashboardNav />
|
|
8
8
|
<div class="flex-1 flex flex-col min-w-0">
|
|
9
|
-
<header class="h-16 border-b border-
|
|
9
|
+
<header class="h-16 border-b border-[#1a2333] px-8 flex items-center justify-between bg-[#06090f]">
|
|
10
10
|
<div class="flex items-center gap-3">
|
|
11
|
-
<h1 class="text-sm font-bold text-white">Production
|
|
12
|
-
<span class="px-2 py-0.5 rounded
|
|
13
|
-
|
|
11
|
+
<h1 class="text-sm font-bold text-white">Cluster: US-East Production</h1>
|
|
12
|
+
<span class="px-2 py-0.5 rounded bg-emerald-500/10 text-emerald-400 text-[10px] font-mono border border-emerald-500/20 font-semibold">
|
|
13
|
+
Live • 99.99% Uptime
|
|
14
14
|
</span>
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
|
-
<div class="flex items-center gap-4 text-xs">
|
|
18
|
-
<span class="text-slate-400">
|
|
17
|
+
<div class="flex items-center gap-4 text-xs font-mono">
|
|
18
|
+
<span class="text-slate-400">User: <strong class="text-white">admin@frootkit.dev</strong></span>
|
|
19
19
|
<a
|
|
20
20
|
href="/api/auth"
|
|
21
|
-
class="px-2.5 py-1 rounded
|
|
21
|
+
class="px-2.5 py-1 rounded bg-[#0a0f18] border border-[#1a2333] text-slate-300 hover:text-emerald-400 transition-colors"
|
|
22
22
|
>
|
|
23
|
-
|
|
23
|
+
/api/auth
|
|
24
24
|
</a>
|
|
25
25
|
</div>
|
|
26
26
|
</header>
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { MetricCard } from '../../components/MetricCard.js';
|
|
2
2
|
|
|
3
3
|
export const metadata = {
|
|
4
|
-
title: 'Workspace Overview —
|
|
4
|
+
title: 'Workspace Overview — FrootAuth',
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
export default function DashboardOverviewPage() {
|
|
8
8
|
const metrics = [
|
|
9
9
|
{ label: 'Monthly Recurring Revenue', value: '$42,850', change: '+14.2%', isPositive: true },
|
|
10
10
|
{ label: 'Active Subscribers', value: '1,280', change: '+8.1%', isPositive: true },
|
|
11
|
-
{ label: 'API
|
|
12
|
-
{ label: '
|
|
11
|
+
{ label: 'API Invocations (24h)', value: '3.42M', change: '+22.4%', isPositive: true },
|
|
12
|
+
{ label: 'P99 Dispatch Latency', value: '0.42ms', change: '-12.0%', isPositive: true },
|
|
13
13
|
];
|
|
14
14
|
|
|
15
15
|
const recentUsers = [
|
|
16
16
|
{ name: 'Sarah Connor', email: 'sarah@frootkit.dev', role: 'Owner', date: 'Just now' },
|
|
17
|
-
{ name: '
|
|
18
|
-
{ name: '
|
|
19
|
-
{ name: '
|
|
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' },
|
|
20
20
|
];
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<div class="space-y-8">
|
|
24
24
|
<div>
|
|
25
|
-
<h2 class="text-2xl font-bold text-white mb-1">Metrics &
|
|
26
|
-
<p class="text-xs text-slate-400">Real-time
|
|
25
|
+
<h2 class="text-2xl font-bold text-white mb-1">Metrics & Telemetry</h2>
|
|
26
|
+
<p class="text-xs text-slate-400 font-mono">Real-time throughput and workspace subscriber analytics.</p>
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
29
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
@@ -38,25 +38,25 @@ export default function DashboardOverviewPage() {
|
|
|
38
38
|
))}
|
|
39
39
|
</div>
|
|
40
40
|
|
|
41
|
-
<div class="rounded-
|
|
41
|
+
<div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-6">
|
|
42
42
|
<h3 class="text-sm font-bold text-white mb-4">Recent Workspace Activity</h3>
|
|
43
43
|
<div class="overflow-x-auto">
|
|
44
|
-
<table class="w-full text-left text-xs">
|
|
44
|
+
<table class="w-full text-left text-xs font-mono">
|
|
45
45
|
<thead>
|
|
46
|
-
<tr class="border-b border-
|
|
46
|
+
<tr class="border-b border-[#1a2333] text-slate-400">
|
|
47
47
|
<th class="pb-3 font-semibold">User</th>
|
|
48
48
|
<th class="pb-3 font-semibold">Email</th>
|
|
49
49
|
<th class="pb-3 font-semibold">Role</th>
|
|
50
|
-
<th class="pb-3 font-semibold">
|
|
50
|
+
<th class="pb-3 font-semibold">Timestamp</th>
|
|
51
51
|
</tr>
|
|
52
52
|
</thead>
|
|
53
|
-
<tbody class="divide-y divide-
|
|
53
|
+
<tbody class="divide-y divide-[#1a2333]/70">
|
|
54
54
|
{recentUsers.map((u) => (
|
|
55
|
-
<tr key={u.email} class="hover:bg-
|
|
55
|
+
<tr key={u.email} class="hover:bg-[#0f1624]/40 transition-colors">
|
|
56
56
|
<td class="py-3 font-medium text-white">{u.name}</td>
|
|
57
|
-
<td class="py-3 text-slate-400
|
|
57
|
+
<td class="py-3 text-slate-400">{u.email}</td>
|
|
58
58
|
<td class="py-3">
|
|
59
|
-
<span class="px-2 py-0.5 rounded
|
|
59
|
+
<span class="px-2 py-0.5 rounded bg-[#0f1624] text-slate-300 border border-[#1a2333] text-[10px]">
|
|
60
60
|
{u.role}
|
|
61
61
|
</span>
|
|
62
62
|
</td>
|
|
@@ -2,12 +2,12 @@ import { Navbar } from '../../components/Navbar.js';
|
|
|
2
2
|
import { AuthForm } from '../../components/AuthForm.js';
|
|
3
3
|
|
|
4
4
|
export const metadata = {
|
|
5
|
-
title: 'Sign In —
|
|
5
|
+
title: 'Sign In — FrootAuth',
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
export default function LoginPage() {
|
|
9
9
|
return (
|
|
10
|
-
<div class="min-h-screen flex flex-col justify-between">
|
|
10
|
+
<div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
|
|
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">
|
|
@@ -1,57 +1,97 @@
|
|
|
1
1
|
import { Navbar } from '../components/Navbar.js';
|
|
2
2
|
|
|
3
3
|
export const metadata = {
|
|
4
|
-
title: '
|
|
5
|
-
description: '
|
|
4
|
+
title: 'FrootAuth — Web Crypto Authentication & Dashboard',
|
|
5
|
+
description: 'Pure Web Crypto PBKDF2 password hashing and secure session management for FrootKit.',
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
export default function SaaSMarketingPage() {
|
|
9
9
|
return (
|
|
10
|
-
<div class="min-h-screen flex flex-col justify-between">
|
|
10
|
+
<div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
|
|
11
11
|
<Navbar />
|
|
12
12
|
|
|
13
|
-
<main class="max-w-6xl mx-auto px-6 py-
|
|
14
|
-
<div class="
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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">
|
|
15
|
+
{/* Left Column (7 cols) */}
|
|
16
|
+
<div class="lg:col-span-7">
|
|
17
|
+
<div class="text-xs font-mono font-medium text-emerald-400 mb-3 uppercase tracking-wide">
|
|
18
|
+
Security Architecture • Pure Web Crypto
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
|
22
|
+
Fullstack Authentication & Administration.
|
|
23
|
+
</h1>
|
|
24
|
+
|
|
25
|
+
<p class="text-base sm:text-lg text-slate-300 leading-relaxed mb-8 max-w-xl">
|
|
26
|
+
Zero external C++ dependencies. Real PBKDF2 password hashing (100,000 iterations), cryptographically random session tokens, protected layout routes, and administrative dashboard metrics.
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<div class="flex flex-wrap items-center gap-4 mb-8">
|
|
30
|
+
<a
|
|
31
|
+
href="/signup"
|
|
32
|
+
class="px-5 py-2.5 rounded-lg bg-emerald-500 text-slate-950 font-semibold hover:bg-emerald-400 transition-colors text-sm"
|
|
33
|
+
>
|
|
34
|
+
Create Account →
|
|
35
|
+
</a>
|
|
36
|
+
<a
|
|
37
|
+
href="/dashboard"
|
|
38
|
+
class="px-5 py-2.5 rounded-lg bg-[#0a0f18] border border-[#1a2333] text-slate-200 font-semibold hover:border-slate-700 hover:text-white transition-colors text-sm"
|
|
39
|
+
>
|
|
40
|
+
View Dashboard
|
|
41
|
+
</a>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="text-xs font-mono text-slate-400 flex items-center gap-2">
|
|
45
|
+
<span class="text-emerald-400 font-bold">✓</span>
|
|
46
|
+
<span>Demo Account ready: admin@frootkit.dev / password123</span>
|
|
47
|
+
</div>
|
|
18
48
|
</div>
|
|
19
49
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
{/* Right Column: Mini Dashboard Card (5 cols) */}
|
|
51
|
+
<div class="lg:col-span-5">
|
|
52
|
+
<div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-6 shadow-xl space-y-4">
|
|
53
|
+
<div class="flex items-center justify-between pb-3 border-b border-[#1a2333]">
|
|
54
|
+
<span class="text-xs font-mono text-slate-400">Security Telemetry</span>
|
|
55
|
+
<span class="text-[10px] font-mono text-emerald-400 px-2 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20">
|
|
56
|
+
PBKDF2-SHA256
|
|
57
|
+
</span>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div class="space-y-3 font-mono text-xs">
|
|
61
|
+
<div class="flex justify-between">
|
|
62
|
+
<span class="text-slate-400">Iterations:</span>
|
|
63
|
+
<span class="text-white font-bold">100,000</span>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="flex justify-between">
|
|
66
|
+
<span class="text-slate-400">Salt Length:</span>
|
|
67
|
+
<span class="text-white font-bold">128-bit (16 bytes)</span>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="flex justify-between">
|
|
70
|
+
<span class="text-slate-400">Key Derivation:</span>
|
|
71
|
+
<span class="text-white font-bold">256-bit SubtleCrypto</span>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="flex justify-between">
|
|
74
|
+
<span class="text-slate-400">Cookie Security:</span>
|
|
75
|
+
<span class="text-emerald-400 font-bold">HttpOnly; SameSite=Lax</span>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="pt-3 border-t border-[#1a2333] flex justify-between items-center text-xs">
|
|
80
|
+
<span class="text-slate-400">Endpoint:</span>
|
|
81
|
+
<code class="text-emerald-400 font-mono">/api/auth?action=login</code>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
44
84
|
</div>
|
|
45
85
|
</div>
|
|
46
86
|
</main>
|
|
47
87
|
|
|
48
|
-
<footer class="border-t border-
|
|
88
|
+
<footer class="border-t border-[#1a2333] bg-[#06090f] py-8 text-xs text-slate-400 font-mono">
|
|
49
89
|
<div class="max-w-6xl mx-auto px-6 flex justify-between">
|
|
50
|
-
<div>
|
|
90
|
+
<div>FrootAuth © {new Date().getFullYear()} OrbitNorth LLC</div>
|
|
51
91
|
<div class="flex gap-4">
|
|
52
|
-
<a href="/login" class="hover:text-
|
|
53
|
-
<a href="/signup" class="hover:text-
|
|
54
|
-
<a href="/dashboard" class="hover:text-
|
|
92
|
+
<a href="/login" class="hover:text-white transition-colors">Sign In</a>
|
|
93
|
+
<a href="/signup" class="hover:text-white transition-colors">Sign Up</a>
|
|
94
|
+
<a href="/dashboard" class="hover:text-white transition-colors">Dashboard</a>
|
|
55
95
|
</div>
|
|
56
96
|
</div>
|
|
57
97
|
</footer>
|
|
@@ -2,12 +2,12 @@ import { Navbar } from '../../components/Navbar.js';
|
|
|
2
2
|
import { AuthForm } from '../../components/AuthForm.js';
|
|
3
3
|
|
|
4
4
|
export const metadata = {
|
|
5
|
-
title: 'Create Account —
|
|
5
|
+
title: 'Create Account — FrootAuth',
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
export default function SignupPage() {
|
|
9
9
|
return (
|
|
10
|
-
<div class="min-h-screen flex flex-col justify-between">
|
|
10
|
+
<div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
|
|
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">
|
|
@@ -6,13 +6,13 @@ export function AuthForm({ mode }: AuthFormProps) {
|
|
|
6
6
|
const isLogin = mode === 'login';
|
|
7
7
|
|
|
8
8
|
return (
|
|
9
|
-
<div class="rounded-
|
|
10
|
-
<div class="
|
|
11
|
-
<h1 class="text-2xl font-bold text-white mb-
|
|
12
|
-
{isLogin ? 'Sign in to
|
|
9
|
+
<div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-8 shadow-xl">
|
|
10
|
+
<div class="mb-6">
|
|
11
|
+
<h1 class="text-2xl font-bold text-white mb-1.5">
|
|
12
|
+
{isLogin ? 'Sign in to workspace' : 'Create workspace account'}
|
|
13
13
|
</h1>
|
|
14
14
|
<p class="text-slate-400 text-xs">
|
|
15
|
-
{isLogin ? "
|
|
15
|
+
{isLogin ? "Need an account? " : 'Already registered? '}
|
|
16
16
|
<a href={isLogin ? '/signup' : '/login'} class="text-emerald-400 font-semibold hover:underline">
|
|
17
17
|
{isLogin ? 'Sign up' : 'Sign in'}
|
|
18
18
|
</a>
|
|
@@ -20,54 +20,62 @@ export function AuthForm({ mode }: AuthFormProps) {
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
22
|
{isLogin && (
|
|
23
|
-
<div class="mb-6 p-3 rounded-
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
</div>
|
|
23
|
+
<div class="mb-6 p-3 rounded-lg bg-[#06090f] border border-[#1a2333] text-xs text-slate-300 font-mono">
|
|
24
|
+
<span class="text-emerald-400 font-bold block mb-0.5">Demo Credentials:</span>
|
|
25
|
+
<span>admin@frootkit.dev • password123</span>
|
|
27
26
|
</div>
|
|
28
27
|
)}
|
|
29
28
|
|
|
30
29
|
<form action={`/api/auth?action=${mode}`} method="POST" class="space-y-4">
|
|
31
30
|
{!isLogin && (
|
|
32
31
|
<div>
|
|
33
|
-
<label class="block text-xs font-medium text-slate-300 mb-1.5"
|
|
32
|
+
<label class="block text-xs font-mono font-medium text-slate-300 mb-1.5" for="name">
|
|
33
|
+
Full Name
|
|
34
|
+
</label>
|
|
34
35
|
<input
|
|
36
|
+
id="name"
|
|
35
37
|
type="text"
|
|
36
38
|
name="name"
|
|
37
|
-
placeholder="
|
|
39
|
+
placeholder="Developer Name"
|
|
38
40
|
required
|
|
39
|
-
class="w-full px-
|
|
41
|
+
class="w-full px-3.5 py-2 rounded-lg bg-[#06090f] border border-[#1a2333] text-white text-sm focus:outline-none focus:border-emerald-500 transition-colors"
|
|
40
42
|
/>
|
|
41
43
|
</div>
|
|
42
44
|
)}
|
|
43
45
|
|
|
44
46
|
<div>
|
|
45
|
-
<label class="block text-xs font-medium text-slate-300 mb-1.5"
|
|
47
|
+
<label class="block text-xs font-mono font-medium text-slate-300 mb-1.5" for="email">
|
|
48
|
+
Email Address
|
|
49
|
+
</label>
|
|
46
50
|
<input
|
|
51
|
+
id="email"
|
|
47
52
|
type="email"
|
|
48
53
|
name="email"
|
|
49
54
|
placeholder="admin@frootkit.dev"
|
|
50
55
|
defaultValue={isLogin ? 'admin@frootkit.dev' : ''}
|
|
51
56
|
required
|
|
52
|
-
class="w-full px-
|
|
57
|
+
class="w-full px-3.5 py-2 rounded-lg bg-[#06090f] border border-[#1a2333] text-white text-sm focus:outline-none focus:border-emerald-500 transition-colors"
|
|
53
58
|
/>
|
|
54
59
|
</div>
|
|
55
60
|
|
|
56
61
|
<div>
|
|
57
|
-
<label class="block text-xs font-medium text-slate-300 mb-1.5">
|
|
62
|
+
<label class="block text-xs font-mono font-medium text-slate-300 mb-1.5" for="password">
|
|
63
|
+
Password
|
|
64
|
+
</label>
|
|
58
65
|
<input
|
|
66
|
+
id="password"
|
|
59
67
|
type="password"
|
|
60
68
|
name="password"
|
|
61
69
|
placeholder="••••••••••••"
|
|
62
70
|
defaultValue={isLogin ? 'password123' : ''}
|
|
63
71
|
required
|
|
64
|
-
class="w-full px-
|
|
72
|
+
class="w-full px-3.5 py-2 rounded-lg bg-[#06090f] border border-[#1a2333] text-white text-sm focus:outline-none focus:border-emerald-500 transition-colors"
|
|
65
73
|
/>
|
|
66
74
|
</div>
|
|
67
75
|
|
|
68
76
|
<button
|
|
69
77
|
type="submit"
|
|
70
|
-
class="w-full py-
|
|
78
|
+
class="w-full py-2.5 rounded-lg bg-emerald-500 text-slate-950 font-semibold text-sm hover:bg-emerald-400 transition-colors mt-2"
|
|
71
79
|
>
|
|
72
80
|
{isLogin ? 'Sign In →' : 'Create Account →'}
|
|
73
81
|
</button>
|
|
@@ -1,47 +1,71 @@
|
|
|
1
1
|
export function DashboardNav() {
|
|
2
|
-
const links = [
|
|
3
|
-
{ label: 'Overview', href: '/dashboard', icon: '📊' },
|
|
4
|
-
{ label: 'Analytics', href: '/dashboard#analytics', icon: '📈' },
|
|
5
|
-
{ label: 'Team', href: '/dashboard#team', icon: '👥' },
|
|
6
|
-
{ label: 'API Keys', href: '/api/auth', icon: '🔑' },
|
|
7
|
-
];
|
|
8
|
-
|
|
9
2
|
return (
|
|
10
|
-
<aside class="w-64 border-r border-
|
|
3
|
+
<aside class="w-64 border-r border-[#1a2333] bg-[#0a0f18] p-6 flex flex-col justify-between shrink-0 min-h-screen">
|
|
11
4
|
<div>
|
|
12
|
-
<div class="flex items-center gap-2.5 font-bold text-white text-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
<div class="flex items-center gap-2.5 font-bold text-white text-base mb-8">
|
|
6
|
+
<div class="w-7 h-7 rounded-lg bg-emerald-500/10 border border-emerald-500/30 flex items-center justify-center text-emerald-400">
|
|
7
|
+
<svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
8
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
|
9
|
+
</svg>
|
|
10
|
+
</div>
|
|
16
11
|
<span>Workspace</span>
|
|
17
12
|
</div>
|
|
18
13
|
|
|
19
|
-
<nav class="space-y-1 text-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
<nav class="space-y-1 text-xs font-mono">
|
|
15
|
+
<a
|
|
16
|
+
href="/dashboard"
|
|
17
|
+
class="flex items-center gap-3 px-3 py-2 rounded-lg bg-[#0f1624] text-white border border-[#1a2333]"
|
|
18
|
+
>
|
|
19
|
+
<svg class="w-4 h-4 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
|
|
20
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
|
|
21
|
+
</svg>
|
|
22
|
+
<span>Overview</span>
|
|
23
|
+
</a>
|
|
24
|
+
|
|
25
|
+
<a
|
|
26
|
+
href="/dashboard#analytics"
|
|
27
|
+
class="flex items-center gap-3 px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-[#0f1624]/50 transition-colors"
|
|
28
|
+
>
|
|
29
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
|
|
30
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
|
|
31
|
+
</svg>
|
|
32
|
+
<span>Telemetry</span>
|
|
33
|
+
</a>
|
|
34
|
+
|
|
35
|
+
<a
|
|
36
|
+
href="/dashboard#team"
|
|
37
|
+
class="flex items-center gap-3 px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-[#0f1624]/50 transition-colors"
|
|
38
|
+
>
|
|
39
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
|
|
40
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
|
|
41
|
+
</svg>
|
|
42
|
+
<span>Members</span>
|
|
43
|
+
</a>
|
|
44
|
+
|
|
45
|
+
<a
|
|
46
|
+
href="/api/auth"
|
|
47
|
+
class="flex items-center gap-3 px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-[#0f1624]/50 transition-colors"
|
|
48
|
+
>
|
|
49
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
|
|
50
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" />
|
|
51
|
+
</svg>
|
|
52
|
+
<span>Session API</span>
|
|
53
|
+
</a>
|
|
30
54
|
</nav>
|
|
31
55
|
</div>
|
|
32
56
|
|
|
33
|
-
<div class="pt-6 border-t border-
|
|
57
|
+
<div class="pt-6 border-t border-[#1a2333] flex items-center justify-between">
|
|
34
58
|
<div class="flex items-center gap-2.5">
|
|
35
|
-
<div class="w-
|
|
36
|
-
|
|
59
|
+
<div class="w-7 h-7 rounded-full bg-emerald-500/10 border border-emerald-500/30 flex items-center justify-center font-bold text-xs text-emerald-400 font-mono">
|
|
60
|
+
AD
|
|
37
61
|
</div>
|
|
38
62
|
<div class="text-xs">
|
|
39
|
-
<div class="font-bold text-white">
|
|
40
|
-
<div class="text-slate-500">
|
|
63
|
+
<div class="font-bold text-white">admin@frootkit.dev</div>
|
|
64
|
+
<div class="text-slate-500 font-mono text-[11px]">Role: Administrator</div>
|
|
41
65
|
</div>
|
|
42
66
|
</div>
|
|
43
67
|
<form action="/api/auth?action=logout" method="POST">
|
|
44
|
-
<button type="submit" class="text-slate-
|
|
68
|
+
<button type="submit" class="text-slate-400 hover:text-rose-400 text-xs transition-colors" title="Sign out">
|
|
45
69
|
→
|
|
46
70
|
</button>
|
|
47
71
|
</form>
|
|
@@ -7,12 +7,12 @@ export interface MetricCardProps {
|
|
|
7
7
|
|
|
8
8
|
export function MetricCard({ label, value, change, isPositive }: MetricCardProps) {
|
|
9
9
|
return (
|
|
10
|
-
<div class="rounded-
|
|
11
|
-
<div class="text-xs font-medium text-slate-400 mb-2">{label}</div>
|
|
10
|
+
<div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-5">
|
|
11
|
+
<div class="text-xs font-mono font-medium text-slate-400 mb-2 uppercase tracking-wide">{label}</div>
|
|
12
12
|
<div class="flex items-baseline justify-between">
|
|
13
|
-
<div class="text-2xl sm:text-3xl font-
|
|
13
|
+
<div class="text-2xl sm:text-3xl font-extrabold text-white font-mono">{value}</div>
|
|
14
14
|
<span
|
|
15
|
-
class={`text-xs font-mono font-
|
|
15
|
+
class={`text-xs font-mono font-semibold px-2 py-0.5 rounded ${
|
|
16
16
|
isPositive
|
|
17
17
|
? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20'
|
|
18
18
|
: 'bg-rose-500/10 text-rose-400 border border-rose-500/20'
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export function Navbar() {
|
|
2
2
|
return (
|
|
3
|
-
<header class="border-b border-
|
|
3
|
+
<header class="border-b border-[#1a2333] bg-[#06090f]/95 sticky top-0 z-50">
|
|
4
4
|
<div class="max-w-6xl mx-auto px-6 h-16 flex items-center justify-between">
|
|
5
|
-
<a href="/" class="flex items-center gap-2.5 font-bold text-white text-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
<a href="/" class="flex items-center gap-2.5 font-bold text-white text-base tracking-tight hover:text-emerald-400 transition-colors">
|
|
6
|
+
<div class="w-8 h-8 rounded-lg bg-emerald-500/10 border border-emerald-500/30 flex items-center justify-center text-emerald-400">
|
|
7
|
+
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
8
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
|
9
|
+
</svg>
|
|
10
|
+
</div>
|
|
11
|
+
<span>Froot<span class="text-emerald-400">Auth</span></span>
|
|
10
12
|
</a>
|
|
11
13
|
|
|
12
14
|
<nav class="flex items-center gap-6 text-sm font-medium">
|
|
@@ -18,9 +20,9 @@ export function Navbar() {
|
|
|
18
20
|
</a>
|
|
19
21
|
<a
|
|
20
22
|
href="/signup"
|
|
21
|
-
class="px-4 py-2 rounded-
|
|
23
|
+
class="px-4 py-2 rounded-lg bg-emerald-500 text-slate-950 font-semibold hover:bg-emerald-400 transition-colors text-xs"
|
|
22
24
|
>
|
|
23
|
-
Get Started
|
|
25
|
+
Get Started →
|
|
24
26
|
</a>
|
|
25
27
|
</nav>
|
|
26
28
|
</div>
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
|
|
3
3
|
@theme {
|
|
4
|
-
--color-brand-
|
|
5
|
-
--color-brand-
|
|
6
|
-
--color-brand-200: #a7f3d0;
|
|
7
|
-
--color-brand-300: #6ee7b7;
|
|
8
|
-
--color-brand-400: #34d399;
|
|
9
|
-
--color-brand-500: #10b981;
|
|
10
|
-
--color-brand-600: #059669;
|
|
11
|
-
--color-brand-700: #047857;
|
|
12
|
-
--color-brand-800: #065f46;
|
|
13
|
-
--color-brand-900: #064e3b;
|
|
14
|
-
--color-brand-950: #022c22;
|
|
4
|
+
--color-brand-primary: #10b981;
|
|
5
|
+
--color-brand-hover: #34d399;
|
|
15
6
|
}
|
|
16
7
|
|
|
17
8
|
:root {
|
|
18
9
|
color-scheme: dark;
|
|
19
10
|
}
|
|
11
|
+
|
|
12
|
+
html {
|
|
13
|
+
background-color: #06090f;
|
|
14
|
+
color: #f8fafc;
|
|
15
|
+
scroll-behavior: smooth;
|
|
16
|
+
-webkit-font-smoothing: antialiased;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Accessibility: Mandatory Reduced Motion */
|
|
20
|
+
@media (prefers-reduced-motion: reduce) {
|
|
21
|
+
*, *::before, *::after {
|
|
22
|
+
animation-duration: 0.01ms !important;
|
|
23
|
+
animation-iteration-count: 1 !important;
|
|
24
|
+
transition-duration: 0.01ms !important;
|
|
25
|
+
scroll-behavior: auto !important;
|
|
26
|
+
}
|
|
27
|
+
}
|