create-frootkit 1.2.7 → 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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/templates/auth/package.json +1 -1
  3. package/templates/auth/src/app/dashboard/layout.tsx +14 -9
  4. package/templates/auth/src/app/dashboard/page.tsx +55 -24
  5. package/templates/auth/src/app/layout.tsx +3 -3
  6. package/templates/auth/src/app/login/page.tsx +5 -1
  7. package/templates/auth/src/app/page.tsx +103 -45
  8. package/templates/auth/src/app/signup/page.tsx +5 -1
  9. package/templates/auth/src/components/AuthForm.tsx +34 -19
  10. package/templates/auth/src/components/DashboardNav.tsx +97 -56
  11. package/templates/auth/src/components/MetricCard.tsx +13 -6
  12. package/templates/auth/src/components/Navbar.tsx +13 -12
  13. package/templates/auth/src/styles.css +27 -5
  14. package/templates/blog/package.json +1 -1
  15. package/templates/blog/src/app/blog/[slug]/page.tsx +19 -18
  16. package/templates/blog/src/app/layout.tsx +4 -4
  17. package/templates/blog/src/app/page.tsx +15 -14
  18. package/templates/blog/src/components/Footer.tsx +6 -6
  19. package/templates/blog/src/components/Navbar.tsx +17 -15
  20. package/templates/blog/src/components/Newsletter.tsx +11 -9
  21. package/templates/blog/src/components/PostCard.tsx +29 -27
  22. package/templates/blog/src/styles.css +14 -5
  23. package/templates/ecommerce/package.json +1 -1
  24. package/templates/ecommerce/src/app/cart/page.tsx +3 -3
  25. package/templates/ecommerce/src/app/layout.tsx +2 -2
  26. package/templates/ecommerce/src/app/page.tsx +37 -15
  27. package/templates/ecommerce/src/app/products/[id]/page.tsx +34 -25
  28. package/templates/ecommerce/src/components/CartDrawer.tsx +20 -17
  29. package/templates/ecommerce/src/components/Footer.tsx +6 -6
  30. package/templates/ecommerce/src/components/Navbar.tsx +21 -14
  31. package/templates/ecommerce/src/components/ProductCard.tsx +22 -15
  32. package/templates/ecommerce/src/data/products.ts +17 -11
  33. package/templates/ecommerce/src/styles.css +29 -5
  34. package/templates/empty/package.json +1 -1
  35. package/templates/empty/src/app/layout.tsx +5 -5
  36. package/templates/empty/src/app/page.tsx +10 -9
  37. package/templates/empty/src/styles.css +13 -15
  38. package/templates/starter/package.json +1 -1
  39. package/templates/starter/src/app/layout.tsx +4 -4
  40. package/templates/starter/src/app/page.tsx +41 -33
  41. package/templates/starter/src/components/FeatureCard.tsx +5 -5
  42. package/templates/starter/src/components/Footer.tsx +6 -6
  43. package/templates/starter/src/components/Header.tsx +18 -14
  44. package/templates/starter/src/components/TerminalPreview.tsx +30 -30
  45. package/templates/starter/src/styles.css +14 -5
@@ -1,80 +1,121 @@
1
1
  export function DashboardNav() {
2
2
  return (
3
- <aside class="w-64 border-r border-[#1a2333] bg-[#0a0f18] p-5 flex flex-col justify-between shrink-0 min-h-screen">
4
- <div>
5
- {/* Brand Header */}
6
- <div class="flex items-center gap-3 font-bold text-white text-base mb-6 px-1">
7
- <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 shrink-0">
8
- <svg width="18" height="18" style="width: 18px; height: 18px; min-width: 18px; min-height: 18px;" class="w-4.5 h-4.5 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
9
- <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" />
3
+ <aside class="w-60 border-r border-white/[0.08] bg-[#0d0e12] p-3 flex flex-col justify-between shrink-0 min-h-screen">
4
+ <div class="space-y-6">
5
+ {/* Workspace Brand / Org Selector */}
6
+ <div class="px-2 pt-1">
7
+ <div class="flex items-center justify-between p-1.5 rounded-lg hover:bg-white/[0.04] transition-colors cursor-pointer border border-transparent hover:border-white/[0.06]">
8
+ <div class="flex items-center gap-2.5 min-w-0">
9
+ <div class="w-6 h-6 rounded-md bg-indigo-500/15 border border-indigo-500/30 flex items-center justify-center text-indigo-400 shrink-0">
10
+ <svg style="width: 13px; height: 13px; min-width: 13px; min-height: 13px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
11
+ <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
12
+ </svg>
13
+ </div>
14
+ <div class="truncate">
15
+ <div class="text-xs font-semibold text-zinc-200 truncate">Orbit Workspace</div>
16
+ <div class="text-[10px] text-zinc-500 truncate">Production Cluster</div>
17
+ </div>
18
+ </div>
19
+ <svg style="width: 12px; height: 12px; min-width: 12px; min-height: 12px;" class="text-zinc-500 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
20
+ <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
10
21
  </svg>
11
22
  </div>
12
- <span class="tracking-tight">Workspace</span>
13
23
  </div>
14
24
 
15
- {/* Navigation Links */}
16
- <nav class="space-y-1 text-sm font-medium">
17
- <a
18
- href="/dashboard"
19
- class="flex items-center gap-3 px-3 py-2 rounded-lg bg-emerald-500/10 text-emerald-400 border border-emerald-500/25 transition-colors"
20
- >
21
- <svg width="18" height="18" style="width: 18px; height: 18px; min-width: 18px; min-height: 18px;" class="w-4.5 h-4.5 shrink-0 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
22
- <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" />
23
- </svg>
24
- <span>Overview</span>
25
- </a>
25
+ {/* Navigation Sections */}
26
+ <div class="space-y-4">
27
+ <div>
28
+ <div class="px-2.5 mb-1.5 text-[10px] font-semibold text-zinc-500 uppercase tracking-wider">
29
+ Platform
30
+ </div>
31
+ <nav class="space-y-0.5 text-xs font-medium">
32
+ <a
33
+ href="/dashboard"
34
+ class="flex items-center gap-2.5 px-2.5 py-1.5 rounded-md bg-white/[0.08] text-white border border-white/[0.08] shadow-[inset_0_1px_0_0_rgba(255,255,255,0.06)]"
35
+ >
36
+ <span class="w-4 h-4 flex items-center justify-center shrink-0 text-indigo-400">
37
+ <svg style="width: 14px; height: 14px; min-width: 14px; min-height: 14px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
38
+ <rect x="3" y="3" width="7" height="7" />
39
+ <rect x="14" y="3" width="7" height="7" />
40
+ <rect x="14" y="14" width="7" height="7" />
41
+ <rect x="3" y="14" width="7" height="7" />
42
+ </svg>
43
+ </span>
44
+ <span>Overview</span>
45
+ </a>
26
46
 
27
- <a
28
- href="/dashboard#analytics"
29
- class="flex items-center gap-3 px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-white/[0.04] transition-colors"
30
- >
31
- <svg width="18" height="18" style="width: 18px; height: 18px; min-width: 18px; min-height: 18px;" class="w-4.5 h-4.5 shrink-0 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
32
- <path stroke-linecap="round" stroke-linejoin="round" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
33
- </svg>
34
- <span>Telemetry</span>
35
- </a>
47
+ <a
48
+ href="/dashboard#analytics"
49
+ class="flex items-center gap-2.5 px-2.5 py-1.5 rounded-md text-zinc-400 hover:text-zinc-200 hover:bg-white/[0.04] transition-colors"
50
+ >
51
+ <span class="w-4 h-4 flex items-center justify-center shrink-0 text-zinc-500">
52
+ <svg style="width: 14px; height: 14px; min-width: 14px; min-height: 14px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
53
+ <polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
54
+ </svg>
55
+ </span>
56
+ <span>Telemetry</span>
57
+ </a>
36
58
 
37
- <a
38
- href="/dashboard#team"
39
- class="flex items-center gap-3 px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-white/[0.04] transition-colors"
40
- >
41
- <svg width="18" height="18" style="width: 18px; height: 18px; min-width: 18px; min-height: 18px;" class="w-4.5 h-4.5 shrink-0 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
42
- <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" />
43
- </svg>
44
- <span>Members</span>
45
- </a>
59
+ <a
60
+ href="/dashboard#team"
61
+ class="flex items-center gap-2.5 px-2.5 py-1.5 rounded-md text-zinc-400 hover:text-zinc-200 hover:bg-white/[0.04] transition-colors"
62
+ >
63
+ <span class="w-4 h-4 flex items-center justify-center shrink-0 text-zinc-500">
64
+ <svg style="width: 14px; height: 14px; min-width: 14px; min-height: 14px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
65
+ <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
66
+ <circle cx="9" cy="7" r="4" />
67
+ <path d="M23 21v-2a4 4 0 0 0-3-3.87" />
68
+ <path d="M16 3.13a4 4 0 0 1 0 7.75" />
69
+ </svg>
70
+ </span>
71
+ <span>Members</span>
72
+ </a>
73
+ </nav>
74
+ </div>
46
75
 
47
- <a
48
- href="/api/auth"
49
- class="flex items-center gap-3 px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-white/[0.04] transition-colors"
50
- >
51
- <svg width="18" height="18" style="width: 18px; height: 18px; min-width: 18px; min-height: 18px;" class="w-4.5 h-4.5 shrink-0 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
52
- <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" />
53
- </svg>
54
- <span>Session API</span>
55
- </a>
56
- </nav>
76
+ <div>
77
+ <div class="px-2.5 mb-1.5 text-[10px] font-semibold text-zinc-500 uppercase tracking-wider">
78
+ Developer
79
+ </div>
80
+ <nav class="space-y-0.5 text-xs font-medium">
81
+ <a
82
+ href="/api/auth"
83
+ class="flex items-center gap-2.5 px-2.5 py-1.5 rounded-md text-zinc-400 hover:text-zinc-200 hover:bg-white/[0.04] transition-colors"
84
+ >
85
+ <span class="w-4 h-4 flex items-center justify-center shrink-0 text-zinc-500">
86
+ <svg style="width: 14px; height: 14px; min-width: 14px; min-height: 14px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
87
+ <polyline points="16 18 22 12 16 6" />
88
+ <polyline points="8 6 2 12 8 18" />
89
+ </svg>
90
+ </span>
91
+ <span>Session API</span>
92
+ </a>
93
+ </nav>
94
+ </div>
95
+ </div>
57
96
  </div>
58
97
 
59
98
  {/* User profile & Sign out */}
60
- <div class="pt-4 border-t border-[#1a2333] flex items-center justify-between">
99
+ <div class="p-2 border-t border-white/[0.06] flex items-center justify-between">
61
100
  <div class="flex items-center gap-2.5 min-w-0">
62
- <div class="w-8 h-8 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 shrink-0">
101
+ <div class="w-7 h-7 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center font-medium text-[11px] text-white shrink-0">
63
102
  AD
64
103
  </div>
65
- <div class="text-xs truncate">
66
- <div class="font-semibold text-white truncate">admin@frootkit.dev</div>
67
- <div class="text-slate-400 text-[11px]">Administrator</div>
104
+ <div class="text-xs min-w-0 truncate">
105
+ <div class="font-medium text-zinc-200 truncate">admin@frootkit.dev</div>
106
+ <div class="text-zinc-500 text-[10px] truncate">Owner</div>
68
107
  </div>
69
108
  </div>
70
- <form action="/api/auth?action=logout" method="POST" class="shrink-0 ml-2">
109
+ <form action="/api/auth?action=logout" method="POST" class="shrink-0 ml-1">
71
110
  <button
72
111
  type="submit"
73
- class="p-1.5 rounded-md text-slate-400 hover:text-rose-400 hover:bg-rose-500/10 transition-colors"
112
+ class="p-1.5 rounded-md text-zinc-500 hover:text-zinc-200 hover:bg-white/[0.06] transition-colors"
74
113
  title="Sign out"
75
114
  >
76
- <svg width="16" height="16" style="width: 16px; height: 16px; min-width: 16px; min-height: 16px;" class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
77
- <path stroke-linecap="round" stroke-linejoin="round" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
115
+ <svg style="width: 14px; height: 14px; min-width: 14px; min-height: 14px;" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
116
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
117
+ <polyline points="16 17 21 12 16 7" />
118
+ <line x1="21" y1="12" x2="9" y2="12" />
78
119
  </svg>
79
120
  </button>
80
121
  </form>
@@ -3,26 +3,33 @@ export interface MetricCardProps {
3
3
  value: string;
4
4
  change: string;
5
5
  isPositive: boolean;
6
+ context?: string;
6
7
  }
7
8
 
8
- export function MetricCard({ label, value, change, isPositive }: MetricCardProps) {
9
+ export function MetricCard({ label, value, change, isPositive, context = 'vs last 30d' }: MetricCardProps) {
9
10
  return (
10
- <div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-5 flex flex-col justify-between shadow-sm">
11
- <div class="text-xs font-medium text-slate-400 mb-3 tracking-wide">
11
+ <div class="rounded-xl border border-white/[0.08] bg-[#0f1117] p-4 sm:p-5 flex flex-col justify-between shadow-[inset_0_1px_0_0_rgba(255,255,255,0.05)] transition-all hover:border-white/[0.14]">
12
+ <div class="text-xs font-medium text-zinc-400 mb-3 tracking-normal">
12
13
  {label}
13
14
  </div>
14
15
  <div class="flex items-baseline justify-between gap-3">
15
- <div class="text-2xl font-bold text-white tracking-tight">{value}</div>
16
+ <div class="text-2xl sm:text-3xl font-semibold text-white tracking-tight tabular-nums">
17
+ {value}
18
+ </div>
16
19
  <span
17
- class={`text-xs font-semibold px-2 py-0.5 rounded-md border shrink-0 ${
20
+ class={`inline-flex items-center gap-1 text-[11px] font-medium px-2 py-0.5 rounded-full border shrink-0 ${
18
21
  isPositive
19
22
  ? 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20'
20
23
  : 'bg-rose-500/10 text-rose-400 border-rose-500/20'
21
24
  }`}
22
25
  >
23
- {change}
26
+ <span>{isPositive ? '↑' : '↓'}</span>
27
+ <span>{change}</span>
24
28
  </span>
25
29
  </div>
30
+ <div class="mt-2 text-[11px] text-zinc-500">
31
+ {context}
32
+ </div>
26
33
  </div>
27
34
  );
28
35
  }
@@ -1,29 +1,30 @@
1
1
  export function Navbar() {
2
2
  return (
3
- <header class="border-b border-[#1a2333] bg-[#06090f]/95 sticky top-0 z-50">
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-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 shrink-0">
7
- <svg width="18" height="18" class="w-4.5 h-4.5 shrink-0" 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" />
3
+ <header class="border-b border-white/[0.08] bg-[#08090a]/80 backdrop-blur-md sticky top-0 z-50">
4
+ <div class="max-w-6xl mx-auto px-6 h-14 flex items-center justify-between">
5
+ <a href="/" class="flex items-center gap-2.5 font-semibold text-zinc-100 text-sm tracking-tight group">
6
+ <div class="w-7 h-7 rounded-md bg-indigo-500/10 border border-indigo-500/25 flex items-center justify-center text-indigo-400 group-hover:border-indigo-400/50 transition-colors shrink-0">
7
+ <svg style="width: 14px; height: 14px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
8
+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
9
+ <path d="M7 11V7a5 5 0 0 1 10 0v4" />
9
10
  </svg>
10
11
  </div>
11
- <span>Froot<span class="text-emerald-400">Auth</span></span>
12
+ <span>Froot<span class="text-indigo-400">Auth</span></span>
12
13
  </a>
13
14
 
14
- <nav class="flex items-center gap-6 text-sm font-medium">
15
- <a href="/dashboard" class="text-slate-300 hover:text-white transition-colors">
15
+ <nav class="flex items-center gap-5 text-xs font-medium">
16
+ <a href="/dashboard" class="text-zinc-400 hover:text-zinc-200 transition-colors">
16
17
  Dashboard
17
18
  </a>
18
- <a href="/login" class="text-slate-300 hover:text-white transition-colors">
19
+ <a href="/login" class="text-zinc-400 hover:text-zinc-200 transition-colors">
19
20
  Sign In
20
21
  </a>
21
22
  <a
22
23
  href="/signup"
23
- class="px-4 py-2 rounded-lg bg-emerald-500 text-slate-950 font-semibold hover:bg-emerald-400 transition-colors text-xs flex items-center gap-1.5"
24
+ class="px-3 py-1.5 rounded-md bg-white text-zinc-950 font-medium hover:bg-zinc-200 transition-all text-xs shadow-sm flex items-center gap-1.5"
24
25
  >
25
26
  <span>Get Started</span>
26
- <span>→</span>
27
+ <span class="text-zinc-500">→</span>
27
28
  </a>
28
29
  </nav>
29
30
  </div>
@@ -4,28 +4,50 @@
4
4
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
5
5
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
6
6
 
7
- --color-brand-primary: #10b981;
8
- --color-brand-hover: #34d399;
7
+ --color-brand-primary: #6366f1;
8
+ --color-brand-hover: #4f46e5;
9
9
  }
10
10
 
11
11
  :root {
12
12
  color-scheme: dark;
13
+ --bg-canvas: #08090a;
14
+ --bg-surface: #0f1117;
15
+ --bg-elevated: #151822;
16
+ --border-subtle: rgba(255, 255, 255, 0.08);
17
+ --border-strong: rgba(255, 255, 255, 0.16);
18
+ --text-primary: #f4f4f5;
19
+ --text-secondary: #9496a1;
20
+ --text-muted: #5c6370;
13
21
  }
14
22
 
15
23
  html {
16
- background-color: #06090f;
17
- color: #f8fafc;
24
+ background-color: var(--bg-canvas);
25
+ color: var(--text-primary);
18
26
  font-family: var(--font-sans);
19
27
  scroll-behavior: smooth;
20
28
  -webkit-font-smoothing: antialiased;
29
+ -moz-osx-font-smoothing: grayscale;
21
30
  }
22
31
 
23
- /* SVG safety: prevents flex ballooning across all browsers */
32
+ /* Strict SVG safety to prevent flex ballooning */
24
33
  svg {
25
34
  flex-shrink: 0;
26
35
  max-width: 100%;
27
36
  }
28
37
 
38
+ /* Linear-style subtle card highlight */
39
+ .linear-card {
40
+ background-color: var(--bg-surface);
41
+ border: 1px solid var(--border-subtle);
42
+ box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.06);
43
+ border-radius: 0.75rem;
44
+ transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
45
+ }
46
+
47
+ .linear-card:hover {
48
+ border-color: var(--border-strong);
49
+ }
50
+
29
51
  /* Accessibility: Mandatory Reduced Motion */
30
52
  @media (prefers-reduced-motion: reduce) {
31
53
  *, *::before, *::after {
@@ -8,7 +8,7 @@
8
8
  "start": "frootkit start"
9
9
  },
10
10
  "dependencies": {
11
- "frootkit": "npm:froot-kit@^1.3.2",
11
+ "frootkit": "npm:froot-kit@^1.3.4",
12
12
  "frootjs": "^1.0.6",
13
13
  "preact": "^11.1.0",
14
14
  "preact-render-to-string": "^6.8.2"
@@ -11,58 +11,59 @@ export default function BlogPostPage({ params }: { params?: { slug?: string } })
11
11
  const post = POSTS.find((p) => p.slug === slug) || POSTS[0]!;
12
12
 
13
13
  return (
14
- <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
14
+ <div class="min-h-screen bg-[#08090a] text-zinc-100 flex flex-col justify-between selection:bg-indigo-500/20 selection:text-indigo-300">
15
15
  <Navbar />
16
16
 
17
17
  <main class="max-w-3xl mx-auto px-6 py-12 flex-1 w-full">
18
18
  <a
19
19
  href="/"
20
- class="inline-flex items-center gap-2 text-xs font-mono text-slate-400 hover:text-emerald-400 mb-8 transition-colors"
20
+ class="inline-flex items-center gap-2 text-xs text-zinc-400 hover:text-white mb-8 transition-colors"
21
21
  >
22
- ← Back to articles
22
+ <span>←</span>
23
+ <span>Back to articles</span>
23
24
  </a>
24
25
 
25
26
  <header class="mb-10">
26
- <div class="flex items-center gap-3 mb-4 text-xs font-mono">
27
- <span class="px-2.5 py-0.5 rounded bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 font-semibold">
27
+ <div class="flex items-center gap-3 mb-4 text-xs">
28
+ <span class="px-2.5 py-0.5 rounded-full bg-indigo-500/10 text-indigo-400 border border-indigo-500/20 font-medium text-[11px]">
28
29
  {post.category}
29
30
  </span>
30
- <span class="text-slate-500">•</span>
31
- <span class="text-slate-400">{post.readTime}</span>
32
- <span class="text-slate-500">•</span>
33
- <span class="text-slate-400">{post.date}</span>
31
+ <span class="text-zinc-600">•</span>
32
+ <span class="text-zinc-400">{post.readTime}</span>
33
+ <span class="text-zinc-600">•</span>
34
+ <span class="text-zinc-400">{post.date}</span>
34
35
  </div>
35
36
 
36
- <h1 class="text-3xl sm:text-5xl font-extrabold text-white tracking-tight mb-6 leading-tight">
37
+ <h1 class="text-3xl sm:text-4xl font-semibold text-white tracking-[-0.025em] mb-6 leading-tight">
37
38
  {post.title}
38
39
  </h1>
39
40
 
40
- <div class="flex items-center gap-4 p-4 rounded-xl bg-[#0a0f18] border border-[#1a2333]">
41
+ <div class="flex items-center gap-3.5 p-3.5 rounded-xl bg-[#0f1117] border border-white/[0.08] shadow-[inset_0_1px_0_0_rgba(255,255,255,0.05)]">
41
42
  <img
42
43
  src={post.author.avatar}
43
44
  alt={post.author.name}
44
- class="w-10 h-10 rounded-full object-cover border border-[#1a2333]"
45
+ class="w-9 h-9 rounded-full object-cover border border-white/[0.1]"
45
46
  />
46
47
  <div>
47
- <div class="font-bold text-white text-sm">{post.author.name}</div>
48
- <div class="text-xs text-slate-400">{post.author.role}</div>
48
+ <div class="font-medium text-white text-xs">{post.author.name}</div>
49
+ <div class="text-[11px] text-zinc-400">{post.author.role}</div>
49
50
  </div>
50
51
  </div>
51
52
  </header>
52
53
 
53
- <article class="prose max-w-none space-y-6 text-slate-300 leading-relaxed text-base sm:text-lg">
54
+ <article class="prose max-w-none space-y-6 text-zinc-300 leading-relaxed text-base">
54
55
  {post.content.map((paragraph, idx) => (
55
56
  <p key={idx}>{paragraph}</p>
56
57
  ))}
57
58
  </article>
58
59
 
59
- <div class="mt-12 pt-8 border-t border-[#1a2333] flex flex-wrap gap-2">
60
+ <div class="mt-12 pt-8 border-t border-white/[0.08] flex flex-wrap gap-2">
60
61
  {post.tags.map((tag) => (
61
62
  <span
62
63
  key={tag}
63
- class="px-2.5 py-1 rounded bg-[#0a0f18] text-xs font-mono text-slate-400 border border-[#1a2333]"
64
+ class="px-2.5 py-1 rounded-full bg-white/[0.04] text-xs font-medium text-zinc-300 border border-white/[0.06]"
64
65
  >
65
- #{tag}
66
+ {tag}
66
67
  </span>
67
68
  ))}
68
69
  </div>
@@ -9,10 +9,10 @@ export interface RootLayoutProps {
9
9
  }
10
10
 
11
11
  export default function RootLayout({ children, metadata }: RootLayoutProps) {
12
- const title = metadata?.title || 'FrootBlog — Insights on Modern Web Performance';
12
+ const title = metadata?.title || 'FrootBlog — Engineering Architecture';
13
13
  const description =
14
14
  metadata?.description ||
15
- 'High-performance engineering articles and tutorials powered by Preact SSR and FrootKit.';
15
+ 'Deep dives into Preact SSR, monomorphic engines, and zero-hydration architectures.';
16
16
 
17
17
  return (
18
18
  <html lang="en" class="dark scroll-smooth">
@@ -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;800&family=JetBrains+Mono:wght@400;500;600&display=swap"
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-[#030712] text-slate-100 min-h-screen antialiased selection:bg-emerald-500/20 selection:text-emerald-300 font-sans">
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>
@@ -5,7 +5,7 @@ import { Newsletter } from '../components/Newsletter.js';
5
5
  import { Footer } from '../components/Footer.js';
6
6
 
7
7
  export const metadata = {
8
- title: 'FrootBlog — Engineering Articles & Systems Architecture',
8
+ title: 'FrootJournal — Engineering Articles & Systems Architecture',
9
9
  description: 'Deep dives into Preact SSR, fullstack TypeScript, and native styling.',
10
10
  };
11
11
 
@@ -13,19 +13,20 @@ export default function BlogHomePage() {
13
13
  const [featuredPost, ...recentPosts] = POSTS;
14
14
 
15
15
  return (
16
- <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
16
+ <div class="min-h-screen bg-[#08090a] text-zinc-100 flex flex-col justify-between selection:bg-indigo-500/20 selection:text-indigo-300">
17
17
  <Navbar />
18
18
 
19
- <main class="max-w-5xl mx-auto px-6 py-12 flex-1 w-full">
19
+ <main class="max-w-5xl mx-auto px-6 py-12 sm:py-16 flex-1 w-full">
20
20
  {/* Header Block */}
21
- <div class="mb-10">
22
- <div class="text-xs font-mono font-medium text-emerald-400 mb-2 uppercase tracking-wide">
23
- Engineering Journal
21
+ <div class="mb-12">
22
+ <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-4">
23
+ <span class="w-1.5 h-1.5 rounded-full bg-indigo-400" />
24
+ <span>Systems Architecture Journal</span>
24
25
  </div>
25
- <h1 class="text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-3">
26
- Systems Architecture & Web Engineering
26
+ <h1 class="text-3xl sm:text-5xl font-semibold text-white tracking-[-0.03em] leading-tight mb-4">
27
+ Engineering Dispatch & Systems Architecture.
27
28
  </h1>
28
- <p class="text-slate-400 text-base max-w-2xl leading-relaxed">
29
+ <p class="text-zinc-400 text-base max-w-2xl leading-relaxed">
29
30
  Exploring sub-millisecond server rendering, monomorphic dispatch trees, and zero-hydration web architectures.
30
31
  </p>
31
32
  </div>
@@ -34,16 +35,16 @@ export default function BlogHomePage() {
34
35
  {featuredPost && <PostCard post={featuredPost} featured={true} />}
35
36
 
36
37
  {/* Recent Articles Grid */}
37
- <div class="mb-8 flex items-center justify-between border-b border-[#1a2333] pb-3">
38
- <h2 class="text-xs font-mono uppercase tracking-wider text-slate-400 font-semibold">
39
- All Articles
38
+ <div class="mb-8 flex items-center justify-between border-b border-white/[0.08] pb-4">
39
+ <h2 class="text-xs uppercase tracking-wider text-zinc-400 font-semibold">
40
+ Recent Publications
40
41
  </h2>
41
- <span class="text-xs font-mono text-slate-500">
42
+ <span class="text-xs text-zinc-500 tabular-nums">
42
43
  {recentPosts.length + 1} publications
43
44
  </span>
44
45
  </div>
45
46
 
46
- <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
47
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-5">
47
48
  {recentPosts.map((post) => (
48
49
  <PostCard key={post.slug} post={post} />
49
50
  ))}
@@ -1,14 +1,14 @@
1
1
  export function Footer() {
2
2
  return (
3
- <footer class="border-t border-[#1a2333] bg-[#06090f] py-8 text-xs text-slate-400">
4
- <div class="max-w-5xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4 font-mono">
3
+ <footer class="border-t border-white/[0.08] bg-[#08090a] py-8 text-xs text-zinc-500">
4
+ <div class="max-w-5xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
5
5
  <div>
6
- FrootBlog © {new Date().getFullYear()} OrbitNorth LLC. MIT Licensed.
6
+ FrootBlog © {new Date().getFullYear()} OrbitNorth LLC. Written for systems engineers.
7
7
  </div>
8
8
  <div class="flex items-center gap-6">
9
- <a href="https://github.com/orbitnorth/frootkit" class="hover:text-white transition-colors">GitHub</a>
10
- <a href="https://frootjs.org" class="hover:text-white transition-colors">Documentation</a>
11
- <a href="/api/posts" class="hover:text-white transition-colors">Posts API</a>
9
+ <a href="https://github.com/orbitnorth/frootkit" class="hover:text-zinc-300 transition-colors">GitHub</a>
10
+ <a href="https://frootjs.org" class="hover:text-zinc-300 transition-colors">Documentation</a>
11
+ <a href="/api/posts" class="hover:text-zinc-300 transition-colors font-mono text-[11px]">/api/posts</a>
12
12
  </div>
13
13
  </div>
14
14
  </footer>
@@ -1,30 +1,32 @@
1
1
  export function Navbar() {
2
2
  return (
3
- <header class="border-b border-[#1a2333] bg-[#06090f]/95 sticky top-0 z-50">
4
- <div class="max-w-5xl mx-auto px-6 h-16 flex items-center justify-between">
5
- <a href="/" class="flex items-center gap-3 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 width="16" height="16" class="w-4 h-4 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
8
- <path stroke-linecap="round" stroke-linejoin="round" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z" />
3
+ <header class="border-b border-white/[0.08] bg-[#08090a]/80 backdrop-blur-md sticky top-0 z-50">
4
+ <div class="max-w-5xl mx-auto px-6 h-14 flex items-center justify-between">
5
+ <a href="/" class="flex items-center gap-2.5 font-semibold text-zinc-100 text-sm tracking-tight group">
6
+ <div class="w-6 h-6 rounded-md bg-indigo-500/15 border border-indigo-500/30 flex items-center justify-center text-indigo-400 group-hover:border-indigo-400/50 transition-colors shrink-0">
7
+ <svg style="width: 13px; height: 13px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
8
+ <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" />
9
+ <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z" />
9
10
  </svg>
10
11
  </div>
11
- <span>Froot<span class="text-emerald-400">Blog</span></span>
12
+ <span>Froot<span class="text-indigo-400">Journal</span></span>
12
13
  </a>
13
14
 
14
- <nav class="flex items-center gap-6 text-sm font-medium">
15
- <a href="/" class="text-slate-300 hover:text-white transition-colors">
15
+ <nav class="flex items-center gap-5 text-xs font-medium">
16
+ <a href="/" class="text-zinc-400 hover:text-zinc-200 transition-colors">
16
17
  Articles
17
18
  </a>
18
- <a href="/api/posts" class="text-emerald-400 hover:text-emerald-300 font-mono text-xs px-2.5 py-1 rounded-md bg-[#0a0f18] border border-[#1a2333] transition-colors">
19
+ <a
20
+ href="/api/posts"
21
+ class="text-zinc-400 hover:text-zinc-200 font-mono text-[11px] px-2 py-0.5 rounded bg-white/[0.03] border border-white/[0.06] transition-colors"
22
+ >
19
23
  /api/posts
20
24
  </a>
21
25
  <a
22
- href="https://github.com/orbitnorth/frootkit"
23
- target="_blank"
24
- rel="noreferrer"
25
- class="text-slate-300 hover:text-white transition-colors"
26
+ href="#newsletter"
27
+ class="px-3 py-1.5 rounded-md bg-white text-zinc-950 font-medium hover:bg-zinc-200 transition-all text-xs shadow-sm"
26
28
  >
27
- GitHub
29
+ Subscribe
28
30
  </a>
29
31
  </nav>
30
32
  </div>