metabinaries 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +43 -0
- package/index.js +164 -0
- package/package.json +32 -0
- package/src/constants.js +62 -0
- package/src/templates/app.js +527 -0
- package/src/templates/configs.js +303 -0
- package/src/templates/core.js +328 -0
- package/src/templates/folder-structure.js +21 -0
- package/src/templates/layout.js +279 -0
- package/src/templates/misc.js +277 -0
- package/src/templates/packages.js +42 -0
- package/src/templates/ui-2.js +585 -0
- package/src/templates/ui-3.js +606 -0
- package/src/templates/ui-4.js +615 -0
- package/src/templates/ui.js +777 -0
- package/src/utils.js +38 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
// App Routes & Layouts Templates
|
|
2
|
+
export const appTemplates = {
|
|
3
|
+
'app/layout.tsx': `export default function RootLayout({
|
|
4
|
+
children,
|
|
5
|
+
}: {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}) {
|
|
8
|
+
return (
|
|
9
|
+
<html suppressHydrationWarning>
|
|
10
|
+
<body suppressHydrationWarning>
|
|
11
|
+
{children}
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
14
|
+
);
|
|
15
|
+
}`,
|
|
16
|
+
|
|
17
|
+
'app/not-found.tsx': `import { Button } from '@/components/ui/button';
|
|
18
|
+
import {
|
|
19
|
+
Empty,
|
|
20
|
+
EmptyContent,
|
|
21
|
+
EmptyDescription,
|
|
22
|
+
EmptyHeader,
|
|
23
|
+
EmptyTitle,
|
|
24
|
+
} from '@/components/ui/empty';
|
|
25
|
+
import { Compass, Home } from 'lucide-react';
|
|
26
|
+
import { useLocale } from 'next-intl';
|
|
27
|
+
import Link from 'next/link';
|
|
28
|
+
|
|
29
|
+
export default function NotFound() {
|
|
30
|
+
const locale = useLocale();
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div className='flex w-full items-center justify-center'>
|
|
34
|
+
<div className='flex h-screen items-center border-x'>
|
|
35
|
+
<div>
|
|
36
|
+
<div className='absolute inset-x-0 h-px bg-border' />
|
|
37
|
+
<Empty>
|
|
38
|
+
<EmptyHeader>
|
|
39
|
+
<EmptyTitle className='font-black font-mono text-8xl'>
|
|
40
|
+
404
|
|
41
|
+
</EmptyTitle>
|
|
42
|
+
<EmptyDescription className='text-nowrap'>
|
|
43
|
+
The page you're looking for might have been <br />
|
|
44
|
+
moved or doesn't exist.
|
|
45
|
+
</EmptyDescription>
|
|
46
|
+
</EmptyHeader>
|
|
47
|
+
<EmptyContent>
|
|
48
|
+
<div className='flex gap-2'>
|
|
49
|
+
<Button asChild>
|
|
50
|
+
<Link href={\`/\${locale}\`}>
|
|
51
|
+
<Home /> Go Home
|
|
52
|
+
</Link>
|
|
53
|
+
</Button>
|
|
54
|
+
|
|
55
|
+
<Button asChild variant='outline'>
|
|
56
|
+
<Link href={\`/\${locale}\`}>
|
|
57
|
+
<Compass /> Explore
|
|
58
|
+
</Link>
|
|
59
|
+
</Button>
|
|
60
|
+
</div>
|
|
61
|
+
</EmptyContent>
|
|
62
|
+
</Empty>
|
|
63
|
+
<div className='absolute inset-x-0 h-px bg-border' />
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}`,
|
|
69
|
+
|
|
70
|
+
'app/robots.ts': `import { MetadataRoute } from 'next';
|
|
71
|
+
|
|
72
|
+
export default function robots(): MetadataRoute.Robots {
|
|
73
|
+
const siteUrl =
|
|
74
|
+
process.env.NEXT_PUBLIC_SITE_URL || 'https://next-admin-kit-nine.dev';
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
rules: [
|
|
78
|
+
{
|
|
79
|
+
userAgent: '*',
|
|
80
|
+
allow: '/',
|
|
81
|
+
disallow: [
|
|
82
|
+
'/api/',
|
|
83
|
+
'/admin/',
|
|
84
|
+
'/login/',
|
|
85
|
+
'/sign-up/',
|
|
86
|
+
'/_next/',
|
|
87
|
+
'/static/',
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
userAgent: 'Googlebot',
|
|
92
|
+
allow: '/',
|
|
93
|
+
disallow: ['/api/', '/admin/', '/login/', '/sign-up/'],
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
sitemap: \`\${siteUrl}/sitemap.xml\`,
|
|
97
|
+
};
|
|
98
|
+
}`,
|
|
99
|
+
|
|
100
|
+
'app/[locale]/layout.tsx': `import './globals.css';
|
|
101
|
+
import { NextIntlClientProvider, hasLocale } from 'next-intl';
|
|
102
|
+
import { notFound } from 'next/navigation';
|
|
103
|
+
import { routing } from '@/i18n/routing';
|
|
104
|
+
import { Toaster } from '@/components/ui/sonner';
|
|
105
|
+
import { Providers } from '@/components/layout/providers';
|
|
106
|
+
import LayoutWrapper from './_layout-wrapper';
|
|
107
|
+
|
|
108
|
+
export default async function LocaleLayout({
|
|
109
|
+
children,
|
|
110
|
+
params,
|
|
111
|
+
}: {
|
|
112
|
+
children: React.ReactNode;
|
|
113
|
+
params: Promise<{ locale: string }>;
|
|
114
|
+
}) {
|
|
115
|
+
// Ensure that the incoming \`locale\` is valid
|
|
116
|
+
const { locale } = await params;
|
|
117
|
+
if (!hasLocale(routing.locales, locale)) {
|
|
118
|
+
notFound();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<html
|
|
123
|
+
lang={locale}
|
|
124
|
+
dir={locale === 'ar' ? 'rtl' : 'ltr'}
|
|
125
|
+
suppressHydrationWarning
|
|
126
|
+
>
|
|
127
|
+
<body suppressHydrationWarning>
|
|
128
|
+
<NextIntlClientProvider locale={locale}>
|
|
129
|
+
<Providers>
|
|
130
|
+
<Toaster
|
|
131
|
+
position='bottom-right'
|
|
132
|
+
expand={true}
|
|
133
|
+
richColors={true}
|
|
134
|
+
closeButton={true}
|
|
135
|
+
/>
|
|
136
|
+
<LayoutWrapper>{children}</LayoutWrapper>
|
|
137
|
+
</Providers>
|
|
138
|
+
</NextIntlClientProvider>
|
|
139
|
+
</body>
|
|
140
|
+
</html>
|
|
141
|
+
);
|
|
142
|
+
}`,
|
|
143
|
+
|
|
144
|
+
'app/[locale]/sitemap.ts': `import { MetadataRoute } from 'next';
|
|
145
|
+
|
|
146
|
+
export default function sitemap(): MetadataRoute.Sitemap {
|
|
147
|
+
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000';
|
|
148
|
+
const locales = ['en', 'ar'];
|
|
149
|
+
|
|
150
|
+
return locales.flatMap((locale) => [
|
|
151
|
+
{
|
|
152
|
+
url: \`\${siteUrl}/\${locale}\`,
|
|
153
|
+
lastModified: new Date(),
|
|
154
|
+
changeFrequency: 'daily' as const,
|
|
155
|
+
priority: 1,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
url: \`\${siteUrl}/\${locale}/login\`,
|
|
159
|
+
lastModified: new Date(),
|
|
160
|
+
changeFrequency: 'monthly' as const,
|
|
161
|
+
priority: 0.8,
|
|
162
|
+
},
|
|
163
|
+
]);
|
|
164
|
+
}`,
|
|
165
|
+
|
|
166
|
+
'app/[locale]/loading.tsx': `export default function Loading() {
|
|
167
|
+
return (
|
|
168
|
+
<div className="flex h-screen w-full items-center justify-center bg-background">
|
|
169
|
+
<div className="flex flex-col items-center gap-4">
|
|
170
|
+
<div className="h-12 w-12 animate-spin rounded-full border-4 border-primary border-t-transparent"></div>
|
|
171
|
+
<p className="text-sm font-medium text-muted-foreground animate-pulse">
|
|
172
|
+
Loading MetaBinaries...
|
|
173
|
+
</p>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
}`,
|
|
178
|
+
|
|
179
|
+
'app/[locale]/error.tsx': `'use client';
|
|
180
|
+
|
|
181
|
+
import { useEffect } from 'react';
|
|
182
|
+
import { Button } from '@/components/ui/button';
|
|
183
|
+
|
|
184
|
+
export default function Error({
|
|
185
|
+
error,
|
|
186
|
+
reset,
|
|
187
|
+
}: {
|
|
188
|
+
error: Error & { digest?: string };
|
|
189
|
+
reset: () => void;
|
|
190
|
+
}) {
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
console.error(error);
|
|
193
|
+
}, [error]);
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<div className="flex h-screen w-full flex-col items-center justify-center bg-background p-4 text-center">
|
|
197
|
+
<div className="space-y-4">
|
|
198
|
+
<h2 className="text-2xl font-bold text-destructive">Something went wrong!</h2>
|
|
199
|
+
<p className="text-muted-foreground max-w-md">
|
|
200
|
+
An unexpected error occurred. Our team has been notified.
|
|
201
|
+
</p>
|
|
202
|
+
<div className="flex gap-4 justify-center">
|
|
203
|
+
<Button onClick={() => reset()} variant="default">
|
|
204
|
+
Try again
|
|
205
|
+
</Button>
|
|
206
|
+
<Button onClick={() => window.location.href = '/'} variant="outline">
|
|
207
|
+
Go Home
|
|
208
|
+
</Button>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
);
|
|
213
|
+
}`,
|
|
214
|
+
|
|
215
|
+
'app/[locale]/page.tsx': `'use client';
|
|
216
|
+
|
|
217
|
+
import { motion } from 'framer-motion';
|
|
218
|
+
import { Button } from '@/components/ui/button';
|
|
219
|
+
import { Badge } from '@/components/ui/badge';
|
|
220
|
+
import { Card } from '@/components/ui/card';
|
|
221
|
+
import { Rocket, Shield, Globe, Zap, ArrowRight } from 'lucide-react';
|
|
222
|
+
import { Link } from '@/i18n/navigation';
|
|
223
|
+
|
|
224
|
+
export default function HomePage() {
|
|
225
|
+
return (
|
|
226
|
+
<div className='relative min-h-screen overflow-hidden bg-slate-950 font-sans selection:bg-blue-500/30'>
|
|
227
|
+
{/* Background Orbs */}
|
|
228
|
+
<div className='fixed inset-0 overflow-hidden pointer-events-none'>
|
|
229
|
+
<div className='absolute top-[-10%] left-[-10%] w-[40%] h-[40%] rounded-full bg-blue-600/10 blur-[120px]' />
|
|
230
|
+
<div className='absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] rounded-full bg-indigo-600/10 blur-[120px]' />
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
{/* Main Content */}
|
|
234
|
+
<div className='relative z-10 container mx-auto px-6 py-12 md:py-24 flex flex-col items-center'>
|
|
235
|
+
<motion.div
|
|
236
|
+
initial={{ opacity: 0, y: 20 }}
|
|
237
|
+
animate={{ opacity: 1, y: 0 }}
|
|
238
|
+
transition={{ duration: 0.6 }}
|
|
239
|
+
className='flex flex-col items-center'
|
|
240
|
+
>
|
|
241
|
+
<Badge
|
|
242
|
+
variant='outline'
|
|
243
|
+
className='mb-6 py-1 px-4 border-slate-800 bg-slate-900/50 text-blue-400 backdrop-blur-sm'
|
|
244
|
+
>
|
|
245
|
+
✨ Developed by MetaBinaries Technical Team
|
|
246
|
+
</Badge>
|
|
247
|
+
|
|
248
|
+
<h1 className='text-center'>
|
|
249
|
+
<span className='block text-5xl md:text-7xl font-bold tracking-tight text-white mb-2'>
|
|
250
|
+
MetaBinaries
|
|
251
|
+
</span>
|
|
252
|
+
<span className='block text-4xl md:text-6xl font-bold tracking-tight bg-gradient-to-r from-blue-400 via-indigo-400 to-purple-400 bg-clip-text text-transparent'>
|
|
253
|
+
Project Initialized
|
|
254
|
+
</span>
|
|
255
|
+
</h1>
|
|
256
|
+
|
|
257
|
+
<p className='mt-8 text-lg md:text-xl text-slate-400 text-center max-w-2xl leading-relaxed'>
|
|
258
|
+
Your enterprise-grade CRM workspace is ready for development.
|
|
259
|
+
Experience a high-performance, feature-driven architecture built for
|
|
260
|
+
scale.
|
|
261
|
+
</p>
|
|
262
|
+
|
|
263
|
+
<div className='mt-12 flex flex-col sm:flex-row gap-4'>
|
|
264
|
+
<Button
|
|
265
|
+
size='lg'
|
|
266
|
+
asChild
|
|
267
|
+
className='bg-blue-600 hover:bg-blue-700 text-white rounded-full px-8 h-12 shadow-lg shadow-blue-600/20'
|
|
268
|
+
>
|
|
269
|
+
<Link href='/login' className='flex items-center gap-2'>
|
|
270
|
+
Enter Workspace <ArrowRight className='size-4' />
|
|
271
|
+
</Link>
|
|
272
|
+
</Button>
|
|
273
|
+
<Button
|
|
274
|
+
variant='outline'
|
|
275
|
+
size='lg'
|
|
276
|
+
asChild
|
|
277
|
+
className='border-slate-800 bg-slate-900/50 hover:bg-slate-800 text-slate-300 rounded-full px-8 h-12 backdrop-blur-sm'
|
|
278
|
+
>
|
|
279
|
+
<Link href='/sign-up' className='flex items-center gap-2'>
|
|
280
|
+
Create Account
|
|
281
|
+
</Link>
|
|
282
|
+
</Button>
|
|
283
|
+
</div>
|
|
284
|
+
</motion.div>
|
|
285
|
+
|
|
286
|
+
{/* Feature Grid */}
|
|
287
|
+
<motion.div
|
|
288
|
+
initial={{ opacity: 0, y: 40 }}
|
|
289
|
+
animate={{ opacity: 1, y: 0 }}
|
|
290
|
+
transition={{ duration: 0.8, delay: 0.2 }}
|
|
291
|
+
className='mt-24 grid grid-cols-1 md:grid-cols-3 gap-6 w-full max-w-5xl'
|
|
292
|
+
>
|
|
293
|
+
<FeatureCard
|
|
294
|
+
icon={<Zap className='text-yellow-400' />}
|
|
295
|
+
title='Fast Development'
|
|
296
|
+
description='Pre-configured with Redux Toolkit, Axios, and Zod for rapid feature building.'
|
|
297
|
+
/>
|
|
298
|
+
<FeatureCard
|
|
299
|
+
icon={<Shield className='text-green-400' />}
|
|
300
|
+
title='Secure by Design'
|
|
301
|
+
description='Built-in AuthGuards, secure API interceptors, and robust rate limiting.'
|
|
302
|
+
/>
|
|
303
|
+
<FeatureCard
|
|
304
|
+
icon={<Globe className='text-blue-400' />}
|
|
305
|
+
title='Full i18n'
|
|
306
|
+
description='Deep integration with next-intl for English (LTR) and Arabic (RTL) support.'
|
|
307
|
+
/>
|
|
308
|
+
</motion.div>
|
|
309
|
+
|
|
310
|
+
{/* Footer info */}
|
|
311
|
+
<motion.div
|
|
312
|
+
initial={{ opacity: 0 }}
|
|
313
|
+
animate={{ opacity: 1 }}
|
|
314
|
+
transition={{ delay: 1 }}
|
|
315
|
+
className='mt-24 text-slate-500 text-sm flex flex-col items-center gap-4'
|
|
316
|
+
>
|
|
317
|
+
<div className='flex items-center gap-6'>
|
|
318
|
+
<span className='flex items-center gap-2'>
|
|
319
|
+
<span className='size-2 rounded-full bg-green-500 animate-pulse' />
|
|
320
|
+
System Online
|
|
321
|
+
</span>
|
|
322
|
+
<span className='w-px h-4 bg-slate-800' />
|
|
323
|
+
<span>v1.0.0</span>
|
|
324
|
+
</div>
|
|
325
|
+
<p>© 2026 MetaBinaries Technical Team. All rights reserved.</p>
|
|
326
|
+
</motion.div>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function FeatureCard({
|
|
333
|
+
icon,
|
|
334
|
+
title,
|
|
335
|
+
description,
|
|
336
|
+
}: {
|
|
337
|
+
icon: React.ReactNode;
|
|
338
|
+
title: string;
|
|
339
|
+
description: string;
|
|
340
|
+
}) {
|
|
341
|
+
return (
|
|
342
|
+
<Card className='p-6 bg-slate-900/40 border-slate-800/80 backdrop-blur-sm hover:border-slate-700 transition-colors group'>
|
|
343
|
+
<div className='size-10 rounded-full bg-slate-800 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform'>
|
|
344
|
+
{icon}
|
|
345
|
+
</div>
|
|
346
|
+
<h3 className='text-lg font-semibold text-white mb-2'>{title}</h3>
|
|
347
|
+
<p className='text-slate-400 text-sm leading-relaxed'>{description}</p>
|
|
348
|
+
</Card>
|
|
349
|
+
);
|
|
350
|
+
}`,
|
|
351
|
+
|
|
352
|
+
'app/[locale]/_layout-wrapper.tsx': `'use client';
|
|
353
|
+
|
|
354
|
+
export default function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
|
355
|
+
return <>{children}</>;
|
|
356
|
+
}`,
|
|
357
|
+
|
|
358
|
+
'app/[locale]/globals.css': `@import 'tailwindcss';
|
|
359
|
+
|
|
360
|
+
@theme {
|
|
361
|
+
--color-border: hsl(var(--border));
|
|
362
|
+
--color-input: hsl(var(--input));
|
|
363
|
+
--color-ring: hsl(var(--ring));
|
|
364
|
+
--color-background: hsl(var(--background));
|
|
365
|
+
--color-foreground: hsl(var(--foreground));
|
|
366
|
+
|
|
367
|
+
--color-primary: hsl(var(--primary));
|
|
368
|
+
--color-primary-foreground: hsl(var(--primary-foreground));
|
|
369
|
+
|
|
370
|
+
--color-secondary: hsl(var(--secondary));
|
|
371
|
+
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
372
|
+
|
|
373
|
+
--color-destructive: hsl(var(--destructive));
|
|
374
|
+
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
375
|
+
|
|
376
|
+
--color-muted: hsl(var(--muted));
|
|
377
|
+
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
378
|
+
|
|
379
|
+
--color-accent: hsl(var(--accent));
|
|
380
|
+
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
381
|
+
|
|
382
|
+
--color-popover: hsl(var(--popover));
|
|
383
|
+
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
384
|
+
|
|
385
|
+
--color-card: hsl(var(--card));
|
|
386
|
+
--color-card-foreground: hsl(var(--card-foreground));
|
|
387
|
+
|
|
388
|
+
--radius-lg: var(--radius);
|
|
389
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
390
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
@layer base {
|
|
394
|
+
:root {
|
|
395
|
+
--background: 0 0% 100%;
|
|
396
|
+
--foreground: 224 71.4% 4.1%;
|
|
397
|
+
--card: 0 0% 100%;
|
|
398
|
+
--card-foreground: 224 71.4% 4.1%;
|
|
399
|
+
--popover: 0 0% 100%;
|
|
400
|
+
--popover-foreground: 224 71.4% 4.1%;
|
|
401
|
+
--primary: 220.9 39.3% 11%;
|
|
402
|
+
--primary-foreground: 210 20% 98%;
|
|
403
|
+
--secondary: 220 14.3% 95.9%;
|
|
404
|
+
--secondary-foreground: 220.9 39.3% 11%;
|
|
405
|
+
--muted: 220 14.3% 95.9%;
|
|
406
|
+
--muted-foreground: 220 8.9% 46.1%;
|
|
407
|
+
--accent: 220 14.3% 95.9%;
|
|
408
|
+
--accent-foreground: 220.9 39.3% 11%;
|
|
409
|
+
--destructive: 0 84.2% 60.2%;
|
|
410
|
+
--destructive-foreground: 210 20% 98%;
|
|
411
|
+
--border: 220 13% 91%;
|
|
412
|
+
--input: 220 13% 91%;
|
|
413
|
+
--ring: 224 71.4% 4.1%;
|
|
414
|
+
--radius: 0.5rem;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.dark {
|
|
418
|
+
--background: 224 71.4% 4.1%;
|
|
419
|
+
--foreground: 210 20% 98%;
|
|
420
|
+
--card: 224 71.4% 4.1%;
|
|
421
|
+
--card-foreground: 210 20% 98%;
|
|
422
|
+
--popover: 224 71.4% 4.1%;
|
|
423
|
+
--popover-foreground: 210 20% 98%;
|
|
424
|
+
--primary: 210 20% 98%;
|
|
425
|
+
--primary-foreground: 220.9 39.3% 11%;
|
|
426
|
+
--secondary: 215 27.9% 16.9%;
|
|
427
|
+
--secondary-foreground: 210 20% 98%;
|
|
428
|
+
--muted: 215 27.9% 16.9%;
|
|
429
|
+
--muted-foreground: 217.9 10.6% 64.9%;
|
|
430
|
+
--accent: 215 27.9% 16.9%;
|
|
431
|
+
--accent-foreground: 210 20% 98%;
|
|
432
|
+
--destructive: 0 62.8% 30.6%;
|
|
433
|
+
--destructive-foreground: 210 20% 98%;
|
|
434
|
+
--border: 215 27.9% 16.9%;
|
|
435
|
+
--input: 215 27.9% 16.9%;
|
|
436
|
+
--ring: 216 12.2% 83.9%;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
@layer base {
|
|
441
|
+
* {
|
|
442
|
+
border-color: hsl(var(--border));
|
|
443
|
+
}
|
|
444
|
+
body {
|
|
445
|
+
@apply bg-background text-foreground;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/* Custom Scrollbar */
|
|
450
|
+
::-webkit-scrollbar {
|
|
451
|
+
width: 8px;
|
|
452
|
+
height: 8px;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
::-webkit-scrollbar-track {
|
|
456
|
+
@apply bg-transparent;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
::-webkit-scrollbar-thumb {
|
|
460
|
+
@apply bg-muted-foreground/20 rounded-full hover:bg-muted-foreground/30 transition-colors;
|
|
461
|
+
}`,
|
|
462
|
+
|
|
463
|
+
'app/[locale]/(auth)/layout.tsx': `export default function AuthLayout({
|
|
464
|
+
children,
|
|
465
|
+
}: {
|
|
466
|
+
children: React.ReactNode;
|
|
467
|
+
}) {
|
|
468
|
+
return (
|
|
469
|
+
<div className="min-h-screen flex items-center justify-center bg-gray-50 p-4">
|
|
470
|
+
<div className="w-full max-w-md bg-white rounded-xl shadow-lg p-8">
|
|
471
|
+
{children}
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
);
|
|
475
|
+
}`,
|
|
476
|
+
|
|
477
|
+
'app/[locale]/(auth)/login/page.tsx': `export default function LoginPage() {
|
|
478
|
+
return (
|
|
479
|
+
<div className="space-y-6 text-center">
|
|
480
|
+
<h1 className="text-2xl font-bold">Welcome Back</h1>
|
|
481
|
+
<p className="text-sm text-gray-500">Sign in to your CRM workspace</p>
|
|
482
|
+
<form className="space-y-4">
|
|
483
|
+
<input className="w-full border p-2 rounded" placeholder="Email" />
|
|
484
|
+
<input className="w-full border p-2 rounded" type="password" placeholder="Password" />
|
|
485
|
+
<button className="w-full bg-blue-600 text-white py-2 rounded">Login</button>
|
|
486
|
+
</form>
|
|
487
|
+
</div>
|
|
488
|
+
);
|
|
489
|
+
}`,
|
|
490
|
+
|
|
491
|
+
'app/[locale]/(auth)/sign-up/page.tsx': `export default function SignUpPage() {
|
|
492
|
+
return (
|
|
493
|
+
<div className="text-center">
|
|
494
|
+
<h1 className="text-2xl font-bold">Create Account</h1>
|
|
495
|
+
<p className="text-gray-500">Registration is restricted.</p>
|
|
496
|
+
</div>
|
|
497
|
+
);
|
|
498
|
+
}`,
|
|
499
|
+
|
|
500
|
+
'app/[locale]/(auth)/forgot-password/page.tsx': `export default function ForgotPasswordPage() {
|
|
501
|
+
return (
|
|
502
|
+
<div className="text-center">
|
|
503
|
+
<h1 className="text-2xl font-bold">Reset Password</h1>
|
|
504
|
+
<p className="text-gray-500">Contact admin for reset link.</p>
|
|
505
|
+
</div>
|
|
506
|
+
);
|
|
507
|
+
}`,
|
|
508
|
+
|
|
509
|
+
'app/[locale]/(workspace)/layout.tsx': `export default function WorkspaceLayout({
|
|
510
|
+
children,
|
|
511
|
+
}: {
|
|
512
|
+
children: React.ReactNode;
|
|
513
|
+
}) {
|
|
514
|
+
return (
|
|
515
|
+
<>{children}</>
|
|
516
|
+
);
|
|
517
|
+
}`,
|
|
518
|
+
|
|
519
|
+
'app/[locale]/(workspace)/(home)/page.tsx': `export default function DashboardPage() {
|
|
520
|
+
return (
|
|
521
|
+
<div className="space-y-6">
|
|
522
|
+
<h1 className="text-2xl font-bold">Dashboard</h1>
|
|
523
|
+
<p className="text-muted-foreground">Welcome to your workspace.</p>
|
|
524
|
+
</div>
|
|
525
|
+
);
|
|
526
|
+
}`,
|
|
527
|
+
};
|