@digilogiclabs/create-saas-app 2.10.0 → 2.11.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/README.md +153 -113
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +2 -6
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
- package/dist/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
- package/dist/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
- package/dist/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
- package/dist/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
- package/dist/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
- package/dist/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
- package/dist/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
- package/dist/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
- package/dist/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
- package/dist/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
- package/dist/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
- package/dist/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
- package/dist/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
- package/dist/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
- package/dist/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
- package/dist/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
- package/dist/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
- package/dist/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
- package/dist/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
- package/dist/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
- package/dist/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
- package/dist/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
- package/package.json +1 -1
- package/src/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
- package/src/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
- package/src/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
- package/src/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
- package/src/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
- package/src/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
- package/src/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
- package/src/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
- package/src/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
- package/src/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
- package/src/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
- package/src/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
- package/src/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
- package/src/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
- package/src/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
- package/src/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
- package/src/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
- package/src/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
- package/src/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
- package/src/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
- package/src/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
- package/src/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
- package/src/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"AAUA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,YAAY,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC3C,QAAQ,EAAE,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;IACjD,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC3C,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;IACrE,YAAY,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1C,YAAY,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAClD,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACxC,EAAE,EAAE;QACF,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,QAAQ,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;KAC7C,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,GAAE,aAAa,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"AAUA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,YAAY,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC3C,QAAQ,EAAE,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;IACjD,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC3C,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;IACrE,YAAY,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1C,YAAY,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAClD,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACxC,EAAE,EAAE;QACF,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,QAAQ,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;KAC7C,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,GAAE,aAAa,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,iBA2K7E"}
|
|
@@ -32,7 +32,7 @@ async function createProject(platform, template, name, options = {}) {
|
|
|
32
32
|
if (withAi === true)
|
|
33
33
|
return { enabled: true, capabilities: ['text'] };
|
|
34
34
|
if (withAi === 'all')
|
|
35
|
-
return { enabled: true, capabilities: ['text', 'audio', 'video'
|
|
35
|
+
return { enabled: true, capabilities: ['text', 'audio', 'video'] };
|
|
36
36
|
return { enabled: true, capabilities: withAi.split(',').map((c) => c.trim()) };
|
|
37
37
|
};
|
|
38
38
|
const aiConfig = parseAiCapabilities(options.withAi);
|
|
@@ -43,11 +43,7 @@ async function createProject(platform, template, name, options = {}) {
|
|
|
43
43
|
const hasAudio = capabilities.includes('audio');
|
|
44
44
|
const hasVideo = capabilities.includes('video');
|
|
45
45
|
const hasText = capabilities.includes('text');
|
|
46
|
-
|
|
47
|
-
// Use RAG template if RAG/knowledge capabilities are requested
|
|
48
|
-
if (hasRAG)
|
|
49
|
-
return 'ui-auth-payments-ai-rag';
|
|
50
|
-
// Use comprehensive AI template for other AI capabilities
|
|
46
|
+
// Use comprehensive AI template for AI capabilities
|
|
51
47
|
if (hasVideo || hasAudio || hasText)
|
|
52
48
|
return 'ui-auth-payments-ai';
|
|
53
49
|
return baseTemplate || 'ui-auth-payments-ai';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":";;;;;AAwDA,
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo auth API routes.
|
|
3
|
+
*
|
|
4
|
+
* POST /api/auth — Login or Signup
|
|
5
|
+
* DELETE /api/auth — Logout
|
|
6
|
+
*
|
|
7
|
+
* Replace with your real auth provider (Auth.js, Supabase Auth, etc.)
|
|
8
|
+
* when configuring your app for production.
|
|
9
|
+
*/
|
|
10
|
+
import { NextRequest, NextResponse } from 'next/server'
|
|
11
|
+
import { cookies } from 'next/headers'
|
|
12
|
+
|
|
13
|
+
export async function POST(request: NextRequest) {
|
|
14
|
+
try {
|
|
15
|
+
const body = await request.json()
|
|
16
|
+
const { email, password, action } = body
|
|
17
|
+
|
|
18
|
+
if (!email || !password) {
|
|
19
|
+
return NextResponse.json(
|
|
20
|
+
{ error: 'Email and password are required' },
|
|
21
|
+
{ status: 400 }
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Demo: accept any email/password combination.
|
|
26
|
+
// Replace with real authentication (database lookup, bcrypt compare, etc.)
|
|
27
|
+
const user = {
|
|
28
|
+
id: crypto.randomUUID(),
|
|
29
|
+
email,
|
|
30
|
+
name: email.split('@')[0],
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const session = JSON.stringify({ user })
|
|
34
|
+
const cookieStore = await cookies()
|
|
35
|
+
|
|
36
|
+
cookieStore.set('session', session, {
|
|
37
|
+
httpOnly: true,
|
|
38
|
+
secure: process.env.NODE_ENV === 'production',
|
|
39
|
+
sameSite: 'lax',
|
|
40
|
+
path: '/',
|
|
41
|
+
maxAge: 60 * 60 * 24 * 7, // 7 days
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return NextResponse.json({ user })
|
|
45
|
+
} catch {
|
|
46
|
+
return NextResponse.json(
|
|
47
|
+
{ error: 'Authentication failed' },
|
|
48
|
+
{ status: 500 }
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function DELETE() {
|
|
54
|
+
const cookieStore = await cookies()
|
|
55
|
+
cookieStore.delete('session')
|
|
56
|
+
return NextResponse.json({ success: true })
|
|
57
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
import { Button, Card, CardContent } from '@digilogiclabs/saas-factory-ui'
|
|
5
|
+
import { Bot } from 'lucide-react'
|
|
6
|
+
import { useRouter } from 'next/navigation'
|
|
7
|
+
import Link from 'next/link'
|
|
8
|
+
|
|
9
|
+
export default function LoginPage() {
|
|
10
|
+
const [email, setEmail] = useState('')
|
|
11
|
+
const [password, setPassword] = useState('')
|
|
12
|
+
const [error, setError] = useState('')
|
|
13
|
+
const [loading, setLoading] = useState(false)
|
|
14
|
+
const router = useRouter()
|
|
15
|
+
|
|
16
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
17
|
+
e.preventDefault()
|
|
18
|
+
setError('')
|
|
19
|
+
setLoading(true)
|
|
20
|
+
try {
|
|
21
|
+
const res = await fetch('/api/auth', {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: { 'Content-Type': 'application/json' },
|
|
24
|
+
body: JSON.stringify({ email, password, action: 'login' }),
|
|
25
|
+
})
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
const data = await res.json()
|
|
28
|
+
throw new Error(data.error || 'Failed to sign in')
|
|
29
|
+
}
|
|
30
|
+
router.push('/dashboard')
|
|
31
|
+
router.refresh()
|
|
32
|
+
} catch (err) {
|
|
33
|
+
setError(err instanceof Error ? err.message : 'Failed to sign in')
|
|
34
|
+
} finally {
|
|
35
|
+
setLoading(false)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="min-h-screen flex items-center justify-center bg-background px-4">
|
|
41
|
+
<div className="w-full max-w-md">
|
|
42
|
+
{/* Logo */}
|
|
43
|
+
<Link href="/" className="flex items-center justify-center gap-2 mb-8 hover:opacity-80 transition-opacity">
|
|
44
|
+
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-brand-from via-brand-via to-brand-to flex items-center justify-center">
|
|
45
|
+
<Bot className="w-5 h-5 text-white" />
|
|
46
|
+
</div>
|
|
47
|
+
<span className="font-bold text-xl">AI Platform</span>
|
|
48
|
+
</Link>
|
|
49
|
+
|
|
50
|
+
<Card className="border border-border">
|
|
51
|
+
<CardContent className="p-8">
|
|
52
|
+
<div className="text-center mb-8">
|
|
53
|
+
<h1 className="text-2xl font-bold">Welcome back</h1>
|
|
54
|
+
<p className="text-muted-foreground mt-2">Sign in to access AI models</p>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
{error && (
|
|
58
|
+
<div className="bg-destructive/10 text-destructive p-3 rounded-lg mb-6 text-sm" role="alert">
|
|
59
|
+
{error}
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
|
|
63
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
64
|
+
<div>
|
|
65
|
+
<label htmlFor="email" className="block text-sm font-medium mb-1.5">
|
|
66
|
+
Email
|
|
67
|
+
</label>
|
|
68
|
+
<input
|
|
69
|
+
id="email"
|
|
70
|
+
type="email"
|
|
71
|
+
value={email}
|
|
72
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
73
|
+
className="w-full px-3 py-2.5 rounded-lg border border-input bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-shadow"
|
|
74
|
+
placeholder="you@example.com"
|
|
75
|
+
required
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div>
|
|
80
|
+
<label htmlFor="password" className="block text-sm font-medium mb-1.5">
|
|
81
|
+
Password
|
|
82
|
+
</label>
|
|
83
|
+
<input
|
|
84
|
+
id="password"
|
|
85
|
+
type="password"
|
|
86
|
+
value={password}
|
|
87
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
88
|
+
className="w-full px-3 py-2.5 rounded-lg border border-input bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-shadow"
|
|
89
|
+
placeholder="Enter your password"
|
|
90
|
+
required
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<Button type="submit" className="w-full h-11 text-base cursor-pointer hover:brightness-110 active:scale-[0.98] transition-all duration-200" disabled={loading}>
|
|
95
|
+
{loading ? 'Signing in...' : 'Sign In'}
|
|
96
|
+
</Button>
|
|
97
|
+
</form>
|
|
98
|
+
|
|
99
|
+
<div className="mt-6 text-center">
|
|
100
|
+
<p className="text-muted-foreground text-sm">
|
|
101
|
+
Don't have an account?{' '}
|
|
102
|
+
<Link href="/signup" className="text-primary hover:underline font-medium">
|
|
103
|
+
Create an account
|
|
104
|
+
</Link>
|
|
105
|
+
</p>
|
|
106
|
+
</div>
|
|
107
|
+
</CardContent>
|
|
108
|
+
</Card>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
import { Button, Card } from '@digilogiclabs/saas-factory-ui'
|
|
5
|
+
import { Bot, MessageSquare, Code, Eye, Sparkles, Zap } from 'lucide-react'
|
|
6
|
+
import Link from 'next/link'
|
|
7
|
+
|
|
8
|
+
interface Model {
|
|
9
|
+
id: string
|
|
10
|
+
name: string
|
|
11
|
+
provider: 'OpenAI' | 'Anthropic' | 'Google'
|
|
12
|
+
description: string
|
|
13
|
+
capabilities: { label: string; icon: React.ComponentType<{ className?: string }> }[]
|
|
14
|
+
pricing: string
|
|
15
|
+
badge: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const MODELS: Model[] = [
|
|
19
|
+
{
|
|
20
|
+
id: 'gpt-4o',
|
|
21
|
+
name: 'GPT-4o',
|
|
22
|
+
provider: 'OpenAI',
|
|
23
|
+
description: 'Most capable OpenAI model with vision and advanced reasoning.',
|
|
24
|
+
capabilities: [
|
|
25
|
+
{ label: 'Chat', icon: MessageSquare },
|
|
26
|
+
{ label: 'Code', icon: Code },
|
|
27
|
+
{ label: 'Vision', icon: Eye },
|
|
28
|
+
],
|
|
29
|
+
pricing: '~2.5M tokens/$1',
|
|
30
|
+
badge: 'bg-green-500/20 text-green-400',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 'gpt-4o-mini',
|
|
34
|
+
name: 'GPT-4o Mini',
|
|
35
|
+
provider: 'OpenAI',
|
|
36
|
+
description: 'Fast and affordable for everyday tasks and simple queries.',
|
|
37
|
+
capabilities: [
|
|
38
|
+
{ label: 'Chat', icon: MessageSquare },
|
|
39
|
+
{ label: 'Code', icon: Code },
|
|
40
|
+
],
|
|
41
|
+
pricing: '~16.6M tokens/$1',
|
|
42
|
+
badge: 'bg-green-500/20 text-green-400',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'claude-3-5-sonnet',
|
|
46
|
+
name: 'Claude 3.5 Sonnet',
|
|
47
|
+
provider: 'Anthropic',
|
|
48
|
+
description: 'Excellent at analysis, writing, and complex reasoning tasks.',
|
|
49
|
+
capabilities: [
|
|
50
|
+
{ label: 'Chat', icon: MessageSquare },
|
|
51
|
+
{ label: 'Code', icon: Code },
|
|
52
|
+
{ label: 'Vision', icon: Eye },
|
|
53
|
+
{ label: 'Analysis', icon: Sparkles },
|
|
54
|
+
],
|
|
55
|
+
pricing: '~3.3M tokens/$1',
|
|
56
|
+
badge: 'bg-orange-500/20 text-orange-400',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 'claude-3-haiku',
|
|
60
|
+
name: 'Claude 3 Haiku',
|
|
61
|
+
provider: 'Anthropic',
|
|
62
|
+
description: 'Fastest Anthropic model, great for quick responses and automation.',
|
|
63
|
+
capabilities: [
|
|
64
|
+
{ label: 'Chat', icon: MessageSquare },
|
|
65
|
+
{ label: 'Code', icon: Code },
|
|
66
|
+
],
|
|
67
|
+
pricing: '~20M tokens/$1',
|
|
68
|
+
badge: 'bg-orange-500/20 text-orange-400',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'gemini-1-5-pro',
|
|
72
|
+
name: 'Gemini 1.5 Pro',
|
|
73
|
+
provider: 'Google',
|
|
74
|
+
description: 'Long context window with multimodal support from Google.',
|
|
75
|
+
capabilities: [
|
|
76
|
+
{ label: 'Chat', icon: MessageSquare },
|
|
77
|
+
{ label: 'Code', icon: Code },
|
|
78
|
+
{ label: 'Vision', icon: Eye },
|
|
79
|
+
{ label: 'Analysis', icon: Sparkles },
|
|
80
|
+
],
|
|
81
|
+
pricing: '~4M tokens/$1',
|
|
82
|
+
badge: 'bg-blue-500/20 text-blue-400',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'gemini-flash',
|
|
86
|
+
name: 'Gemini Flash',
|
|
87
|
+
provider: 'Google',
|
|
88
|
+
description: 'Ultra-fast responses with efficient token usage.',
|
|
89
|
+
capabilities: [
|
|
90
|
+
{ label: 'Chat', icon: MessageSquare },
|
|
91
|
+
{ label: 'Code', icon: Code },
|
|
92
|
+
],
|
|
93
|
+
pricing: '~26.6M tokens/$1',
|
|
94
|
+
badge: 'bg-blue-500/20 text-blue-400',
|
|
95
|
+
},
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
const PROVIDERS = ['All', 'OpenAI', 'Anthropic', 'Google'] as const
|
|
99
|
+
|
|
100
|
+
export default function ModelsPage() {
|
|
101
|
+
const [filter, setFilter] = useState<string>('All')
|
|
102
|
+
|
|
103
|
+
const filteredModels = filter === 'All'
|
|
104
|
+
? MODELS
|
|
105
|
+
: MODELS.filter(m => m.provider === filter)
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div className="min-h-screen bg-background">
|
|
109
|
+
<div className="max-w-7xl mx-auto px-4 py-8">
|
|
110
|
+
{/* Header */}
|
|
111
|
+
<div className="mb-8">
|
|
112
|
+
<h1 className="text-3xl font-bold text-foreground">AI Models</h1>
|
|
113
|
+
<p className="text-muted-foreground mt-1">
|
|
114
|
+
Browse available models and find the right one for your use case.
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
{/* Filter */}
|
|
119
|
+
<div className="flex flex-wrap gap-2 mb-8">
|
|
120
|
+
{PROVIDERS.map((provider) => (
|
|
121
|
+
<Button
|
|
122
|
+
key={provider}
|
|
123
|
+
variant={filter === provider ? 'default' : 'outline'}
|
|
124
|
+
size="sm"
|
|
125
|
+
onClick={() => setFilter(provider)}
|
|
126
|
+
>
|
|
127
|
+
{provider}
|
|
128
|
+
</Button>
|
|
129
|
+
))}
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
{/* Models Grid */}
|
|
133
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
134
|
+
{filteredModels.map((model) => (
|
|
135
|
+
<Card key={model.id} className="p-6 bg-secondary border-border flex flex-col">
|
|
136
|
+
<div className="flex items-start justify-between mb-3">
|
|
137
|
+
<div className="flex items-center gap-3">
|
|
138
|
+
<div className="w-10 h-10 bg-primary/20 rounded-lg flex items-center justify-center">
|
|
139
|
+
<Bot className="w-5 h-5 text-primary" />
|
|
140
|
+
</div>
|
|
141
|
+
<div>
|
|
142
|
+
<h3 className="text-lg font-semibold text-foreground">{model.name}</h3>
|
|
143
|
+
<span className={`text-xs font-medium px-2 py-0.5 rounded-full ${model.badge}`}>
|
|
144
|
+
{model.provider}
|
|
145
|
+
</span>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<p className="text-sm text-muted-foreground mb-4 flex-1">
|
|
151
|
+
{model.description}
|
|
152
|
+
</p>
|
|
153
|
+
|
|
154
|
+
{/* Capabilities */}
|
|
155
|
+
<div className="flex flex-wrap gap-2 mb-4">
|
|
156
|
+
{model.capabilities.map((cap) => (
|
|
157
|
+
<span
|
|
158
|
+
key={cap.label}
|
|
159
|
+
className="inline-flex items-center gap-1 text-xs px-2 py-1 bg-muted rounded-md text-muted-foreground"
|
|
160
|
+
>
|
|
161
|
+
<cap.icon className="w-3 h-3" />
|
|
162
|
+
{cap.label}
|
|
163
|
+
</span>
|
|
164
|
+
))}
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
{/* Pricing */}
|
|
168
|
+
<div className="flex items-center gap-1 text-sm text-muted-foreground mb-4">
|
|
169
|
+
<Zap className="w-4 h-4 text-primary" />
|
|
170
|
+
<span>{model.pricing}</span>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
{/* Action */}
|
|
174
|
+
<Link href={`/chat?model=${model.id}`}>
|
|
175
|
+
<Button className="w-full">
|
|
176
|
+
<MessageSquare className="w-4 h-4 mr-2" />
|
|
177
|
+
Try in Chat
|
|
178
|
+
</Button>
|
|
179
|
+
</Link>
|
|
180
|
+
</Card>
|
|
181
|
+
))}
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
)
|
|
186
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
import { Button, Card } from '@digilogiclabs/saas-factory-ui'
|
|
5
|
+
import { Play, Loader2, Clock, Hash, Bot } from 'lucide-react'
|
|
6
|
+
import { useAuth } from '@digilogiclabs/app-sdk'
|
|
7
|
+
import Link from 'next/link'
|
|
8
|
+
|
|
9
|
+
const MODELS = [
|
|
10
|
+
{ id: 'gpt-4o', name: 'GPT-4o' },
|
|
11
|
+
{ id: 'gpt-4o-mini', name: 'GPT-4o Mini' },
|
|
12
|
+
{ id: 'claude-3-5-sonnet', name: 'Claude 3.5 Sonnet' },
|
|
13
|
+
{ id: 'claude-3-haiku', name: 'Claude 3 Haiku' },
|
|
14
|
+
{ id: 'gemini-1-5-pro', name: 'Gemini 1.5 Pro' },
|
|
15
|
+
{ id: 'gemini-flash', name: 'Gemini Flash' },
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
const DEMO_RESPONSES: Record<string, string> = {
|
|
19
|
+
'gpt-4o': 'This is a simulated response from GPT-4o. In production, this would connect to the OpenAI API and return a real completion based on your prompt and parameters.',
|
|
20
|
+
'gpt-4o-mini': 'This is a simulated response from GPT-4o Mini. This model is optimized for speed and cost-efficiency while maintaining good quality output.',
|
|
21
|
+
'claude-3-5-sonnet': 'This is a simulated response from Claude 3.5 Sonnet. Known for nuanced analysis and careful reasoning, this model excels at complex tasks.',
|
|
22
|
+
'claude-3-haiku': 'This is a simulated response from Claude 3 Haiku. Designed for fast, concise responses ideal for automation and quick queries.',
|
|
23
|
+
'gemini-1-5-pro': 'This is a simulated response from Gemini 1.5 Pro. With its large context window, this model handles long documents and complex multi-turn conversations well.',
|
|
24
|
+
'gemini-flash': 'This is a simulated response from Gemini Flash. Optimized for ultra-fast inference, this model provides quick responses at minimal cost.',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function PlaygroundPage() {
|
|
28
|
+
const { user, loading: authLoading } = useAuth()
|
|
29
|
+
const [model, setModel] = useState(MODELS[0].id)
|
|
30
|
+
const [systemPrompt, setSystemPrompt] = useState('You are a helpful AI assistant.')
|
|
31
|
+
const [userMessage, setUserMessage] = useState('')
|
|
32
|
+
const [temperature, setTemperature] = useState(0.7)
|
|
33
|
+
const [maxTokens, setMaxTokens] = useState(1024)
|
|
34
|
+
const [response, setResponse] = useState('')
|
|
35
|
+
const [isRunning, setIsRunning] = useState(false)
|
|
36
|
+
const [tokenCount, setTokenCount] = useState<number | null>(null)
|
|
37
|
+
const [responseTime, setResponseTime] = useState<number | null>(null)
|
|
38
|
+
|
|
39
|
+
const handleRun = async () => {
|
|
40
|
+
if (!userMessage.trim() || isRunning) return
|
|
41
|
+
|
|
42
|
+
setIsRunning(true)
|
|
43
|
+
setResponse('')
|
|
44
|
+
setTokenCount(null)
|
|
45
|
+
setResponseTime(null)
|
|
46
|
+
|
|
47
|
+
const start = Date.now()
|
|
48
|
+
|
|
49
|
+
await new Promise(resolve => setTimeout(resolve, 500 + Math.random() * 500))
|
|
50
|
+
|
|
51
|
+
const demoResponse = DEMO_RESPONSES[model] || 'Response from the selected model.'
|
|
52
|
+
const fullResponse = `${demoResponse}\n\nParameters used:\n- Model: ${model}\n- Temperature: ${temperature}\n- Max Tokens: ${maxTokens}\n- System Prompt: "${systemPrompt}"\n- User Message: "${userMessage}"`
|
|
53
|
+
|
|
54
|
+
setResponse(fullResponse)
|
|
55
|
+
setTokenCount(Math.floor(fullResponse.split(/\s+/).length * 1.3))
|
|
56
|
+
setResponseTime(Date.now() - start)
|
|
57
|
+
setIsRunning(false)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (authLoading) {
|
|
61
|
+
return (
|
|
62
|
+
<div className="min-h-screen bg-background flex items-center justify-center">
|
|
63
|
+
<Loader2 className="w-8 h-8 text-primary animate-spin" />
|
|
64
|
+
</div>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!user) {
|
|
69
|
+
return (
|
|
70
|
+
<div className="min-h-screen bg-background flex items-center justify-center">
|
|
71
|
+
<Card className="p-8 bg-secondary border-border text-center max-w-md">
|
|
72
|
+
<Bot className="w-16 h-16 text-primary mx-auto mb-4" />
|
|
73
|
+
<h2 className="text-2xl font-bold text-foreground mb-2">Sign in to use Playground</h2>
|
|
74
|
+
<p className="text-muted-foreground mb-6">
|
|
75
|
+
Create an account to test AI models in the playground.
|
|
76
|
+
</p>
|
|
77
|
+
<div className="flex gap-2 justify-center">
|
|
78
|
+
<Link href="/login">
|
|
79
|
+
<Button variant="outline">Sign In</Button>
|
|
80
|
+
</Link>
|
|
81
|
+
<Link href="/signup">
|
|
82
|
+
<Button>Sign Up</Button>
|
|
83
|
+
</Link>
|
|
84
|
+
</div>
|
|
85
|
+
</Card>
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div className="min-h-screen bg-background">
|
|
92
|
+
<div className="max-w-7xl mx-auto px-4 py-8">
|
|
93
|
+
{/* Header */}
|
|
94
|
+
<div className="mb-8">
|
|
95
|
+
<h1 className="text-3xl font-bold text-foreground">API Playground</h1>
|
|
96
|
+
<p className="text-muted-foreground mt-1">
|
|
97
|
+
Test different models and parameters before integrating into your app.
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
{/* Split Layout */}
|
|
102
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
103
|
+
{/* Left Panel - Request */}
|
|
104
|
+
<Card className="p-6 bg-secondary border-border">
|
|
105
|
+
<h2 className="text-lg font-semibold text-foreground mb-4">Request</h2>
|
|
106
|
+
|
|
107
|
+
{/* Model Selection */}
|
|
108
|
+
<div className="mb-4">
|
|
109
|
+
<label className="block text-sm font-medium text-muted-foreground mb-1.5">
|
|
110
|
+
Model
|
|
111
|
+
</label>
|
|
112
|
+
<select
|
|
113
|
+
value={model}
|
|
114
|
+
onChange={(e) => setModel(e.target.value)}
|
|
115
|
+
className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-foreground text-sm focus:ring-2 focus:ring-ring"
|
|
116
|
+
>
|
|
117
|
+
{MODELS.map((m) => (
|
|
118
|
+
<option key={m.id} value={m.id} className="bg-card">
|
|
119
|
+
{m.name}
|
|
120
|
+
</option>
|
|
121
|
+
))}
|
|
122
|
+
</select>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
{/* System Prompt */}
|
|
126
|
+
<div className="mb-4">
|
|
127
|
+
<label className="block text-sm font-medium text-muted-foreground mb-1.5">
|
|
128
|
+
System Prompt
|
|
129
|
+
</label>
|
|
130
|
+
<textarea
|
|
131
|
+
value={systemPrompt}
|
|
132
|
+
onChange={(e) => setSystemPrompt(e.target.value)}
|
|
133
|
+
rows={3}
|
|
134
|
+
className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-foreground text-sm placeholder-muted-foreground focus:ring-2 focus:ring-ring resize-none"
|
|
135
|
+
placeholder="You are a helpful assistant..."
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
{/* User Message */}
|
|
140
|
+
<div className="mb-4">
|
|
141
|
+
<label className="block text-sm font-medium text-muted-foreground mb-1.5">
|
|
142
|
+
User Message
|
|
143
|
+
</label>
|
|
144
|
+
<textarea
|
|
145
|
+
value={userMessage}
|
|
146
|
+
onChange={(e) => setUserMessage(e.target.value)}
|
|
147
|
+
rows={4}
|
|
148
|
+
className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-foreground text-sm placeholder-muted-foreground focus:ring-2 focus:ring-ring resize-none"
|
|
149
|
+
placeholder="Enter your message..."
|
|
150
|
+
/>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
{/* Temperature */}
|
|
154
|
+
<div className="mb-4">
|
|
155
|
+
<div className="flex items-center justify-between mb-1.5">
|
|
156
|
+
<label className="text-sm font-medium text-muted-foreground">Temperature</label>
|
|
157
|
+
<span className="text-sm text-foreground font-mono">{temperature.toFixed(1)}</span>
|
|
158
|
+
</div>
|
|
159
|
+
<input
|
|
160
|
+
type="range"
|
|
161
|
+
min="0"
|
|
162
|
+
max="1"
|
|
163
|
+
step="0.1"
|
|
164
|
+
value={temperature}
|
|
165
|
+
onChange={(e) => setTemperature(parseFloat(e.target.value))}
|
|
166
|
+
className="w-full accent-primary"
|
|
167
|
+
/>
|
|
168
|
+
<div className="flex justify-between text-xs text-muted-foreground mt-1">
|
|
169
|
+
<span>Precise</span>
|
|
170
|
+
<span>Creative</span>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
{/* Max Tokens */}
|
|
175
|
+
<div className="mb-6">
|
|
176
|
+
<label className="block text-sm font-medium text-muted-foreground mb-1.5">
|
|
177
|
+
Max Tokens
|
|
178
|
+
</label>
|
|
179
|
+
<input
|
|
180
|
+
type="number"
|
|
181
|
+
value={maxTokens}
|
|
182
|
+
onChange={(e) => setMaxTokens(parseInt(e.target.value) || 0)}
|
|
183
|
+
min={1}
|
|
184
|
+
max={4096}
|
|
185
|
+
className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-foreground text-sm focus:ring-2 focus:ring-ring"
|
|
186
|
+
/>
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
{/* Run Button */}
|
|
190
|
+
<Button
|
|
191
|
+
className="w-full"
|
|
192
|
+
onClick={handleRun}
|
|
193
|
+
disabled={!userMessage.trim() || isRunning}
|
|
194
|
+
>
|
|
195
|
+
{isRunning ? (
|
|
196
|
+
<>
|
|
197
|
+
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
198
|
+
Running...
|
|
199
|
+
</>
|
|
200
|
+
) : (
|
|
201
|
+
<>
|
|
202
|
+
<Play className="w-4 h-4 mr-2" />
|
|
203
|
+
Run
|
|
204
|
+
</>
|
|
205
|
+
)}
|
|
206
|
+
</Button>
|
|
207
|
+
</Card>
|
|
208
|
+
|
|
209
|
+
{/* Right Panel - Response */}
|
|
210
|
+
<Card className="p-6 bg-secondary border-border flex flex-col">
|
|
211
|
+
<h2 className="text-lg font-semibold text-foreground mb-4">Response</h2>
|
|
212
|
+
|
|
213
|
+
{/* Response Area */}
|
|
214
|
+
<div className="bg-muted rounded-lg p-4 flex-1 min-h-[300px] font-mono text-sm text-foreground whitespace-pre-wrap overflow-auto">
|
|
215
|
+
{isRunning ? (
|
|
216
|
+
<div className="flex items-center gap-2 text-muted-foreground">
|
|
217
|
+
<Loader2 className="w-4 h-4 animate-spin" />
|
|
218
|
+
Generating response...
|
|
219
|
+
</div>
|
|
220
|
+
) : response ? (
|
|
221
|
+
response
|
|
222
|
+
) : (
|
|
223
|
+
<span className="text-muted-foreground">
|
|
224
|
+
Response will appear here after you click Run.
|
|
225
|
+
</span>
|
|
226
|
+
)}
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
{/* Metadata */}
|
|
230
|
+
{(tokenCount !== null || responseTime !== null) && (
|
|
231
|
+
<div className="flex gap-4 mt-4 pt-4 border-t border-border">
|
|
232
|
+
{tokenCount !== null && (
|
|
233
|
+
<div className="flex items-center gap-1.5 text-sm text-muted-foreground">
|
|
234
|
+
<Hash className="w-4 h-4" />
|
|
235
|
+
<span>{tokenCount} tokens</span>
|
|
236
|
+
</div>
|
|
237
|
+
)}
|
|
238
|
+
{responseTime !== null && (
|
|
239
|
+
<div className="flex items-center gap-1.5 text-sm text-muted-foreground">
|
|
240
|
+
<Clock className="w-4 h-4" />
|
|
241
|
+
<span>{responseTime}ms</span>
|
|
242
|
+
</div>
|
|
243
|
+
)}
|
|
244
|
+
</div>
|
|
245
|
+
)}
|
|
246
|
+
</Card>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
)
|
|
251
|
+
}
|