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.
Files changed (59) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +2 -2
  3. package/templates/auth/src/app/dashboard/layout.tsx +9 -9
  4. package/templates/auth/src/app/dashboard/page.tsx +16 -16
  5. package/templates/auth/src/app/login/page.tsx +2 -2
  6. package/templates/auth/src/app/page.tsx +77 -37
  7. package/templates/auth/src/app/signup/page.tsx +2 -2
  8. package/templates/auth/src/components/AuthForm.tsx +25 -17
  9. package/templates/auth/src/components/DashboardNav.tsx +53 -29
  10. package/templates/auth/src/components/MetricCard.tsx +4 -4
  11. package/templates/auth/src/components/Navbar.tsx +10 -8
  12. package/templates/auth/src/styles.css +19 -11
  13. package/templates/blog/src/app/blog/[slug]/page.tsx +9 -9
  14. package/templates/blog/src/app/page.tsx +26 -12
  15. package/templates/blog/src/components/Footer.tsx +5 -5
  16. package/templates/blog/src/components/Navbar.tsx +8 -6
  17. package/templates/blog/src/components/Newsletter.tsx +16 -10
  18. package/templates/blog/src/components/PostCard.tsx +60 -13
  19. package/templates/blog/src/styles.css +19 -11
  20. package/templates/ecommerce/src/app/cart/page.tsx +2 -2
  21. package/templates/ecommerce/src/app/page.tsx +20 -29
  22. package/templates/ecommerce/src/app/products/[id]/page.tsx +19 -18
  23. package/templates/ecommerce/src/components/CartDrawer.tsx +12 -12
  24. package/templates/ecommerce/src/components/Footer.tsx +5 -5
  25. package/templates/ecommerce/src/components/Navbar.tsx +13 -8
  26. package/templates/ecommerce/src/components/ProductCard.tsx +14 -13
  27. package/templates/ecommerce/src/styles.css +19 -11
  28. package/templates/empty/src/app/page.tsx +9 -9
  29. package/templates/empty/src/styles.css +19 -11
  30. package/templates/starter/src/app/page.tsx +75 -74
  31. package/templates/starter/src/components/FeatureCard.tsx +10 -6
  32. package/templates/starter/src/components/Footer.tsx +5 -5
  33. package/templates/starter/src/components/Header.tsx +5 -5
  34. package/templates/starter/src/components/TerminalPreview.tsx +28 -28
  35. package/templates/starter/src/styles.css +19 -11
  36. package/dist/templates/auth.d.ts +0 -3
  37. package/dist/templates/auth.d.ts.map +0 -1
  38. package/dist/templates/auth.js +0 -487
  39. package/dist/templates/auth.js.map +0 -1
  40. package/dist/templates/blog.d.ts +0 -3
  41. package/dist/templates/blog.d.ts.map +0 -1
  42. package/dist/templates/blog.js +0 -369
  43. package/dist/templates/blog.js.map +0 -1
  44. package/dist/templates/common.d.ts +0 -5
  45. package/dist/templates/common.d.ts.map +0 -1
  46. package/dist/templates/common.js +0 -116
  47. package/dist/templates/common.js.map +0 -1
  48. package/dist/templates/ecommerce.d.ts +0 -3
  49. package/dist/templates/ecommerce.d.ts.map +0 -1
  50. package/dist/templates/ecommerce.js +0 -474
  51. package/dist/templates/ecommerce.js.map +0 -1
  52. package/dist/templates/empty.d.ts +0 -3
  53. package/dist/templates/empty.d.ts.map +0 -1
  54. package/dist/templates/empty.js +0 -85
  55. package/dist/templates/empty.js.map +0 -1
  56. package/dist/templates/starter.d.ts +0 -3
  57. package/dist/templates/starter.d.ts.map +0 -1
  58. package/dist/templates/starter.js +0 -308
  59. package/dist/templates/starter.js.map +0 -1
@@ -11,20 +11,20 @@ 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 flex flex-col justify-between">
14
+ <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
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-sm text-slate-400 hover:text-emerald-400 mb-8 transition-colors"
20
+ class="inline-flex items-center gap-2 text-xs font-mono text-slate-400 hover:text-emerald-400 mb-8 transition-colors"
21
21
  >
22
- &larr; Back to all articles
22
+ &larr; Back to articles
23
23
  </a>
24
24
 
25
25
  <header class="mb-10">
26
26
  <div class="flex items-center gap-3 mb-4 text-xs font-mono">
27
- <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 font-medium">
27
+ <span class="px-2.5 py-0.5 rounded bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 font-semibold">
28
28
  {post.category}
29
29
  </span>
30
30
  <span class="text-slate-500">&bull;</span>
@@ -37,11 +37,11 @@ export default function BlogPostPage({ params }: { params?: { slug?: string } })
37
37
  {post.title}
38
38
  </h1>
39
39
 
40
- <div class="flex items-center gap-4 p-4 rounded-2xl bg-slate-900/50 border border-slate-800">
40
+ <div class="flex items-center gap-4 p-4 rounded-xl bg-[#0a0f18] border border-[#1a2333]">
41
41
  <img
42
42
  src={post.author.avatar}
43
43
  alt={post.author.name}
44
- class="w-12 h-12 rounded-full object-cover ring-2 ring-emerald-500/30"
44
+ class="w-10 h-10 rounded-full object-cover border border-[#1a2333]"
45
45
  />
46
46
  <div>
47
47
  <div class="font-bold text-white text-sm">{post.author.name}</div>
@@ -50,17 +50,17 @@ export default function BlogPostPage({ params }: { params?: { slug?: string } })
50
50
  </div>
51
51
  </header>
52
52
 
53
- <article class="prose prose-invert prose-emerald max-w-none space-y-6 text-slate-300 leading-relaxed text-base sm:text-lg">
53
+ <article class="prose max-w-none space-y-6 text-slate-300 leading-relaxed text-base sm:text-lg">
54
54
  {post.content.map((paragraph, idx) => (
55
55
  <p key={idx}>{paragraph}</p>
56
56
  ))}
57
57
  </article>
58
58
 
59
- <div class="mt-12 pt-8 border-t border-slate-800/80 flex flex-wrap gap-2">
59
+ <div class="mt-12 pt-8 border-t border-[#1a2333] flex flex-wrap gap-2">
60
60
  {post.tags.map((tag) => (
61
61
  <span
62
62
  key={tag}
63
- class="px-3 py-1 rounded-lg bg-slate-900 text-xs text-slate-300 border border-slate-800"
63
+ class="px-2.5 py-1 rounded bg-[#0a0f18] text-xs font-mono text-slate-400 border border-[#1a2333]"
64
64
  >
65
65
  #{tag}
66
66
  </span>
@@ -5,32 +5,46 @@ import { Newsletter } from '../components/Newsletter.js';
5
5
  import { Footer } from '../components/Footer.js';
6
6
 
7
7
  export const metadata = {
8
- title: 'FrootBlog — Insights on Modern Web Performance',
8
+ title: 'FrootBlog — Engineering Articles & Systems Architecture',
9
9
  description: 'Deep dives into Preact SSR, fullstack TypeScript, and native styling.',
10
10
  };
11
11
 
12
12
  export default function BlogHomePage() {
13
+ const [featuredPost, ...recentPosts] = POSTS;
14
+
13
15
  return (
14
- <div class="min-h-screen flex flex-col justify-between">
16
+ <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
15
17
  <Navbar />
16
18
 
17
19
  <main class="max-w-5xl mx-auto px-6 py-12 flex-1 w-full">
18
- {/* Header Banner */}
19
- <div class="mb-12 text-center sm:text-left">
20
- <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-xs font-semibold text-emerald-400 mb-4">
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">
21
23
  Engineering Journal
22
24
  </div>
23
- <h1 class="text-4xl sm:text-5xl font-black text-white tracking-tight mb-4">
24
- Stories, Architecture & Tutorials
25
+ <h1 class="text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-3">
26
+ Systems Architecture & Web Engineering
25
27
  </h1>
26
- <p class="text-slate-400 text-base sm:text-lg max-w-2xl">
27
- Exploring the bleeding edge of sub-millisecond server rendering, zero-overhead client apps, and modern developer velocity.
28
+ <p class="text-slate-400 text-base max-w-2xl leading-relaxed">
29
+ Exploring sub-millisecond server rendering, monomorphic dispatch trees, and zero-hydration web architectures.
28
30
  </p>
29
31
  </div>
30
32
 
31
- {/* Post Grid */}
32
- <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
33
- {POSTS.map((post) => (
33
+ {/* Featured Dominant Article */}
34
+ {featuredPost && <PostCard post={featuredPost} featured={true} />}
35
+
36
+ {/* 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
40
+ </h2>
41
+ <span class="text-xs font-mono text-slate-500">
42
+ {recentPosts.length + 1} publications
43
+ </span>
44
+ </div>
45
+
46
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
47
+ {recentPosts.map((post) => (
34
48
  <PostCard key={post.slug} post={post} />
35
49
  ))}
36
50
  </div>
@@ -1,14 +1,14 @@
1
1
  export function Footer() {
2
2
  return (
3
- <footer class="border-t border-slate-900 bg-slate-950/60 py-8 text-center text-xs text-slate-500">
4
- <div class="max-w-5xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
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">
5
5
  <div>
6
6
  FrootBlog &copy; {new Date().getFullYear()} OrbitNorth LLC. MIT Licensed.
7
7
  </div>
8
8
  <div class="flex items-center gap-6">
9
- <a href="https://github.com/orbitnorth/frootkit" class="hover:text-slate-400 transition-colors">GitHub</a>
10
- <a href="https://frootjs.org" class="hover:text-slate-400 transition-colors">Documentation</a>
11
- <a href="/api/posts" class="hover:text-slate-400 transition-colors">Posts API</a>
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>
12
12
  </div>
13
13
  </div>
14
14
  </footer>
@@ -1,11 +1,13 @@
1
1
  export function Navbar() {
2
2
  return (
3
- <header class="border-b border-slate-800/80 bg-slate-950/60 backdrop-blur-md sticky top-0 z-50">
3
+ <header class="border-b border-[#1a2333] bg-[#06090f]/95 sticky top-0 z-50">
4
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-extrabold text-white text-lg tracking-tight hover:opacity-90">
6
- <span class="w-8 h-8 rounded-xl bg-gradient-to-tr from-emerald-500 to-cyan-400 flex items-center justify-center text-slate-950 font-black text-sm">
7
- F
8
- </span>
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 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="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" />
9
+ </svg>
10
+ </div>
9
11
  <span>Froot<span class="text-emerald-400">Blog</span></span>
10
12
  </a>
11
13
 
@@ -13,7 +15,7 @@ export function Navbar() {
13
15
  <a href="/" class="text-slate-300 hover:text-white transition-colors">
14
16
  Articles
15
17
  </a>
16
- <a href="/api/posts" class="text-slate-400 hover:text-emerald-400 transition-colors font-mono text-xs px-2 py-1 rounded bg-slate-900 border border-slate-800">
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">
17
19
  /api/posts
18
20
  </a>
19
21
  <a
@@ -1,27 +1,33 @@
1
1
  export function Newsletter() {
2
2
  return (
3
- <div class="rounded-3xl border border-emerald-500/20 bg-gradient-to-b from-emerald-950/20 to-slate-900/40 p-8 sm:p-12 text-center my-16 backdrop-blur-sm">
4
- <div class="max-w-xl mx-auto">
5
- <h3 class="text-2xl sm:text-3xl font-bold text-white mb-3">
6
- Subscribe to the FrootKit Dispatch
3
+ <div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-8 sm:p-10 my-16">
4
+ <div class="max-w-xl">
5
+ <div class="text-xs font-mono font-medium text-emerald-400 mb-2 uppercase tracking-wide">
6
+ Engineering Dispatch
7
+ </div>
8
+ <h3 class="text-2xl font-bold text-white mb-2">
9
+ Subscribe for Technical Deep Dives
7
10
  </h3>
8
- <p class="text-slate-400 text-sm mb-8">
9
- Weekly deep-dives into modern web architectures, performance optimization, and fullstack TypeScript.
11
+ <p class="text-slate-400 text-sm mb-6 leading-relaxed">
12
+ Bi-weekly write-ups on sub-millisecond server rendering, zero-hydration architectures, and high-performance TypeScript.
10
13
  </p>
14
+
11
15
  <form
12
16
  action="/api/posts"
13
17
  method="GET"
14
- class="flex flex-col sm:flex-row gap-3 max-w-md mx-auto"
18
+ class="flex flex-col sm:flex-row gap-3 max-w-md"
15
19
  >
20
+ <label class="sr-only" for="newsletter-email">Work Email</label>
16
21
  <input
22
+ id="newsletter-email"
17
23
  type="email"
18
- placeholder="colleague@company.com"
24
+ placeholder="developer@company.com"
19
25
  required
20
- class="flex-1 px-4 py-3 rounded-xl bg-slate-950 border border-slate-800 text-white text-sm focus:outline-none focus:border-emerald-500"
26
+ class="flex-1 px-4 py-2.5 rounded-lg bg-[#06090f] border border-[#1a2333] text-white text-sm focus:outline-none focus:border-emerald-500 transition-colors"
21
27
  />
22
28
  <button
23
29
  type="submit"
24
- class="px-6 py-3 rounded-xl bg-emerald-500 text-slate-950 font-bold hover:bg-emerald-400 transition-colors text-sm"
30
+ class="px-5 py-2.5 rounded-lg bg-emerald-500 text-slate-950 font-semibold hover:bg-emerald-400 transition-colors text-sm"
25
31
  >
26
32
  Subscribe
27
33
  </button>
@@ -1,35 +1,82 @@
1
1
  import type { Post } from '../data/posts.js';
2
2
 
3
- export function PostCard({ post }: { post: Post }) {
3
+ export function PostCard({ post, featured = false }: { post: Post; featured?: boolean }) {
4
+ if (featured) {
5
+ return (
6
+ <article class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-8 hover:border-slate-700 transition-colors mb-10">
7
+ <div class="flex items-center gap-3 mb-4 text-xs font-mono">
8
+ <span class="text-emerald-400 font-semibold px-2.5 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20">
9
+ Featured &bull; {post.category}
10
+ </span>
11
+ <span class="text-slate-500">&bull;</span>
12
+ <span class="text-slate-400">{post.readTime}</span>
13
+ <span class="text-slate-500">&bull;</span>
14
+ <span class="text-slate-400">{post.date}</span>
15
+ </div>
16
+
17
+ <h2 class="text-2xl sm:text-3xl font-extrabold text-white mb-4 leading-snug hover:text-emerald-400 transition-colors">
18
+ <a href={`/blog/${post.slug}`}>
19
+ {post.title}
20
+ </a>
21
+ </h2>
22
+
23
+ <p class="text-slate-300 text-base leading-relaxed mb-6 max-w-3xl">
24
+ {post.summary}
25
+ </p>
26
+
27
+ <div class="pt-6 border-t border-[#1a2333] flex items-center justify-between">
28
+ <div class="flex items-center gap-3">
29
+ <img
30
+ src={post.author.avatar}
31
+ alt={post.author.name}
32
+ class="w-8 h-8 rounded-full object-cover border border-[#1a2333]"
33
+ />
34
+ <div class="text-xs">
35
+ <span class="font-medium text-white block">{post.author.name}</span>
36
+ <span class="text-slate-500">{post.author.role}</span>
37
+ </div>
38
+ </div>
39
+
40
+ <a
41
+ href={`/blog/${post.slug}`}
42
+ class="text-emerald-400 text-xs font-semibold hover:text-emerald-300 transition-colors flex items-center gap-1"
43
+ >
44
+ Read Article &rarr;
45
+ </a>
46
+ </div>
47
+ </article>
48
+ );
49
+ }
50
+
4
51
  return (
5
- <article class="rounded-2xl border border-slate-800/80 bg-slate-900/30 p-6 backdrop-blur-sm hover:border-emerald-500/40 transition-all hover:-translate-y-1 group flex flex-col justify-between">
52
+ <article class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-6 hover:border-slate-700 transition-colors flex flex-col justify-between">
6
53
  <div>
7
- <div class="flex items-center justify-between mb-3 text-xs">
8
- <span class="font-mono text-emerald-400 font-medium px-2.5 py-0.5 rounded-full bg-emerald-500/10 border border-emerald-500/20">
54
+ <div class="flex items-center justify-between mb-3 text-xs font-mono">
55
+ <span class="text-emerald-400 font-semibold px-2 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20">
9
56
  {post.category}
10
57
  </span>
11
- <span class="text-slate-400 font-mono">{post.readTime}</span>
58
+ <span class="text-slate-500">{post.readTime}</span>
12
59
  </div>
13
60
 
14
- <h2 class="text-xl font-bold text-white mb-3 group-hover:text-emerald-400 transition-colors line-clamp-2">
61
+ <h3 class="text-lg font-bold text-white mb-3 hover:text-emerald-400 transition-colors line-clamp-2 leading-snug">
15
62
  <a href={`/blog/${post.slug}`}>
16
63
  {post.title}
17
64
  </a>
18
- </h2>
65
+ </h3>
19
66
 
20
- <p class="text-slate-300 text-sm leading-relaxed mb-6 line-clamp-3">
67
+ <p class="text-slate-400 text-sm leading-relaxed mb-6 line-clamp-3">
21
68
  {post.summary}
22
69
  </p>
23
70
  </div>
24
71
 
25
- <div class="pt-4 border-t border-slate-800/60 flex items-center justify-between">
26
- <div class="flex items-center gap-3">
72
+ <div class="pt-4 border-t border-[#1a2333] flex items-center justify-between">
73
+ <div class="flex items-center gap-2.5">
27
74
  <img
28
75
  src={post.author.avatar}
29
76
  alt={post.author.name}
30
- class="w-7 h-7 rounded-full object-cover ring-1 ring-slate-700"
77
+ class="w-6 h-6 rounded-full object-cover border border-[#1a2333]"
31
78
  />
32
- <div class="text-xs">
79
+ <div class="text-[11px]">
33
80
  <span class="font-medium text-slate-200 block">{post.author.name}</span>
34
81
  <span class="text-slate-500">{post.date}</span>
35
82
  </div>
@@ -37,7 +84,7 @@ export function PostCard({ post }: { post: Post }) {
37
84
 
38
85
  <a
39
86
  href={`/blog/${post.slug}`}
40
- class="text-emerald-400 text-xs font-semibold hover:underline flex items-center gap-1 group-hover:translate-x-0.5 transition-transform"
87
+ class="text-emerald-400 text-xs font-semibold hover:text-emerald-300 transition-colors"
41
88
  >
42
89
  Read &rarr;
43
90
  </a>
@@ -1,19 +1,27 @@
1
1
  @import "tailwindcss";
2
2
 
3
3
  @theme {
4
- --color-brand-50: #ecfdf5;
5
- --color-brand-100: #d1fae5;
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
+ }
@@ -8,11 +8,11 @@ export const metadata = {
8
8
 
9
9
  export default function CartPage() {
10
10
  return (
11
- <div class="min-h-screen flex flex-col justify-between">
11
+ <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
12
12
  <Navbar />
13
13
 
14
14
  <main class="max-w-4xl mx-auto px-6 py-12 flex-1 w-full">
15
- <h1 class="text-3xl font-black text-white mb-8">Your Cart</h1>
15
+ <h1 class="text-3xl font-extrabold text-white mb-8">Order Cart</h1>
16
16
  <CartDrawer />
17
17
  </main>
18
18
 
@@ -4,46 +4,37 @@ import { ProductCard } from '../components/ProductCard.js';
4
4
  import { Footer } from '../components/Footer.js';
5
5
 
6
6
  export const metadata = {
7
- title: 'FrootStore — Curated Workspace & Developer Hardware',
7
+ title: 'FrootStore — Hardware Instruments for Developers',
8
8
  description: 'Precision mechanical keyboards, studio audio, and ergonomic setups.',
9
9
  };
10
10
 
11
11
  export default function StoreHomePage() {
12
12
  return (
13
- <div class="min-h-screen flex flex-col justify-between">
13
+ <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
14
14
  <Navbar />
15
15
 
16
16
  <main class="max-w-6xl mx-auto px-6 py-12 flex-1 w-full">
17
- {/* Hero Banner */}
18
- <div class="rounded-3xl border border-slate-800 bg-gradient-to-r from-slate-900 via-slate-950 to-emerald-950/30 p-8 sm:p-12 mb-12 relative overflow-hidden">
19
- <div class="max-w-2xl relative z-10">
20
- <span class="inline-block px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-xs font-semibold text-emerald-400 mb-4">
21
- Autumn 2026 Collection
22
- </span>
23
- <h1 class="text-4xl sm:text-5xl font-black text-white tracking-tight mb-4">
24
- Engineered for Focus. Crafted for Craft.
25
- </h1>
26
- <p class="text-slate-300 text-base sm:text-lg mb-8 leading-relaxed">
27
- Curated minimal workspace hardware designed to elevate your daily development workflow with tactile precision.
28
- </p>
29
- <div class="flex items-center gap-4">
30
- <a
31
- href="#catalog"
32
- class="px-6 py-3 rounded-xl bg-emerald-500 text-slate-950 font-bold hover:bg-emerald-400 transition-colors shadow-lg shadow-emerald-500/20 text-sm"
33
- >
34
- Browse All Equipment
35
- </a>
36
- <span class="text-xs text-slate-400 font-mono">Free shipping over $100</span>
37
- </div>
17
+ {/* Collection Header */}
18
+ <div class="mb-12 border-b border-[#1a2333] pb-8">
19
+ <div class="text-xs font-mono font-medium text-emerald-400 mb-2 uppercase tracking-wide">
20
+ Curated Instruments
38
21
  </div>
22
+ <h1 class="text-3xl sm:text-5xl font-extrabold text-white tracking-tight mb-3">
23
+ Hardware Engineered for Precision
24
+ </h1>
25
+ <p class="text-slate-400 text-base max-w-2xl leading-relaxed">
26
+ Tactile peripherals and minimal workspace instruments designed to eliminate friction from extended coding sessions.
27
+ </p>
39
28
  </div>
40
29
 
41
- {/* Catalog Section */}
42
- <div id="catalog" class="mb-8 flex items-center justify-between">
43
- <div>
44
- <h2 class="text-2xl font-bold text-white">All Products</h2>
45
- <p class="text-xs text-slate-400">Showing {PRODUCTS.length} curated instruments</p>
46
- </div>
30
+ {/* Catalog Section Header */}
31
+ <div id="catalog" class="mb-6 flex items-center justify-between">
32
+ <h2 class="text-xs font-mono uppercase tracking-wider text-slate-400 font-semibold">
33
+ All Products
34
+ </h2>
35
+ <span class="text-xs font-mono text-slate-500">
36
+ {PRODUCTS.length} instruments available
37
+ </span>
47
38
  </div>
48
39
 
49
40
  <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
@@ -11,19 +11,19 @@ export default function ProductDetailPage({ params }: { params?: { id?: string }
11
11
  const product = PRODUCTS.find((p) => p.id === id) || PRODUCTS[0]!;
12
12
 
13
13
  return (
14
- <div class="min-h-screen flex flex-col justify-between">
14
+ <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
15
15
  <Navbar />
16
16
 
17
17
  <main class="max-w-6xl 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-sm text-slate-400 hover:text-emerald-400 mb-8 transition-colors"
20
+ class="inline-flex items-center gap-2 text-xs font-mono text-slate-400 hover:text-emerald-400 mb-8 transition-colors"
21
21
  >
22
22
  &larr; Back to catalog
23
23
  </a>
24
24
 
25
25
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-start">
26
- <div class="rounded-3xl border border-slate-800 overflow-hidden bg-slate-950 aspect-[4/3]">
26
+ <div class="rounded-xl border border-[#1a2333] overflow-hidden bg-[#0a0f18] aspect-[4/3]">
27
27
  <img
28
28
  src={product.image}
29
29
  alt={product.name}
@@ -32,20 +32,21 @@ export default function ProductDetailPage({ params }: { params?: { id?: string }
32
32
  </div>
33
33
 
34
34
  <div>
35
- <div class="flex items-center gap-2 mb-3">
36
- <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 text-xs font-mono font-medium">
35
+ <div class="flex items-center gap-3 mb-3 text-xs font-mono">
36
+ <span class="px-2.5 py-0.5 rounded bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 font-semibold">
37
37
  {product.category}
38
38
  </span>
39
- <span class="text-amber-400 text-xs font-bold">
40
- &#9733; {product.rating} ({product.reviewsCount} reviews)
39
+ <span class="text-slate-500">&bull;</span>
40
+ <span class="text-slate-300 font-semibold">
41
+ {product.rating.toFixed(1)} / 5.0 ({product.reviewsCount} reviews)
41
42
  </span>
42
43
  </div>
43
44
 
44
- <h1 class="text-3xl sm:text-4xl font-black text-white tracking-tight mb-4">
45
+ <h1 class="text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-4">
45
46
  {product.name}
46
47
  </h1>
47
48
 
48
- <div class="text-3xl font-black text-emerald-400 mb-6 font-mono">
49
+ <div class="text-3xl font-bold text-white mb-6 font-mono">
49
50
  ${product.price.toFixed(2)}
50
51
  </div>
51
52
 
@@ -53,14 +54,14 @@ export default function ProductDetailPage({ params }: { params?: { id?: string }
53
54
  {product.description}
54
55
  </p>
55
56
 
56
- <div class="border-t border-slate-800 pt-6 mb-8">
57
- <h3 class="text-xs uppercase font-mono font-bold text-slate-400 tracking-wider mb-4">
58
- Key Specifications
59
- </h3>
60
- <ul class="grid grid-cols-1 sm:grid-cols-2 gap-3 text-sm text-slate-300">
57
+ <div class="border-t border-[#1a2333] pt-6 mb-8">
58
+ <h2 class="text-xs font-mono uppercase tracking-wider font-semibold text-slate-400 mb-4">
59
+ Engineering Specifications
60
+ </h2>
61
+ <ul class="grid grid-cols-1 sm:grid-cols-2 gap-3 text-sm text-slate-300 font-mono">
61
62
  {product.features.map((f) => (
62
63
  <li key={f} class="flex items-center gap-2">
63
- <span class="text-emerald-400 font-bold">&#10003;</span>
64
+ <span class="text-emerald-400 font-bold">&check;</span>
64
65
  <span>{f}</span>
65
66
  </li>
66
67
  ))}
@@ -70,12 +71,12 @@ export default function ProductDetailPage({ params }: { params?: { id?: string }
70
71
  <div class="flex items-center gap-4">
71
72
  <a
72
73
  href="/cart"
73
- class="flex-1 py-3.5 rounded-xl bg-emerald-500 text-slate-950 font-bold text-center text-sm hover:bg-emerald-400 transition-colors shadow-lg shadow-emerald-500/20"
74
+ class="flex-1 py-3 rounded-lg bg-emerald-500 text-slate-950 font-semibold text-center text-sm hover:bg-emerald-400 transition-colors"
74
75
  >
75
76
  Add to Cart &bull; ${product.price.toFixed(2)}
76
77
  </a>
77
- <span class="text-xs text-slate-500 font-mono">
78
- {product.inStock ? 'In Stock (Ready to Ship)' : 'Backorder'}
78
+ <span class="text-xs text-slate-400 font-mono">
79
+ {product.inStock ? 'In Stock (Ships in 24h)' : 'Backorder'}
79
80
  </span>
80
81
  </div>
81
82
  </div>
@@ -11,23 +11,23 @@ export function CartDrawer() {
11
11
  const total = subtotal + shipping;
12
12
 
13
13
  return (
14
- <div class="rounded-2xl border border-slate-800 bg-slate-900/60 p-6 backdrop-blur-md">
15
- <h2 class="text-lg font-bold text-white mb-4 flex items-center justify-between">
14
+ <div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-6 sm:p-8">
15
+ <h2 class="text-lg font-bold text-white mb-6 flex items-center justify-between border-b border-[#1a2333] pb-4">
16
16
  <span>Order Summary</span>
17
17
  <span class="text-xs font-mono text-emerald-400 font-semibold">{cartItems.length} items</span>
18
18
  </h2>
19
19
 
20
20
  <div class="space-y-4 mb-6">
21
21
  {cartItems.map(({ product, quantity }) => (
22
- <div key={product.id} class="flex items-center gap-3 pb-3 border-b border-slate-800/60">
22
+ <div key={product.id} class="flex items-center gap-4 pb-4 border-b border-[#1a2333]">
23
23
  <img
24
24
  src={product.image}
25
25
  alt={product.name}
26
- class="w-12 h-12 rounded-lg object-cover bg-slate-950"
26
+ class="w-14 h-14 rounded-lg object-cover bg-[#06090f] border border-[#1a2333]"
27
27
  />
28
28
  <div class="flex-1 min-w-0">
29
- <h4 class="text-xs font-semibold text-white truncate">{product.name}</h4>
30
- <div class="text-[11px] text-slate-400">Qty: {quantity} &times; ${product.price}</div>
29
+ <h4 class="text-sm font-semibold text-white truncate">{product.name}</h4>
30
+ <div class="text-xs text-slate-400 font-mono mt-0.5">Qty: {quantity} &times; ${product.price.toFixed(2)}</div>
31
31
  </div>
32
32
  <div class="font-bold text-sm text-white font-mono">
33
33
  ${(product.price * quantity).toFixed(2)}
@@ -36,25 +36,25 @@ export function CartDrawer() {
36
36
  ))}
37
37
  </div>
38
38
 
39
- <div class="space-y-2 text-xs text-slate-400 mb-6 font-mono">
39
+ <div class="space-y-2.5 text-xs text-slate-300 mb-6 font-mono">
40
40
  <div class="flex justify-between">
41
- <span>Subtotal</span>
41
+ <span class="text-slate-400">Subtotal</span>
42
42
  <span class="text-white font-bold">${subtotal.toFixed(2)}</span>
43
43
  </div>
44
44
  <div class="flex justify-between">
45
- <span>Estimated Shipping</span>
45
+ <span class="text-slate-400">Standard Shipping</span>
46
46
  <span class="text-emerald-400 font-semibold">{shipping === 0 ? 'FREE' : `$${shipping.toFixed(2)}`}</span>
47
47
  </div>
48
- <div class="pt-3 border-t border-slate-800 flex justify-between text-sm text-white font-bold">
48
+ <div class="pt-3 border-t border-[#1a2333] flex justify-between text-sm text-white font-bold">
49
49
  <span>Total</span>
50
- <span class="text-emerald-400 text-base font-black">${total.toFixed(2)}</span>
50
+ <span class="text-emerald-400 text-base font-mono font-black">${total.toFixed(2)}</span>
51
51
  </div>
52
52
  </div>
53
53
 
54
54
  <form action="/api/checkout" method="POST">
55
55
  <button
56
56
  type="submit"
57
- class="w-full py-3 rounded-xl bg-emerald-500 text-slate-950 font-bold text-sm hover:bg-emerald-400 transition-colors shadow-lg shadow-emerald-500/20"
57
+ class="w-full py-3 rounded-lg bg-emerald-500 text-slate-950 font-semibold text-sm hover:bg-emerald-400 transition-colors"
58
58
  >
59
59
  Proceed to Checkout &rarr;
60
60
  </button>
@@ -1,14 +1,14 @@
1
1
  export function Footer() {
2
2
  return (
3
- <footer class="border-t border-slate-900 bg-slate-950/60 py-8 text-center text-xs text-slate-500">
4
- <div class="max-w-6xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
3
+ <footer class="border-t border-[#1a2333] bg-[#06090f] py-8 text-xs text-slate-400">
4
+ <div class="max-w-6xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4 font-mono">
5
5
  <div>
6
6
  FrootStore &copy; {new Date().getFullYear()} OrbitNorth LLC. MIT Licensed.
7
7
  </div>
8
8
  <div class="flex items-center gap-6">
9
- <a href="https://github.com/orbitnorth/frootkit" class="hover:text-slate-400 transition-colors">GitHub</a>
10
- <a href="https://frootjs.org" class="hover:text-slate-400 transition-colors">Documentation</a>
11
- <a href="/api/products" class="hover:text-slate-400 transition-colors">Products API</a>
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/products" class="hover:text-white transition-colors">Products API</a>
12
12
  </div>
13
13
  </div>
14
14
  </footer>