@digilogiclabs/create-saas-app 1.10.0 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/commands/create.d.ts +7 -0
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +32 -1
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/template-generator.d.ts +9 -0
- package/dist/generators/template-generator.d.ts.map +1 -1
- package/dist/generators/template-generator.js +15 -1
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/web/ui-auth-ai/template/.env.example +18 -0
- package/dist/templates/web/ui-auth-ai/template/README.md +170 -0
- package/dist/templates/web/ui-auth-ai/template/next.config.js +13 -0
- package/dist/templates/web/ui-auth-ai/template/package.json +39 -0
- package/dist/templates/web/ui-auth-ai/template/postcss.config.js +6 -0
- package/dist/templates/web/ui-auth-ai/template/src/app/globals.css +40 -0
- package/dist/templates/web/ui-auth-ai/template/src/app/layout.tsx +41 -0
- package/dist/templates/web/ui-auth-ai/template/src/app/page.tsx +193 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +141 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +158 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +106 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +44 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +24 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/label.tsx +21 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +37 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +23 -0
- package/dist/templates/web/ui-auth-ai/template/src/hooks/useAuth.ts +1 -0
- package/dist/templates/web/ui-auth-ai/template/src/lib/supabase.ts +8 -0
- package/dist/templates/web/ui-auth-ai/template/src/lib/utils.ts +5 -0
- package/dist/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +55 -0
- package/dist/templates/web/ui-auth-ai/template/tailwind.config.js +22 -0
- package/dist/templates/web/ui-auth-ai/template/tsconfig.json +28 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +15 -15
- package/package.json +1 -1
- package/src/templates/web/ui-auth-ai/template/.env.example +18 -0
- package/src/templates/web/ui-auth-ai/template/README.md +170 -0
- package/src/templates/web/ui-auth-ai/template/next.config.js +13 -0
- package/src/templates/web/ui-auth-ai/template/package.json +39 -0
- package/src/templates/web/ui-auth-ai/template/postcss.config.js +6 -0
- package/src/templates/web/ui-auth-ai/template/src/app/globals.css +40 -0
- package/src/templates/web/ui-auth-ai/template/src/app/layout.tsx +41 -0
- package/src/templates/web/ui-auth-ai/template/src/app/page.tsx +193 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +141 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +158 -0
- package/src/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +106 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +44 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +24 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ui/label.tsx +21 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +37 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +23 -0
- package/src/templates/web/ui-auth-ai/template/src/hooks/useAuth.ts +1 -0
- package/src/templates/web/ui-auth-ai/template/src/lib/supabase.ts +8 -0
- package/src/templates/web/ui-auth-ai/template/src/lib/utils.ts +5 -0
- package/src/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +55 -0
- package/src/templates/web/ui-auth-ai/template/tailwind.config.js +22 -0
- package/src/templates/web/ui-auth-ai/template/tsconfig.json +28 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +15 -15
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cn } from "@/lib/utils"
|
|
3
|
+
|
|
4
|
+
export interface SelectProps
|
|
5
|
+
extends React.SelectHTMLAttributes<HTMLSelectElement> {}
|
|
6
|
+
|
|
7
|
+
const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
8
|
+
({ className, children, ...props }, ref) => {
|
|
9
|
+
return (
|
|
10
|
+
<select
|
|
11
|
+
className={cn(
|
|
12
|
+
"flex h-10 w-full items-center justify-between rounded-md border border-gray-300 bg-white px-3 py-2 text-sm placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
className
|
|
14
|
+
)}
|
|
15
|
+
ref={ref}
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
{children}
|
|
19
|
+
</select>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
Select.displayName = "Select"
|
|
24
|
+
|
|
25
|
+
// Simplified Select components for the template
|
|
26
|
+
const SelectTrigger = Select
|
|
27
|
+
const SelectValue = ({ children, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (
|
|
28
|
+
<span {...props}>{children}</span>
|
|
29
|
+
)
|
|
30
|
+
const SelectContent = ({ children, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
31
|
+
<div {...props}>{children}</div>
|
|
32
|
+
)
|
|
33
|
+
const SelectItem = ({ value, children, ...props }: React.OptionHTMLAttributes<HTMLOptionElement>) => (
|
|
34
|
+
<option value={value} {...props}>{children}</option>
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
export { Select, SelectTrigger, SelectValue, SelectContent, SelectItem }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cn } from "@/lib/utils"
|
|
3
|
+
|
|
4
|
+
export interface TextareaProps
|
|
5
|
+
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
|
6
|
+
|
|
7
|
+
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
8
|
+
({ className, ...props }, ref) => {
|
|
9
|
+
return (
|
|
10
|
+
<textarea
|
|
11
|
+
className={cn(
|
|
12
|
+
"flex min-h-[80px] w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
className
|
|
14
|
+
)}
|
|
15
|
+
ref={ref}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
Textarea.displayName = "Textarea"
|
|
22
|
+
|
|
23
|
+
export { Textarea }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useAuth } from '@/providers/auth-provider'
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, useEffect, useState } from 'react'
|
|
4
|
+
import { createClient } from '@/lib/supabase'
|
|
5
|
+
import type { User } from '@supabase/supabase-js'
|
|
6
|
+
|
|
7
|
+
interface AuthContextType {
|
|
8
|
+
user: User | null
|
|
9
|
+
loading: boolean
|
|
10
|
+
signOut: () => Promise<void>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const AuthContext = createContext<AuthContextType | undefined>(undefined)
|
|
14
|
+
|
|
15
|
+
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
16
|
+
const [user, setUser] = useState<User | null>(null)
|
|
17
|
+
const [loading, setLoading] = useState(true)
|
|
18
|
+
const supabase = createClient()
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
// Get initial session
|
|
22
|
+
supabase.auth.getSession().then(({ data: { session } }) => {
|
|
23
|
+
setUser(session?.user ?? null)
|
|
24
|
+
setLoading(false)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Listen for auth changes
|
|
28
|
+
const {
|
|
29
|
+
data: { subscription },
|
|
30
|
+
} = supabase.auth.onAuthStateChange((_event, session) => {
|
|
31
|
+
setUser(session?.user ?? null)
|
|
32
|
+
setLoading(false)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return () => subscription.unsubscribe()
|
|
36
|
+
}, [supabase.auth])
|
|
37
|
+
|
|
38
|
+
const signOut = async () => {
|
|
39
|
+
await supabase.auth.signOut()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<AuthContext.Provider value={{ user, loading, signOut }}>
|
|
44
|
+
{children}
|
|
45
|
+
</AuthContext.Provider>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function useAuth() {
|
|
50
|
+
const context = useContext(AuthContext)
|
|
51
|
+
if (context === undefined) {
|
|
52
|
+
throw new Error('useAuth must be used within an AuthProvider')
|
|
53
|
+
}
|
|
54
|
+
return context
|
|
55
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
content: [
|
|
4
|
+
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
|
|
5
|
+
'./components/**/*.{js,ts,jsx,tsx,mdx}',
|
|
6
|
+
'./app/**/*.{js,ts,jsx,tsx,mdx}',
|
|
7
|
+
'./src/**/*.{js,ts,jsx,tsx,mdx}',
|
|
8
|
+
],
|
|
9
|
+
theme: {
|
|
10
|
+
extend: {
|
|
11
|
+
colors: {
|
|
12
|
+
primary: {
|
|
13
|
+
50: '#eff6ff',
|
|
14
|
+
500: '#3b82f6',
|
|
15
|
+
600: '#2563eb',
|
|
16
|
+
700: '#1d4ed8',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
plugins: [],
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es5",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "es6"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"baseUrl": ".",
|
|
22
|
+
"paths": {
|
|
23
|
+
"@/*": ["./src/*"]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
27
|
+
"exclude": ["node_modules"]
|
|
28
|
+
}
|
|
@@ -224,7 +224,7 @@ export default function Home() {
|
|
|
224
224
|
{/* Main Content */}
|
|
225
225
|
<div className="lg:col-span-3 space-y-8">
|
|
226
226
|
{/* Now Playing Card with Enhanced Glassmorphism */}
|
|
227
|
-
<div className=
|
|
227
|
+
<div className={`${glass.card} ${glass.border} rounded-3xl p-6 mb-8 ${animations.hover.lift} ${animations.transition.smooth}">
|
|
228
228
|
<NowPlayingCard
|
|
229
229
|
track={currentTrack || demoPlaylist[0]}
|
|
230
230
|
isPlaying={isPlaying}
|
|
@@ -236,7 +236,7 @@ export default function Home() {
|
|
|
236
236
|
|
|
237
237
|
{/* Featured Playlists with Staggered Animation */}
|
|
238
238
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
|
239
|
-
<div className=
|
|
239
|
+
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.short}">
|
|
240
240
|
<PlaylistCard
|
|
241
241
|
title="Today's Top Hits"
|
|
242
242
|
description="The most played songs today"
|
|
@@ -246,7 +246,7 @@ export default function Home() {
|
|
|
246
246
|
className="bg-transparent border-none"
|
|
247
247
|
/>
|
|
248
248
|
</div>
|
|
249
|
-
<div className=
|
|
249
|
+
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.medium}">
|
|
250
250
|
<PlaylistCard
|
|
251
251
|
title="Chill Vibes"
|
|
252
252
|
description="Relaxing music for focus and creativity"
|
|
@@ -256,7 +256,7 @@ export default function Home() {
|
|
|
256
256
|
className="bg-transparent border-none"
|
|
257
257
|
/>
|
|
258
258
|
</div>
|
|
259
|
-
<div className=
|
|
259
|
+
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.long}">
|
|
260
260
|
<PlaylistCard
|
|
261
261
|
title="Electronic Pulse"
|
|
262
262
|
description="High-energy electronic and dance music"
|
|
@@ -269,7 +269,7 @@ export default function Home() {
|
|
|
269
269
|
</div>
|
|
270
270
|
|
|
271
271
|
{/* Track List with Glassmorphism */}
|
|
272
|
-
<div className=
|
|
272
|
+
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.transition.smooth}">
|
|
273
273
|
<TrackList
|
|
274
274
|
tracks={demoPlaylist}
|
|
275
275
|
currentTrackId={currentTrack?.id}
|
|
@@ -288,7 +288,7 @@ export default function Home() {
|
|
|
288
288
|
|
|
289
289
|
{/* Sidebar with Glassmorphism */}
|
|
290
290
|
<div className="lg:col-span-1">
|
|
291
|
-
<div className=
|
|
291
|
+
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.lift} ${animations.transition.smooth}">
|
|
292
292
|
<PlaylistSidebar
|
|
293
293
|
playlists={[
|
|
294
294
|
{ id: '1', name: 'Liked Songs', trackCount: 47 },
|
|
@@ -306,8 +306,8 @@ export default function Home() {
|
|
|
306
306
|
|
|
307
307
|
{/* Features Overview with Enhanced Glassmorphism */}
|
|
308
308
|
<ResponsiveGrid columns={gridConfig.columns_1_sm2_md4} gap="lg" className="mb-16">
|
|
309
|
-
<div className=
|
|
310
|
-
<div className=
|
|
309
|
+
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.short}">
|
|
310
|
+
<div className={`mx-auto w-12 h-12 ${glass.accent} rounded-xl flex items-center justify-center mb-4 ${animations.hover.glow}`}>
|
|
311
311
|
<Zap className="h-6 w-6 text-blue-400" />
|
|
312
312
|
</div>
|
|
313
313
|
<h3 className="text-lg font-semibold mb-2">High-Quality Streaming</h3>
|
|
@@ -316,8 +316,8 @@ export default function Home() {
|
|
|
316
316
|
</p>
|
|
317
317
|
</div>
|
|
318
318
|
|
|
319
|
-
<div className=
|
|
320
|
-
<div className=
|
|
319
|
+
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.medium}">
|
|
320
|
+
<div className={`mx-auto w-12 h-12 ${glass.accent} rounded-xl flex items-center justify-center mb-4 ${animations.hover.glow}`}>
|
|
321
321
|
<Shield className="h-6 w-6 text-green-400" />
|
|
322
322
|
</div>
|
|
323
323
|
<h3 className="text-lg font-semibold mb-2">Secure & Private</h3>
|
|
@@ -326,8 +326,8 @@ export default function Home() {
|
|
|
326
326
|
</p>
|
|
327
327
|
</div>
|
|
328
328
|
|
|
329
|
-
<div className=
|
|
330
|
-
<div className=
|
|
329
|
+
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.long}">
|
|
330
|
+
<div className={`mx-auto w-12 h-12 ${glass.accent} rounded-xl flex items-center justify-center mb-4 ${animations.hover.glow}`}>
|
|
331
331
|
<Rocket className="h-6 w-6 text-purple-400" />
|
|
332
332
|
</div>
|
|
333
333
|
<h3 className="text-lg font-semibold mb-2">Offline Support</h3>
|
|
@@ -336,8 +336,8 @@ export default function Home() {
|
|
|
336
336
|
</p>
|
|
337
337
|
</div>
|
|
338
338
|
|
|
339
|
-
<div className=
|
|
340
|
-
<div className=
|
|
339
|
+
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.extra}">
|
|
340
|
+
<div className={`mx-auto w-12 h-12 ${glass.accent} rounded-xl flex items-center justify-center mb-4 ${animations.hover.glow}`}>
|
|
341
341
|
<svg className="h-6 w-6 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
342
342
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
|
|
343
343
|
</svg>
|
|
@@ -355,7 +355,7 @@ export default function Home() {
|
|
|
355
355
|
</OfflineWrapper>
|
|
356
356
|
|
|
357
357
|
{/* Fixed Audio Player Bar with Enhanced Glassmorphism */}
|
|
358
|
-
<div className=
|
|
358
|
+
<div className={`fixed bottom-0 left-0 right-0 z-50 ${glass.card} ${glass.border} border-t backdrop-blur-xl`}>
|
|
359
359
|
<FixedAudioBar
|
|
360
360
|
track={currentTrack || demoPlaylist[0]}
|
|
361
361
|
isPlaying={isPlaying}
|
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Supabase Configuration
|
|
2
|
+
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
|
|
3
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
|
|
4
|
+
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
|
|
5
|
+
|
|
6
|
+
# AI Gateway Configuration
|
|
7
|
+
AI_GATEWAY_URL=http://localhost:3001
|
|
8
|
+
{{#ai.enabled}}
|
|
9
|
+
|
|
10
|
+
# AI Provider Configuration ({{ai.provider}})
|
|
11
|
+
# Add your API key for the selected provider:
|
|
12
|
+
# For OpenAI: OPENAI_API_KEY=your_openai_api_key
|
|
13
|
+
# For Anthropic: ANTHROPIC_API_KEY=your_anthropic_api_key
|
|
14
|
+
# For Gemini: GOOGLE_API_KEY=your_google_api_key
|
|
15
|
+
|
|
16
|
+
# Redis Configuration (for AI job processing)
|
|
17
|
+
REDIS_URL=redis://localhost:6379
|
|
18
|
+
{{/ai.enabled}}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# {{titleCaseName}}
|
|
2
|
+
|
|
3
|
+
{{description}}
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
{{#ai.enabled}}
|
|
8
|
+
### AI Capabilities
|
|
9
|
+
{{#ai.hasText}}
|
|
10
|
+
- 🤖 **AI Chat**: Interactive AI assistant powered by {{ai.provider}}
|
|
11
|
+
{{/ai.hasText}}
|
|
12
|
+
{{#ai.hasAudio}}
|
|
13
|
+
- 🎵 **Audio Generation**: Create custom audio with AI
|
|
14
|
+
{{/ai.hasAudio}}
|
|
15
|
+
{{#ai.hasVideo}}
|
|
16
|
+
- 🎥 **Video Generation**: Generate videos with AI
|
|
17
|
+
{{/ai.hasVideo}}
|
|
18
|
+
|
|
19
|
+
### AI Provider: {{ai.provider}}
|
|
20
|
+
This application is configured to use {{ai.provider}} as the AI provider.
|
|
21
|
+
{{/ai.enabled}}
|
|
22
|
+
|
|
23
|
+
### Authentication
|
|
24
|
+
- 🔐 **Supabase Auth**: Secure authentication with email/password
|
|
25
|
+
- 👤 **User Management**: Complete user registration and login flow
|
|
26
|
+
|
|
27
|
+
### Tech Stack
|
|
28
|
+
- **Framework**: Next.js 15 with App Router
|
|
29
|
+
- **Styling**: Tailwind CSS
|
|
30
|
+
- **Authentication**: Supabase
|
|
31
|
+
- **Database**: Supabase (PostgreSQL)
|
|
32
|
+
{{#ai.enabled}}
|
|
33
|
+
- **AI SDK**: @digilogiclabs/saas-factory-ai
|
|
34
|
+
{{/ai.enabled}}
|
|
35
|
+
- **Language**: TypeScript
|
|
36
|
+
|
|
37
|
+
## Getting Started
|
|
38
|
+
|
|
39
|
+
### Prerequisites
|
|
40
|
+
- Node.js 18+
|
|
41
|
+
- npm or yarn
|
|
42
|
+
- Supabase account
|
|
43
|
+
{{#ai.enabled}}
|
|
44
|
+
- {{ai.provider}} API key
|
|
45
|
+
{{/ai.enabled}}
|
|
46
|
+
|
|
47
|
+
### Installation
|
|
48
|
+
|
|
49
|
+
1. **Install dependencies**
|
|
50
|
+
```bash
|
|
51
|
+
npm install
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
2. **Set up environment variables**
|
|
55
|
+
```bash
|
|
56
|
+
cp .env.example .env.local
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Fill in your environment variables:
|
|
60
|
+
- `NEXT_PUBLIC_SUPABASE_URL`: Your Supabase project URL
|
|
61
|
+
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`: Your Supabase anon key
|
|
62
|
+
- `SUPABASE_SERVICE_ROLE_KEY`: Your Supabase service role key
|
|
63
|
+
{{#ai.enabled}}
|
|
64
|
+
- API key for your selected AI provider ({{ai.provider}})
|
|
65
|
+
- `AI_GATEWAY_URL`: URL of your AI gateway service
|
|
66
|
+
- `REDIS_URL`: Redis connection URL (for AI job processing)
|
|
67
|
+
{{/ai.enabled}}
|
|
68
|
+
|
|
69
|
+
3. **Set up Supabase**
|
|
70
|
+
- Create a new Supabase project
|
|
71
|
+
- Run the database migrations (see `migrations/` folder)
|
|
72
|
+
- Enable authentication in your Supabase dashboard
|
|
73
|
+
|
|
74
|
+
{{#ai.enabled}}
|
|
75
|
+
4. **Set up AI Gateway** (Optional for development)
|
|
76
|
+
- Deploy the AI gateway service from `@digilogiclabs/saas-factory-ai-gateway`
|
|
77
|
+
- Or use the development gateway at `http://localhost:3001`
|
|
78
|
+
{{/ai.enabled}}
|
|
79
|
+
|
|
80
|
+
5. **Run the development server**
|
|
81
|
+
```bash
|
|
82
|
+
npm run dev
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
6. **Open your browser**
|
|
86
|
+
Navigate to [http://localhost:3000](http://localhost:3000)
|
|
87
|
+
|
|
88
|
+
## Project Structure
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
src/
|
|
92
|
+
├── app/ # Next.js app router
|
|
93
|
+
│ ├── layout.tsx # Root layout with providers
|
|
94
|
+
│ ├── page.tsx # Home page
|
|
95
|
+
│ └── globals.css # Global styles
|
|
96
|
+
├── components/
|
|
97
|
+
│ ├── ui/ # Reusable UI components
|
|
98
|
+
{{#ai.enabled}}
|
|
99
|
+
│ ├── ai/ # AI-specific components
|
|
100
|
+
{{/ai.enabled}}
|
|
101
|
+
│ └── auth/ # Authentication components
|
|
102
|
+
├── providers/ # React context providers
|
|
103
|
+
├── hooks/ # Custom React hooks
|
|
104
|
+
└── lib/ # Utility functions
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
{{#ai.enabled}}
|
|
108
|
+
## AI Features Usage
|
|
109
|
+
|
|
110
|
+
### Chat Interface
|
|
111
|
+
The chat interface provides real-time streaming responses from {{ai.provider}}:
|
|
112
|
+
```tsx
|
|
113
|
+
import { ChatPanel } from '@digilogiclabs/saas-factory-ai/react'
|
|
114
|
+
|
|
115
|
+
<ChatPanel
|
|
116
|
+
placeholder="Ask me anything..."
|
|
117
|
+
onError={(error) => console.error('Chat error:', error)}
|
|
118
|
+
/>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
{{#ai.hasAudio}}
|
|
122
|
+
### Audio Generation
|
|
123
|
+
Generate custom audio with different styles:
|
|
124
|
+
```tsx
|
|
125
|
+
import { AudioGenerator } from '@/components/ai/audio-generator'
|
|
126
|
+
|
|
127
|
+
<AudioGenerator />
|
|
128
|
+
```
|
|
129
|
+
{{/ai.hasAudio}}
|
|
130
|
+
|
|
131
|
+
{{#ai.hasVideo}}
|
|
132
|
+
### Video Generation
|
|
133
|
+
Create videos from text descriptions:
|
|
134
|
+
```tsx
|
|
135
|
+
import { VideoGenerator } from '@/components/ai/video-generator'
|
|
136
|
+
|
|
137
|
+
<VideoGenerator />
|
|
138
|
+
```
|
|
139
|
+
{{/ai.hasVideo}}
|
|
140
|
+
{{/ai.enabled}}
|
|
141
|
+
|
|
142
|
+
## Deployment
|
|
143
|
+
|
|
144
|
+
### Vercel (Recommended)
|
|
145
|
+
1. Push your code to GitHub
|
|
146
|
+
2. Connect your repo to Vercel
|
|
147
|
+
3. Add your environment variables in Vercel dashboard
|
|
148
|
+
4. Deploy!
|
|
149
|
+
|
|
150
|
+
### Other Platforms
|
|
151
|
+
This is a standard Next.js application and can be deployed to any platform that supports Node.js.
|
|
152
|
+
|
|
153
|
+
## Learn More
|
|
154
|
+
|
|
155
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|
|
156
|
+
- [Supabase Documentation](https://supabase.com/docs)
|
|
157
|
+
{{#ai.enabled}}
|
|
158
|
+
- [SaaS Factory AI Documentation](https://docs.digilogiclabs.com/ai)
|
|
159
|
+
{{/ai.enabled}}
|
|
160
|
+
- [Tailwind CSS](https://tailwindcss.com/docs)
|
|
161
|
+
|
|
162
|
+
## Support
|
|
163
|
+
|
|
164
|
+
- 📚 [Documentation](https://docs.digilogiclabs.com)
|
|
165
|
+
- 💬 [Discord Community](https://discord.gg/digilogiclabs)
|
|
166
|
+
- 🐛 [Issue Tracker](https://github.com/DigiLogicLabs/saas-factory-ai/issues)
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
Generated with ❤️ by [Digi Logic Labs](https://digilogiclabs.com)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** @type {import('next').NextConfig} */
|
|
2
|
+
const nextConfig = {
|
|
3
|
+
experimental: {
|
|
4
|
+
serverComponentsExternalPackages: ['@digilogiclabs/saas-factory-ai'],
|
|
5
|
+
},
|
|
6
|
+
env: {
|
|
7
|
+
NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
8
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
9
|
+
AI_GATEWAY_URL: process.env.AI_GATEWAY_URL || 'http://localhost:3001',
|
|
10
|
+
},
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = nextConfig
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@digilogiclabs/saas-factory-ui": "^0.18.1",
|
|
13
|
+
"@digilogiclabs/saas-factory-auth": "^1.0.0",
|
|
14
|
+
"next": "^15.0.0",
|
|
15
|
+
"react": "^19.0.0",
|
|
16
|
+
"react-dom": "^19.0.0",
|
|
17
|
+
"@supabase/supabase-js": "^2.0.0",
|
|
18
|
+
"@supabase/ssr": "^0.1.0",
|
|
19
|
+
"clsx": "^2.0.0",
|
|
20
|
+
"tailwindcss": "^3.3.0",
|
|
21
|
+
"autoprefixer": "^10.4.16",
|
|
22
|
+
"postcss": "^8.4.31"{{#ai.enabled}},
|
|
23
|
+
"@digilogiclabs/saas-factory-ai": "^3.0.0",
|
|
24
|
+
"@digilogiclabs/saas-factory-ai-types": "^3.0.0"{{/ai.enabled}}
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20.0.0",
|
|
28
|
+
"@types/react": "^18.0.0",
|
|
29
|
+
"@types/react-dom": "^18.0.0",
|
|
30
|
+
"eslint": "^8.0.0",
|
|
31
|
+
"prettier": "^3.0.0",
|
|
32
|
+
"typescript": "^5.0.0"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18.0.0"
|
|
36
|
+
},
|
|
37
|
+
"author": "{{author}}",
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
/* Import SaaS Factory UI styles */
|
|
6
|
+
@import '@digilogiclabs/saas-factory-ui/dist/index.css';
|
|
7
|
+
|
|
8
|
+
@layer base {
|
|
9
|
+
:root {
|
|
10
|
+
--background: 0 0% 100%;
|
|
11
|
+
--foreground: 222.2 84% 4.9%;
|
|
12
|
+
--card: 0 0% 100%;
|
|
13
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
14
|
+
--popover: 0 0% 100%;
|
|
15
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
16
|
+
--primary: 222.2 47.4% 11.2%;
|
|
17
|
+
--primary-foreground: 210 40% 98%;
|
|
18
|
+
--secondary: 210 40% 96%;
|
|
19
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
20
|
+
--muted: 210 40% 96%;
|
|
21
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
22
|
+
--accent: 210 40% 96%;
|
|
23
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
24
|
+
--destructive: 0 84.2% 60.2%;
|
|
25
|
+
--destructive-foreground: 210 40% 98%;
|
|
26
|
+
--border: 214.3 31.8% 91.4%;
|
|
27
|
+
--input: 214.3 31.8% 91.4%;
|
|
28
|
+
--ring: 222.2 84% 4.9%;
|
|
29
|
+
--radius: 0.5rem;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@layer base {
|
|
34
|
+
* {
|
|
35
|
+
@apply border-border;
|
|
36
|
+
}
|
|
37
|
+
body {
|
|
38
|
+
@apply bg-background text-foreground;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Metadata } from 'next'
|
|
2
|
+
import { Inter } from 'next/font/google'
|
|
3
|
+
import './globals.css'
|
|
4
|
+
{{#ai.enabled}}
|
|
5
|
+
import { AIProvider } from '@digilogiclabs/saas-factory-ai/react'
|
|
6
|
+
{{/ai.enabled}}
|
|
7
|
+
import { AuthProvider } from '@/providers/auth-provider'
|
|
8
|
+
|
|
9
|
+
const inter = Inter({ subsets: ['latin'] })
|
|
10
|
+
|
|
11
|
+
export const metadata: Metadata = {
|
|
12
|
+
title: '{{titleCaseName}}',
|
|
13
|
+
description: '{{description}}',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function RootLayout({
|
|
17
|
+
children,
|
|
18
|
+
}: {
|
|
19
|
+
children: React.ReactNode
|
|
20
|
+
}) {
|
|
21
|
+
return (
|
|
22
|
+
<html lang="en">
|
|
23
|
+
<body className={inter.className}>
|
|
24
|
+
<AuthProvider>
|
|
25
|
+
{{#ai.enabled}}
|
|
26
|
+
<AIProvider
|
|
27
|
+
config={{
|
|
28
|
+
gatewayUrl: process.env.NEXT_PUBLIC_AI_GATEWAY_URL || 'http://localhost:3001',
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
</AIProvider>
|
|
33
|
+
{{/ai.enabled}}
|
|
34
|
+
{{^ai.enabled}}
|
|
35
|
+
{children}
|
|
36
|
+
{{/ai.enabled}}
|
|
37
|
+
</AuthProvider>
|
|
38
|
+
</body>
|
|
39
|
+
</html>
|
|
40
|
+
)
|
|
41
|
+
}
|