veryfront 0.0.36 → 0.0.37

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 (75) hide show
  1. package/dist/ai/index.js +1 -1
  2. package/dist/ai/index.js.map +1 -1
  3. package/dist/cli.js +78 -41
  4. package/dist/components.js +1 -1
  5. package/dist/components.js.map +1 -1
  6. package/dist/config.js +1 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/data.js +1 -1
  9. package/dist/data.js.map +1 -1
  10. package/dist/index.js +2 -5
  11. package/dist/index.js.map +2 -2
  12. package/dist/templates/ai/ai/agents/assistant.ts +20 -0
  13. package/dist/templates/ai/ai/prompts/assistant.ts +14 -0
  14. package/dist/templates/ai/ai/tools/get-weather.ts +29 -0
  15. package/dist/templates/ai/app/api/chat/route.ts +37 -0
  16. package/dist/templates/ai/app/layout.tsx +18 -0
  17. package/dist/templates/ai/app/page.tsx +28 -0
  18. package/dist/templates/ai/tsconfig.json +18 -0
  19. package/dist/templates/ai/veryfront.config.ts +9 -0
  20. package/dist/templates/app/_env.example +16 -0
  21. package/dist/templates/app/app/api/auth/login/route.ts +53 -0
  22. package/dist/templates/app/app/api/auth/logout/route.ts +27 -0
  23. package/dist/templates/app/app/api/auth/me/route.ts +34 -0
  24. package/dist/templates/app/app/api/auth/register/route.ts +42 -0
  25. package/dist/templates/app/app/api/stats/route.ts +21 -0
  26. package/dist/templates/app/app/api/users/route.ts +42 -0
  27. package/dist/templates/app/app/dashboard/page.tsx +29 -0
  28. package/dist/templates/app/app/layout.tsx +45 -0
  29. package/dist/templates/app/app/login/page.tsx +222 -0
  30. package/dist/templates/app/app/page.tsx +15 -0
  31. package/dist/templates/app/components/AuthProvider.tsx +51 -0
  32. package/dist/templates/app/components/DashboardLayout.tsx +142 -0
  33. package/dist/templates/app/components/FeatureGrid.tsx +98 -0
  34. package/dist/templates/app/components/Header.tsx +58 -0
  35. package/dist/templates/app/components/HeroSection.tsx +49 -0
  36. package/dist/templates/app/components/RecentActivity.tsx +98 -0
  37. package/dist/templates/app/components/StatsGrid.tsx +126 -0
  38. package/dist/templates/app/components/Toaster.tsx +113 -0
  39. package/dist/templates/app/lib/auth-client.ts +38 -0
  40. package/dist/templates/app/lib/auth.ts +49 -0
  41. package/dist/templates/app/lib/stats.ts +34 -0
  42. package/dist/templates/app/lib/users.ts +86 -0
  43. package/dist/templates/app/middleware/auth.ts +34 -0
  44. package/dist/templates/app/public/robots.txt +4 -0
  45. package/dist/templates/app/veryfront.config.js +74 -0
  46. package/dist/templates/blog/app/about/page.mdx +14 -0
  47. package/dist/templates/blog/app/archive/page.tsx +42 -0
  48. package/dist/templates/blog/app/blog/[slug]/page.tsx +47 -0
  49. package/dist/templates/blog/app/layout.tsx +54 -0
  50. package/dist/templates/blog/app/page.tsx +13 -0
  51. package/dist/templates/blog/components/BlogPostList.tsx +53 -0
  52. package/dist/templates/blog/components/MDXContent.tsx +26 -0
  53. package/dist/templates/blog/content/posts/hello-world.mdx +29 -0
  54. package/dist/templates/blog/content/posts/markdown-showcase.mdx +105 -0
  55. package/dist/templates/blog/lib/posts.ts +76 -0
  56. package/dist/templates/blog/lib/utils.ts +14 -0
  57. package/dist/templates/blog/public/robots.txt +4 -0
  58. package/dist/templates/blog/styles/globals.css +21 -0
  59. package/dist/templates/blog/veryfront.config.js +39 -0
  60. package/dist/templates/docs/app/docs/api/page.mdx +102 -0
  61. package/dist/templates/docs/app/docs/core-concepts/page.mdx +82 -0
  62. package/dist/templates/docs/app/docs/getting-started/page.mdx +67 -0
  63. package/dist/templates/docs/app/layout.tsx +41 -0
  64. package/dist/templates/docs/app/page.mdx +51 -0
  65. package/dist/templates/docs/components/CodeBlock.tsx +44 -0
  66. package/dist/templates/docs/components/Header.tsx +49 -0
  67. package/dist/templates/docs/components/Sidebar.tsx +68 -0
  68. package/dist/templates/docs/public/robots.txt +4 -0
  69. package/dist/templates/docs/styles/globals.css +48 -0
  70. package/dist/templates/docs/veryfront.config.js +47 -0
  71. package/dist/templates/minimal/app/about/page.mdx +18 -0
  72. package/dist/templates/minimal/app/layout.tsx +20 -0
  73. package/dist/templates/minimal/app/page.tsx +26 -0
  74. package/dist/templates/minimal/veryfront.config.js +29 -0
  75. package/package.json +1 -1
@@ -0,0 +1,222 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { login } from "../../lib/auth-client.ts";
5
+
6
+ // Custom SVG Icons
7
+ function LockIcon({ className }: { className?: string }) {
8
+ return (
9
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
10
+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
11
+ <path d="M7 11V7a5 5 0 0 1 10 0v4"/>
12
+ </svg>
13
+ );
14
+ }
15
+
16
+ function MailIcon({ className }: { className?: string }) {
17
+ return (
18
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
19
+ <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/>
20
+ <polyline points="22,6 12,13 2,6"/>
21
+ </svg>
22
+ );
23
+ }
24
+
25
+ function EyeIcon({ className }: { className?: string }) {
26
+ return (
27
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
28
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
29
+ <circle cx="12" cy="12" r="3"/>
30
+ </svg>
31
+ );
32
+ }
33
+
34
+ function EyeOffIcon({ className }: { className?: string }) {
35
+ return (
36
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
37
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/>
38
+ <line x1="1" y1="1" x2="23" y2="23"/>
39
+ </svg>
40
+ );
41
+ }
42
+
43
+ function SparklesIcon({ className }: { className?: string }) {
44
+ return (
45
+ <svg className={className} viewBox="0 0 24 24" fill="currentColor">
46
+ <path d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09 3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456z"/>
47
+ </svg>
48
+ );
49
+ }
50
+
51
+ export default function LoginPage() {
52
+ const [email, setEmail] = useState("");
53
+ const [password, setPassword] = useState("");
54
+ const [error, setError] = useState("");
55
+ const [loading, setLoading] = useState(false);
56
+ const [showPassword, setShowPassword] = useState(false);
57
+
58
+ const handleSubmit = async (e: React.FormEvent) => {
59
+ e.preventDefault();
60
+ setError("");
61
+ setLoading(true);
62
+
63
+ try {
64
+ await login(email, password);
65
+ window.location.href = "/dashboard";
66
+ } catch (err) {
67
+ setError("Invalid email or password");
68
+ } finally {
69
+ setLoading(false);
70
+ }
71
+ };
72
+
73
+ return (
74
+ <div className="min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900 relative overflow-hidden p-4">
75
+ {/* Background Blobs */}
76
+ <div className="absolute inset-0 overflow-hidden pointer-events-none">
77
+ <div className="absolute -top-[20%] -left-[10%] w-[70%] h-[70%] rounded-full bg-purple-500/20 blur-3xl animate-blob"></div>
78
+ <div className="absolute top-[20%] -right-[10%] w-[70%] h-[70%] rounded-full bg-indigo-500/20 blur-3xl animate-blob animation-delay-2000"></div>
79
+ <div className="absolute -bottom-[20%] left-[20%] w-[70%] h-[70%] rounded-full bg-pink-500/20 blur-3xl animate-blob animation-delay-4000"></div>
80
+ </div>
81
+
82
+ <div className="w-full max-w-md relative z-10">
83
+ {/* Logo & Header */}
84
+ <div className="text-center mb-8">
85
+ <div className="w-16 h-16 mx-auto mb-4 rounded-2xl bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center shadow-lg shadow-indigo-500/20 transform hover:scale-105 transition-transform duration-300">
86
+ <SparklesIcon className="w-8 h-8 text-white" />
87
+ </div>
88
+ <h1 className="text-3xl font-bold text-slate-800 dark:text-white mb-2">Welcome back</h1>
89
+ <p className="text-slate-500 dark:text-slate-400">Sign in to your account to continue</p>
90
+ </div>
91
+
92
+ {/* Login Card */}
93
+ <div className="bg-white/80 dark:bg-slate-800/50 backdrop-blur-xl rounded-3xl shadow-2xl border border-white/20 dark:border-slate-700 p-8">
94
+ <form onSubmit={handleSubmit} className="space-y-6">
95
+ {error && (
96
+ <div className="bg-red-50/50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 text-red-700 dark:text-red-300 p-4 rounded-xl text-sm flex items-center gap-2 animate-shake">
97
+ <svg className="w-5 h-5 flex-shrink-0" viewBox="0 0 24 24" fill="currentColor">
98
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
99
+ </svg>
100
+ {error}
101
+ </div>
102
+ )}
103
+
104
+ {/* Email Field */}
105
+ <div>
106
+ <label htmlFor="email" className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
107
+ Email address
108
+ </label>
109
+ <div className="relative group">
110
+ <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
111
+ <MailIcon className="w-5 h-5 text-slate-400 group-focus-within:text-indigo-500 transition-colors" />
112
+ </div>
113
+ <input
114
+ id="email"
115
+ type="email"
116
+ required
117
+ value={email}
118
+ onChange={(e) => setEmail(e.target.value)}
119
+ placeholder="you@example.com"
120
+ className="block w-full pl-10 pr-4 py-3 bg-slate-50 dark:bg-slate-900/50 border border-slate-200 dark:border-slate-700 rounded-xl text-slate-800 dark:text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 transition-all"
121
+ />
122
+ </div>
123
+ </div>
124
+
125
+ {/* Password Field */}
126
+ <div>
127
+ <div className="flex items-center justify-between mb-2">
128
+ <label htmlFor="password" className="block text-sm font-medium text-slate-700 dark:text-slate-300">
129
+ Password
130
+ </label>
131
+ <a href="/forgot-password" className="text-sm text-indigo-600 dark:text-indigo-400 hover:text-indigo-500 font-medium">
132
+ Forgot password?
133
+ </a>
134
+ </div>
135
+ <div className="relative group">
136
+ <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
137
+ <LockIcon className="w-5 h-5 text-slate-400 group-focus-within:text-indigo-500 transition-colors" />
138
+ </div>
139
+ <input
140
+ id="password"
141
+ type={showPassword ? "text" : "password"}
142
+ required
143
+ value={password}
144
+ onChange={(e) => setPassword(e.target.value)}
145
+ placeholder="Enter your password"
146
+ className="block w-full pl-10 pr-12 py-3 bg-slate-50 dark:bg-slate-900/50 border border-slate-200 dark:border-slate-700 rounded-xl text-slate-800 dark:text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 transition-all"
147
+ />
148
+ <button
149
+ type="button"
150
+ onClick={() => setShowPassword(!showPassword)}
151
+ className="absolute inset-y-0 right-0 pr-3 flex items-center text-slate-400 hover:text-slate-600 dark:hover:text-slate-300 transition-colors"
152
+ >
153
+ {showPassword ? (
154
+ <EyeOffIcon className="w-5 h-5" />
155
+ ) : (
156
+ <EyeIcon className="w-5 h-5" />
157
+ )}
158
+ </button>
159
+ </div>
160
+ </div>
161
+
162
+ {/* Submit Button */}
163
+ <button
164
+ type="submit"
165
+ disabled={loading}
166
+ className="w-full py-3.5 px-4 rounded-xl text-white font-bold bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-lg shadow-indigo-500/25 hover:shadow-xl hover:shadow-indigo-500/30 transform hover:-translate-y-0.5"
167
+ >
168
+ {loading ? (
169
+ <span className="flex items-center justify-center gap-2">
170
+ <svg className="w-5 h-5 animate-spin" viewBox="0 0 24 24" fill="none">
171
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
172
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
173
+ </svg>
174
+ Signing in...
175
+ </span>
176
+ ) : (
177
+ "Sign in"
178
+ )}
179
+ </button>
180
+ </form>
181
+
182
+ {/* Divider */}
183
+ <div className="relative my-8">
184
+ <div className="absolute inset-0 flex items-center">
185
+ <div className="w-full border-t border-slate-200 dark:border-slate-700"></div>
186
+ </div>
187
+ <div className="relative flex justify-center text-sm">
188
+ <span className="px-4 bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm text-slate-500">or continue with</span>
189
+ </div>
190
+ </div>
191
+
192
+ {/* Social Login Buttons */}
193
+ <div className="grid grid-cols-2 gap-4">
194
+ <button className="flex items-center justify-center gap-2 px-4 py-3 border border-slate-200 dark:border-slate-700 rounded-xl text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-all hover:border-slate-300 dark:hover:border-slate-600">
195
+ <svg className="w-5 h-5" viewBox="0 0 24 24">
196
+ <path fill="currentColor" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
197
+ <path fill="currentColor" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
198
+ <path fill="currentColor" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
199
+ <path fill="currentColor" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
200
+ </svg>
201
+ Google
202
+ </button>
203
+ <button className="flex items-center justify-center gap-2 px-4 py-3 border border-slate-200 dark:border-slate-700 rounded-xl text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-all hover:border-slate-300 dark:hover:border-slate-600">
204
+ <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
205
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
206
+ </svg>
207
+ GitHub
208
+ </button>
209
+ </div>
210
+ </div>
211
+
212
+ {/* Sign Up Link */}
213
+ <p className="mt-8 text-center text-slate-600 dark:text-slate-400">
214
+ Don't have an account?{" "}
215
+ <a href="/register" className="font-bold text-indigo-600 dark:text-indigo-400 hover:text-indigo-500 transition-colors">
216
+ Sign up for free
217
+ </a>
218
+ </p>
219
+ </div>
220
+ </div>
221
+ );
222
+ }
@@ -0,0 +1,15 @@
1
+ import { Header } from "../components/Header.tsx";
2
+ import { HeroSection } from "../components/HeroSection.tsx";
3
+ import { FeatureGrid } from "../components/FeatureGrid.tsx";
4
+
5
+ export default function HomePage() {
6
+ return (
7
+ <>
8
+ <Header />
9
+ <main>
10
+ <HeroSection />
11
+ <FeatureGrid />
12
+ </main>
13
+ </>
14
+ );
15
+ }
@@ -0,0 +1,51 @@
1
+ 'use client';
2
+
3
+ import React, { createContext, useContext, useState, useEffect } from "react";
4
+ import { logout as logoutUser } from "../lib/auth-client.ts";
5
+
6
+ interface User {
7
+ id: string;
8
+ email: string;
9
+ name: string;
10
+ role: string;
11
+ }
12
+
13
+ interface AuthContextType {
14
+ user: User | null;
15
+ loading: boolean;
16
+ logout: () => void;
17
+ }
18
+
19
+ const AuthContext = createContext<AuthContextType>({
20
+ user: null,
21
+ loading: true,
22
+ logout: () => {},
23
+ });
24
+
25
+ export function AuthProvider({ children }: { children: React.ReactNode }) {
26
+ const [user, setUser] = useState<User | null>(null);
27
+ const [loading, setLoading] = useState(true);
28
+
29
+ useEffect(() => {
30
+ // Check if user is logged in
31
+ fetch("/api/auth/me")
32
+ .then(res => res.ok ? res.json() : null)
33
+ .then(data => {
34
+ if (data?.user) setUser(data.user);
35
+ })
36
+ .finally(() => setLoading(false));
37
+ }, []);
38
+
39
+ const logout = () => {
40
+ logoutUser();
41
+ setUser(null);
42
+ };
43
+
44
+ return (
45
+ <AuthContext.Provider value={{ user, loading, logout }}>
46
+ {children}
47
+ </AuthContext.Provider>
48
+ );
49
+ }
50
+
51
+ export const useAuth = () => useContext(AuthContext);
@@ -0,0 +1,142 @@
1
+ 'use client';
2
+
3
+ import * as React from "react";
4
+ import { useAuth } from "./AuthProvider.tsx";
5
+
6
+ // Navigation Icons
7
+ function HomeIcon({ className }: { className?: string }) {
8
+ return (
9
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
10
+ <path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
11
+ <polyline points="9 22 9 12 15 12 15 22"/>
12
+ </svg>
13
+ );
14
+ }
15
+
16
+ function UsersIcon({ className }: { className?: string }) {
17
+ return (
18
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
19
+ <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
20
+ <circle cx="9" cy="7" r="4"/>
21
+ <path d="M22 21v-2a4 4 0 0 0-3-3.87"/>
22
+ <path d="M16 3.13a4 4 0 0 1 0 7.75"/>
23
+ </svg>
24
+ );
25
+ }
26
+
27
+ function ChartIcon({ className }: { className?: string }) {
28
+ return (
29
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
30
+ <line x1="18" y1="20" x2="18" y2="10"/>
31
+ <line x1="12" y1="20" x2="12" y2="4"/>
32
+ <line x1="6" y1="20" x2="6" y2="14"/>
33
+ </svg>
34
+ );
35
+ }
36
+
37
+ function SettingsIcon({ className }: { className?: string }) {
38
+ return (
39
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
40
+ <circle cx="12" cy="12" r="3"/>
41
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
42
+ </svg>
43
+ );
44
+ }
45
+
46
+ function LogoutIcon({ className }: { className?: string }) {
47
+ return (
48
+ <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
49
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
50
+ <polyline points="16 17 21 12 16 7"/>
51
+ <line x1="21" y1="12" x2="9" y2="12"/>
52
+ </svg>
53
+ );
54
+ }
55
+
56
+ function SparklesIcon({ className }: { className?: string }) {
57
+ return (
58
+ <svg className={className} viewBox="0 0 24 24" fill="currentColor">
59
+ <path d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z"/>
60
+ </svg>
61
+ );
62
+ }
63
+
64
+ const navigation = [
65
+ { name: "Overview", href: "/dashboard", Icon: HomeIcon },
66
+ { name: "Users", href: "/dashboard/users", Icon: UsersIcon },
67
+ { name: "Analytics", href: "/dashboard/analytics", Icon: ChartIcon },
68
+ { name: "Settings", href: "/dashboard/settings", Icon: SettingsIcon },
69
+ ];
70
+
71
+ export function DashboardLayout({ children }: { children: React.ReactNode }) {
72
+ const { user, logout } = useAuth();
73
+
74
+ return (
75
+ <div className="min-h-screen bg-slate-50 dark:bg-slate-900 relative overflow-hidden">
76
+ {/* Background Blobs */}
77
+ <div className="absolute inset-0 overflow-hidden pointer-events-none">
78
+ <div className="absolute -top-[20%] -left-[10%] w-[70%] h-[70%] rounded-full bg-purple-500/10 blur-3xl animate-blob"></div>
79
+ <div className="absolute top-[20%] -right-[10%] w-[70%] h-[70%] rounded-full bg-indigo-500/10 blur-3xl animate-blob animation-delay-2000"></div>
80
+ </div>
81
+
82
+ <div className="flex h-screen relative z-10">
83
+ {/* Sidebar */}
84
+ <div className="w-72 bg-white/80 dark:bg-slate-800/80 backdrop-blur-xl border-r border-slate-200/50 dark:border-slate-700/50 flex flex-col shadow-2xl">
85
+ {/* Logo */}
86
+ <div className="p-8 border-b border-slate-200/50 dark:border-slate-700/50">
87
+ <div className="flex items-center gap-4">
88
+ <div className="w-12 h-12 rounded-2xl bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center shadow-lg shadow-indigo-500/20">
89
+ <SparklesIcon className="w-6 h-6 text-white" />
90
+ </div>
91
+ <div>
92
+ <h1 className="text-xl font-bold text-slate-900 dark:text-white tracking-tight">My App</h1>
93
+ <p className="text-xs font-medium text-slate-500 dark:text-slate-400">Dashboard</p>
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ {/* Navigation */}
99
+ <nav className="flex-1 px-4 py-8 space-y-2">
100
+ {navigation.map((item) => (
101
+ <a
102
+ key={item.name}
103
+ href={item.href}
104
+ className="flex items-center gap-3 px-4 py-3.5 text-sm font-medium rounded-xl text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-700/50 hover:text-indigo-600 dark:hover:text-indigo-400 transition-all group"
105
+ >
106
+ <item.Icon className="w-5 h-5 group-hover:text-indigo-500 transition-colors" />
107
+ {item.name}
108
+ </a>
109
+ ))}
110
+ </nav>
111
+
112
+ {/* User Profile */}
113
+ <div className="p-4 border-t border-slate-200/50 dark:border-slate-700/50 bg-slate-50/50 dark:bg-slate-900/50">
114
+ <div className="flex items-center gap-3 p-3 rounded-xl bg-white dark:bg-slate-800 shadow-sm border border-slate-200/50 dark:border-slate-700/50">
115
+ <div className="w-10 h-10 rounded-full bg-gradient-to-br from-indigo-400 to-purple-500 flex items-center justify-center text-white font-bold shadow-md">
116
+ {user?.name?.[0]?.toUpperCase() || "U"}
117
+ </div>
118
+ <div className="flex-1 min-w-0">
119
+ <p className="text-sm font-bold text-slate-900 dark:text-white truncate">{user?.name}</p>
120
+ <p className="text-xs text-slate-500 dark:text-slate-400 truncate">{user?.email}</p>
121
+ </div>
122
+ <button
123
+ onClick={logout}
124
+ className="p-2 rounded-lg text-slate-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 transition-all"
125
+ title="Logout"
126
+ >
127
+ <LogoutIcon className="w-5 h-5" />
128
+ </button>
129
+ </div>
130
+ </div>
131
+ </div>
132
+
133
+ {/* Main content */}
134
+ <div className="flex-1 overflow-y-auto">
135
+ <main className="p-8 lg:p-12 max-w-7xl mx-auto">
136
+ {children}
137
+ </main>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ );
142
+ }
@@ -0,0 +1,98 @@
1
+ const features = [
2
+ {
3
+ title: "Authentication",
4
+ description: "Secure user authentication with sessions and JWT tokens",
5
+ icon: (
6
+ <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
7
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} 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" />
8
+ </svg>
9
+ ),
10
+ color: "bg-blue-500",
11
+ },
12
+ {
13
+ title: "API Routes",
14
+ description: "Full-featured API with middleware and validation",
15
+ icon: (
16
+ <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
17
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
18
+ </svg>
19
+ ),
20
+ color: "bg-purple-500",
21
+ },
22
+ {
23
+ title: "Database Ready",
24
+ description: "Easy to connect any database with our data layer",
25
+ icon: (
26
+ <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
27
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
28
+ </svg>
29
+ ),
30
+ color: "bg-pink-500",
31
+ },
32
+ {
33
+ title: "Type Safe",
34
+ description: "Full TypeScript support with runtime validation",
35
+ icon: (
36
+ <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
37
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
38
+ </svg>
39
+ ),
40
+ color: "bg-green-500",
41
+ },
42
+ {
43
+ title: "Modern UI",
44
+ description: "Beautiful components built with Tailwind CSS",
45
+ icon: (
46
+ <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
47
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" />
48
+ </svg>
49
+ ),
50
+ color: "bg-orange-500",
51
+ },
52
+ {
53
+ title: "Production Ready",
54
+ description: "Security, caching, and performance optimized",
55
+ icon: (
56
+ <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
57
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19.428 15.428a2 2 0 00-1.022-.547l-2.384-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
58
+ </svg>
59
+ ),
60
+ color: "bg-teal-500",
61
+ },
62
+ ];
63
+
64
+ export function FeatureGrid() {
65
+ return (
66
+ <section className="py-24 bg-slate-50 dark:bg-slate-900">
67
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
68
+ <div className="text-center mb-16">
69
+ <h2 className="text-3xl md:text-4xl font-bold text-slate-900 dark:text-white mb-4">
70
+ Everything You Need
71
+ </h2>
72
+ <p className="text-xl text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
73
+ Start with a solid foundation and build from there. We've handled the boring stuff so you can focus on your product.
74
+ </p>
75
+ </div>
76
+
77
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
78
+ {features.map((feature) => (
79
+ <div
80
+ key={feature.title}
81
+ className="group bg-white dark:bg-slate-800 rounded-2xl p-8 shadow-sm hover:shadow-xl transition-all duration-300 border border-slate-100 dark:border-slate-700"
82
+ >
83
+ <div className={`w-12 h-12 ${feature.color} rounded-xl flex items-center justify-center text-white mb-6 transform group-hover:scale-110 transition-transform duration-300 shadow-lg`}>
84
+ {feature.icon}
85
+ </div>
86
+ <h3 className="text-xl font-bold text-slate-900 dark:text-white mb-3">
87
+ {feature.title}
88
+ </h3>
89
+ <p className="text-slate-600 dark:text-slate-400 leading-relaxed">
90
+ {feature.description}
91
+ </p>
92
+ </div>
93
+ ))}
94
+ </div>
95
+ </div>
96
+ </section>
97
+ );
98
+ }
@@ -0,0 +1,58 @@
1
+ 'use client';
2
+
3
+ import * as React from "react";
4
+ import { useAuth } from "./AuthProvider.tsx";
5
+
6
+ export function Header() {
7
+ const { user, logout } = useAuth();
8
+
9
+ return (
10
+ <header className="bg-white shadow-sm">
11
+ <nav className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
12
+ <div className="flex justify-between h-16">
13
+ <div className="flex items-center">
14
+ <a href="/" className="text-xl font-bold text-indigo-600">
15
+ My App
16
+ </a>
17
+ </div>
18
+
19
+ <div className="flex items-center space-x-4">
20
+ {user ? (
21
+ <>
22
+ <a
23
+ href="/dashboard"
24
+ className="text-gray-700 hover:text-gray-900"
25
+ >
26
+ Dashboard
27
+ </a>
28
+ <span className="text-gray-500">|</span>
29
+ <span className="text-gray-700">{user.name}</span>
30
+ <button
31
+ onClick={logout}
32
+ className="text-gray-700 hover:text-gray-900"
33
+ >
34
+ Sign out
35
+ </button>
36
+ </>
37
+ ) : (
38
+ <>
39
+ <a
40
+ href="/login"
41
+ className="text-gray-700 hover:text-gray-900"
42
+ >
43
+ Sign in
44
+ </a>
45
+ <a
46
+ href="/register"
47
+ className="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700"
48
+ >
49
+ Get started
50
+ </a>
51
+ </>
52
+ )}
53
+ </div>
54
+ </div>
55
+ </nav>
56
+ </header>
57
+ );
58
+ }
@@ -0,0 +1,49 @@
1
+ export function HeroSection() {
2
+ return (
3
+ <section className="relative overflow-hidden bg-slate-900 text-white">
4
+ {/* Background Pattern */}
5
+ <div className="absolute inset-0 z-0 opacity-20">
6
+ <div className="absolute top-0 -left-4 w-72 h-72 bg-purple-500 rounded-full mix-blend-multiply filter blur-xl animate-blob"></div>
7
+ <div className="absolute top-0 -right-4 w-72 h-72 bg-indigo-500 rounded-full mix-blend-multiply filter blur-xl animate-blob animation-delay-2000"></div>
8
+ <div className="absolute -bottom-8 left-20 w-72 h-72 bg-pink-500 rounded-full mix-blend-multiply filter blur-xl animate-blob animation-delay-4000"></div>
9
+ </div>
10
+
11
+ <div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-32">
12
+ <div className="text-center max-w-3xl mx-auto">
13
+ <div className="inline-flex items-center px-4 py-2 rounded-full border border-indigo-500/30 bg-indigo-500/10 text-indigo-300 mb-8 backdrop-blur-sm">
14
+ <span className="flex h-2 w-2 rounded-full bg-indigo-400 mr-2"></span>
15
+ v1.0 is now available
16
+ </div>
17
+
18
+ <h1 className="text-5xl md:text-7xl font-extrabold tracking-tight mb-8 bg-clip-text text-transparent bg-gradient-to-r from-white via-indigo-200 to-indigo-400">
19
+ Build Something <br />
20
+ <span className="text-indigo-400">Extraordinary</span>
21
+ </h1>
22
+
23
+ <p className="text-xl text-slate-300 mb-10 leading-relaxed">
24
+ A modern full-stack application template with authentication,
25
+ API routes, and a beautiful UI. Start your next big idea with a solid foundation.
26
+ </p>
27
+
28
+ <div className="flex flex-col sm:flex-row gap-4 justify-center">
29
+ <a
30
+ href="/register"
31
+ className="px-8 py-4 bg-indigo-600 text-white rounded-xl font-bold hover:bg-indigo-500 transition-all transform hover:scale-105 shadow-lg shadow-indigo-500/25"
32
+ >
33
+ Get Started Free
34
+ </a>
35
+ <a
36
+ href="/docs"
37
+ className="px-8 py-4 bg-white/10 text-white border border-white/20 rounded-xl font-bold hover:bg-white/20 transition-all backdrop-blur-sm"
38
+ >
39
+ Read Documentation
40
+ </a>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ {/* Bottom fade */}
46
+ <div className="absolute bottom-0 left-0 right-0 h-24 bg-gradient-to-t from-slate-50 dark:from-slate-900 to-transparent"></div>
47
+ </section>
48
+ );
49
+ }