@digilogiclabs/create-saas-app 2.8.1 → 2.9.1
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/generators/template-generator.js +8 -8
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/shared/quality/web/src/__tests__/accessibility.test.tsx +3 -3
- package/dist/templates/web/ai-platform/template/src/app/page.tsx +207 -207
- package/dist/templates/web/ai-platform/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/base/template/src/app/dashboard/page.tsx +6 -43
- package/dist/templates/web/base/template/src/app/page.tsx +2 -2
- package/dist/templates/web/base/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/iot-dashboard/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/marketplace/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/micro-saas/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +800 -800
- package/dist/templates/web/ui-auth/template/src/app/login/page.tsx +109 -109
- package/dist/templates/web/ui-auth/template/src/app/page.tsx +3 -3
- package/dist/templates/web/ui-auth/template/src/app/signup/page.tsx +128 -128
- package/dist/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/ui-auth-ai/template/src/app/globals.css +35 -40
- package/dist/templates/web/ui-auth-ai/template/src/app/layout.tsx +1 -0
- package/dist/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +3 -3
- package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +10 -49
- package/dist/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +800 -800
- package/dist/templates/web/ui-auth-payments/template/src/app/login/page.tsx +109 -109
- package/dist/templates/web/ui-auth-payments/template/src/app/page.tsx +350 -350
- package/dist/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +506 -506
- package/dist/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +128 -128
- package/dist/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +143 -143
- package/dist/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +184 -184
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +143 -233
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +10 -50
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +800 -800
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +325 -364
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +1 -1
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +389 -532
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +644 -644
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +119 -163
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +158 -201
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +10 -51
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +402 -403
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +143 -143
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +184 -184
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +1 -1
- package/dist/templates/web/ui-auth-payments-video/template/src/app/page.tsx +3 -7
- package/dist/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +1 -1
- package/dist/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +5 -2
- package/dist/templates/web/ui-only/template/src/components/providers/app-providers.tsx +20 -26
- package/package.json +1 -1
- package/src/templates/shared/quality/web/src/__tests__/accessibility.test.tsx +3 -3
- package/src/templates/web/ai-platform/template/src/app/page.tsx +207 -207
- package/src/templates/web/ai-platform/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/base/template/src/app/dashboard/page.tsx +6 -43
- package/src/templates/web/base/template/src/app/page.tsx +2 -2
- package/src/templates/web/base/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/iot-dashboard/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/marketplace/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/micro-saas/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +800 -800
- package/src/templates/web/ui-auth/template/src/app/login/page.tsx +109 -109
- package/src/templates/web/ui-auth/template/src/app/page.tsx +3 -3
- package/src/templates/web/ui-auth/template/src/app/signup/page.tsx +128 -128
- package/src/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/ui-auth-ai/template/src/app/globals.css +35 -40
- package/src/templates/web/ui-auth-ai/template/src/app/layout.tsx +1 -0
- package/src/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +3 -3
- package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +10 -49
- package/src/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +800 -800
- package/src/templates/web/ui-auth-payments/template/src/app/login/page.tsx +109 -109
- package/src/templates/web/ui-auth-payments/template/src/app/page.tsx +350 -350
- package/src/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +506 -506
- package/src/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +128 -128
- package/src/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +143 -143
- package/src/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +184 -184
- package/src/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +143 -233
- package/src/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +10 -50
- package/src/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +800 -800
- package/src/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +325 -364
- package/src/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +1 -1
- package/src/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +389 -532
- package/src/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +644 -644
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +119 -163
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +158 -201
- package/src/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +10 -51
- package/src/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +402 -403
- package/src/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +143 -143
- package/src/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +184 -184
- package/src/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +1 -1
- package/src/templates/web/ui-auth-payments-video/template/src/app/page.tsx +3 -7
- package/src/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +1 -1
- package/src/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +5 -2
- package/src/templates/web/ui-only/template/src/components/providers/app-providers.tsx +20 -26
|
@@ -1,645 +1,645 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Card,
|
|
5
|
-
Button,
|
|
6
|
-
PageTransition,
|
|
7
|
-
MobileContainer,
|
|
8
|
-
ResponsiveGrid,
|
|
9
|
-
useAnimationTokens,
|
|
10
|
-
useGlassmorphism
|
|
11
|
-
} from '@digilogiclabs/saas-factory-ui'
|
|
12
|
-
import {
|
|
13
|
-
ArrowLeft,
|
|
14
|
-
CheckCircle,
|
|
15
|
-
AlertCircle,
|
|
16
|
-
ExternalLink,
|
|
17
|
-
Copy,
|
|
18
|
-
Database,
|
|
19
|
-
CreditCard,
|
|
20
|
-
Shield,
|
|
21
|
-
Brain,
|
|
22
|
-
Key,
|
|
23
|
-
Globe,
|
|
24
|
-
Settings,
|
|
25
|
-
BookOpen,
|
|
26
|
-
Zap,
|
|
27
|
-
Server,
|
|
28
|
-
Code2,
|
|
29
|
-
FileText
|
|
30
|
-
} from 'lucide-react'
|
|
31
|
-
import Link from 'next/link'
|
|
32
|
-
import { useState } from 'react'
|
|
33
|
-
|
|
34
|
-
interface ServiceConfig {
|
|
35
|
-
name: string
|
|
36
|
-
status: 'required' | 'optional' | 'configured'
|
|
37
|
-
icon: any
|
|
38
|
-
description: string
|
|
39
|
-
setupSteps: Array<{
|
|
40
|
-
title: string
|
|
41
|
-
description: string
|
|
42
|
-
code?: string
|
|
43
|
-
link?: string
|
|
44
|
-
}>
|
|
45
|
-
envVars: Array<{
|
|
46
|
-
name: string
|
|
47
|
-
description: string
|
|
48
|
-
example: string
|
|
49
|
-
required: boolean
|
|
50
|
-
}>
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export default function SetupPage() {
|
|
54
|
-
const animations = useAnimationTokens()
|
|
55
|
-
const glass = useGlassmorphism()
|
|
56
|
-
|
|
57
|
-
// Static glassmorphism classes to avoid template literal corruption
|
|
58
|
-
const glassCard = "bg-white/10 backdrop-blur-lg border border-white/20"
|
|
59
|
-
const glassCardRounded = "bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl"
|
|
60
|
-
const glassBackground = "bg-gradient-to-br from-purple-900/20 via-blue-900/20 to-teal-900/20"
|
|
61
|
-
const [copiedVar, setCopiedVar] = useState<string | null>(null)
|
|
62
|
-
|
|
63
|
-
const projectName = "{{projectName}}"
|
|
64
|
-
const templateName = "Full-Stack AI Platform"
|
|
65
|
-
const templateDescription = "UI + Authentication + Payments + AI (Text, Audio, Video, Chat)"
|
|
66
|
-
|
|
67
|
-
const services: ServiceConfig[] = [
|
|
68
|
-
{
|
|
69
|
-
name: "Supabase (Database & Auth)",
|
|
70
|
-
status: 'required',
|
|
71
|
-
icon: Database,
|
|
72
|
-
description: "PostgreSQL database with built-in authentication, real-time subscriptions, and edge functions.",
|
|
73
|
-
setupSteps: [
|
|
74
|
-
{
|
|
75
|
-
title: "Create Supabase Project",
|
|
76
|
-
description: "Sign up at supabase.com and create a new project",
|
|
77
|
-
link: "https://supabase.com/dashboard"
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
title: "Get API Keys",
|
|
81
|
-
description: "Go to Settings → API to find your project URL and anon key"
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
title: "Configure Authentication",
|
|
85
|
-
description: "Enable email/password auth in Authentication → Settings"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
title: "Set up Database Tables",
|
|
89
|
-
description: "Create tables for user profiles, AI conversations, and usage tracking",
|
|
90
|
-
code: `-- User profiles table
|
|
91
|
-
CREATE TABLE profiles (
|
|
92
|
-
id UUID REFERENCES auth.users(id) PRIMARY KEY,
|
|
93
|
-
email TEXT,
|
|
94
|
-
full_name TEXT,
|
|
95
|
-
avatar_url TEXT,
|
|
96
|
-
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
-- AI conversations table
|
|
100
|
-
CREATE TABLE ai_conversations (
|
|
101
|
-
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
102
|
-
user_id UUID REFERENCES profiles(id),
|
|
103
|
-
message_type TEXT NOT NULL,
|
|
104
|
-
user_message TEXT NOT NULL,
|
|
105
|
-
ai_response TEXT NOT NULL,
|
|
106
|
-
metadata JSONB,
|
|
107
|
-
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
-- Enable RLS
|
|
111
|
-
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
|
|
112
|
-
ALTER TABLE ai_conversations ENABLE ROW LEVEL SECURITY;
|
|
113
|
-
|
|
114
|
-
-- RLS Policies
|
|
115
|
-
CREATE POLICY "Users can view own profile" ON profiles FOR SELECT USING (auth.uid() = id);
|
|
116
|
-
CREATE POLICY "Users can update own profile" ON profiles FOR UPDATE USING (auth.uid() = id);
|
|
117
|
-
CREATE POLICY "Users can view own conversations" ON ai_conversations FOR ALL USING (auth.uid() = user_id);`
|
|
118
|
-
}
|
|
119
|
-
],
|
|
120
|
-
envVars: [
|
|
121
|
-
{
|
|
122
|
-
name: "NEXT_PUBLIC_SUPABASE_URL",
|
|
123
|
-
description: "Your Supabase project URL",
|
|
124
|
-
example: "https://your-project.supabase.co",
|
|
125
|
-
required: true
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
name: "NEXT_PUBLIC_SUPABASE_ANON_KEY",
|
|
129
|
-
description: "Your Supabase anonymous key",
|
|
130
|
-
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
131
|
-
required: true
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
name: "SUPABASE_SERVICE_ROLE_KEY",
|
|
135
|
-
description: "Service role key for server-side operations (optional)",
|
|
136
|
-
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
137
|
-
required: false
|
|
138
|
-
}
|
|
139
|
-
]
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
name: "Stripe (Payments)",
|
|
143
|
-
status: 'required',
|
|
144
|
-
icon: CreditCard
|
|
145
|
-
description: "Payment processing for subscriptions, one-time payments, and billing management.",
|
|
146
|
-
setupSteps: [
|
|
147
|
-
{
|
|
148
|
-
title: "Create Stripe Account",
|
|
149
|
-
description: "Sign up at stripe.com and complete account verification",
|
|
150
|
-
link: "https://dashboard.stripe.com/register"
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
title: "Get API Keys",
|
|
154
|
-
description: "Go to Developers → API keys to find your publishable and secret keys"
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
title: "Set up Products & Pricing",
|
|
158
|
-
description: "Create products and pricing plans in the Stripe dashboard"
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
title: "Configure Webhooks",
|
|
162
|
-
description: "Set up webhooks to handle payment events",
|
|
163
|
-
code: `// Add to your API route: /api/webhooks/stripe
|
|
164
|
-
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET!
|
|
165
|
-
|
|
166
|
-
const sig = headers.get('stripe-signature')!
|
|
167
|
-
const payload = await request.text()
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
const event = stripe.webhooks.constructEvent(payload, sig, endpointSecret)
|
|
171
|
-
|
|
172
|
-
switch (event.type) {
|
|
173
|
-
case 'customer.subscription.created':
|
|
174
|
-
case 'customer.subscription.updated':
|
|
175
|
-
case 'customer.subscription.deleted':
|
|
176
|
-
// Handle subscription changes
|
|
177
|
-
break
|
|
178
|
-
case 'invoice.payment_succeeded':
|
|
179
|
-
// Handle successful payments
|
|
180
|
-
break
|
|
181
|
-
}
|
|
182
|
-
} catch (err) {
|
|
183
|
-
console.error('Webhook signature verification failed:', err)
|
|
184
|
-
return new Response('Webhook Error', { status: 400 })
|
|
185
|
-
}`
|
|
186
|
-
}
|
|
187
|
-
],
|
|
188
|
-
envVars: [
|
|
189
|
-
{
|
|
190
|
-
name: "NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY",
|
|
191
|
-
description: "Your Stripe publishable key",
|
|
192
|
-
example: "pk_test_51234567890abcdef...",
|
|
193
|
-
required: true
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
name: "STRIPE_SECRET_KEY",
|
|
197
|
-
description: "Your Stripe secret key",
|
|
198
|
-
example: "sk_test_51234567890abcdef...",
|
|
199
|
-
required: true
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
name: "STRIPE_WEBHOOK_SECRET",
|
|
203
|
-
description: "Webhook endpoint secret for event verification",
|
|
204
|
-
example: "whsec_1234567890abcdef...",
|
|
205
|
-
required: true
|
|
206
|
-
}
|
|
207
|
-
]
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
name: "OpenAI (AI Provider)",
|
|
211
|
-
status: 'required',
|
|
212
|
-
icon: Brain
|
|
213
|
-
description: "Primary AI provider for text generation, chat, and other AI capabilities.",
|
|
214
|
-
setupSteps: [
|
|
215
|
-
{
|
|
216
|
-
title: "Create OpenAI Account",
|
|
217
|
-
description: "Sign up at platform.openai.com and add billing information",
|
|
218
|
-
link: "https://platform.openai.com/signup"
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
title: "Generate API Key",
|
|
222
|
-
description: "Go to API Keys section and create a new secret key"
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
title: "Set Usage Limits",
|
|
226
|
-
description: "Configure usage limits and monitoring in your OpenAI dashboard"
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
title: "Test Integration",
|
|
230
|
-
description: "Verify your API key works with a simple test request",
|
|
231
|
-
code: `// Test your OpenAI API key
|
|
232
|
-
import OpenAI from 'openai'
|
|
233
|
-
|
|
234
|
-
const openai = new OpenAI({
|
|
235
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
const response = await openai.chat.completions.create({
|
|
239
|
-
model: "gpt-4",
|
|
240
|
-
messages: [{ role: "user", content: "Hello, world!" }],
|
|
241
|
-
max_tokens: 50
|
|
242
|
-
})`
|
|
243
|
-
}
|
|
244
|
-
],
|
|
245
|
-
envVars: [
|
|
246
|
-
{
|
|
247
|
-
name: "OPENAI_API_KEY",
|
|
248
|
-
description: "Your OpenAI API key",
|
|
249
|
-
example: "sk-1234567890abcdef...",
|
|
250
|
-
required: true
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
name: "OPENAI_ORG_ID",
|
|
254
|
-
description: "Your OpenAI organization ID (optional)",
|
|
255
|
-
example: "org-1234567890abcdef",
|
|
256
|
-
required: false
|
|
257
|
-
}
|
|
258
|
-
]
|
|
259
|
-
},
|
|
260
|
-
{
|
|
261
|
-
name: "ElevenLabs (Audio AI)",
|
|
262
|
-
status: 'optional',
|
|
263
|
-
icon: Server,
|
|
264
|
-
description: "Advanced voice synthesis and audio generation for high-quality AI voices.",
|
|
265
|
-
setupSteps: [
|
|
266
|
-
{
|
|
267
|
-
title: "Create ElevenLabs Account",
|
|
268
|
-
description: "Sign up at elevenlabs.io for voice synthesis",
|
|
269
|
-
link: "https://elevenlabs.io"
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
title: "Get API Key",
|
|
273
|
-
description: "Generate an API key from your profile settings"
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
title: "Choose Voice Models",
|
|
277
|
-
description: "Select or clone voices for your audio generation needs"
|
|
278
|
-
}
|
|
279
|
-
],
|
|
280
|
-
envVars: [
|
|
281
|
-
{
|
|
282
|
-
name: "ELEVENLABS_API_KEY",
|
|
283
|
-
description: "Your ElevenLabs API key for voice synthesis",
|
|
284
|
-
example: "sk-1234567890abcdef...",
|
|
285
|
-
required: false
|
|
286
|
-
}
|
|
287
|
-
]
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
name: "Replicate (Video AI)",
|
|
291
|
-
status: 'optional',
|
|
292
|
-
icon: Globe,
|
|
293
|
-
description: "Video generation and processing using various AI models.",
|
|
294
|
-
setupSteps: [
|
|
295
|
-
{
|
|
296
|
-
title: "Create Replicate Account",
|
|
297
|
-
description: "Sign up at replicate.com for AI video generation",
|
|
298
|
-
link: "https://replicate.com"
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
title: "Get API Token",
|
|
302
|
-
description: "Generate an API token from your account settings"
|
|
303
|
-
},
|
|
304
|
-
{
|
|
305
|
-
title: "Explore Models",
|
|
306
|
-
description: "Browse video generation models in the Replicate model library"
|
|
307
|
-
}
|
|
308
|
-
],
|
|
309
|
-
envVars: [
|
|
310
|
-
{
|
|
311
|
-
name: "REPLICATE_API_TOKEN",
|
|
312
|
-
description: "Your Replicate API token for video generation",
|
|
313
|
-
example: "r8_1234567890abcdef...",
|
|
314
|
-
required: false
|
|
315
|
-
}
|
|
316
|
-
]
|
|
317
|
-
}
|
|
318
|
-
]
|
|
319
|
-
|
|
320
|
-
const allEnvVars = services.flatMap(service => service.envVars)
|
|
321
|
-
|
|
322
|
-
const copyToClipboard = async (text: string, varName: string) => {
|
|
323
|
-
await navigator.clipboard.writeText(text)
|
|
324
|
-
setCopiedVar(varName)
|
|
325
|
-
setTimeout(() => setCopiedVar(null), 2000)
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const getStatusColor = (status: ServiceConfig['status']) => {
|
|
329
|
-
switch (status) {
|
|
330
|
-
case 'required': return 'text-red-400'
|
|
331
|
-
case 'optional': return 'text-yellow-400'
|
|
332
|
-
case 'configured': return 'text-green-400'
|
|
333
|
-
default: return 'text-gray-400'
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const getStatusIcon = (status: ServiceConfig['status']) => {
|
|
338
|
-
switch (status) {
|
|
339
|
-
case 'required': return AlertCircle
|
|
340
|
-
case 'optional': return Settings
|
|
341
|
-
case 'configured': return CheckCircle
|
|
342
|
-
default: return AlertCircle
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return (
|
|
347
|
-
<PageTransition type="slide" direction="up" duration={300}>
|
|
348
|
-
<main className={`min-h-screen ${glassBackground} relative overflow-hidden`}>
|
|
349
|
-
<div className="absolute inset-0 bg-gradient-to-tr from-purple-500/10 to-blue-500/10 opacity-30" />
|
|
350
|
-
<div className="relative z-10">
|
|
351
|
-
<MobileContainer className="py-8">
|
|
352
|
-
{/* Header */}
|
|
353
|
-
<div className="flex items-center justify-between mb-8">
|
|
354
|
-
<div className="flex items-center gap-4">
|
|
355
|
-
<Link href="/" className={`${glassCard} p-2 rounded-xl ${animations.hover.scale}`}>
|
|
356
|
-
<ArrowLeft className="w-5 h-5" />
|
|
357
|
-
</Link>
|
|
358
|
-
<div>
|
|
359
|
-
<h1 className="text-2xl font-bold">Setup Guide</h1>
|
|
360
|
-
<p className="text-gray-600 dark:text-gray-300">{templateName}</p>
|
|
361
|
-
</div>
|
|
362
|
-
</div>
|
|
363
|
-
<div className={`${glassCard} px-4 py-2 rounded-xl`}>
|
|
364
|
-
<span className="text-sm font-medium">{projectName}</span>
|
|
365
|
-
</div>
|
|
366
|
-
</div>
|
|
367
|
-
|
|
368
|
-
{/* Template Overview */}
|
|
369
|
-
<div className={`${glassCardRounded} p-6 mb-8`}>
|
|
370
|
-
<div className="flex items-center gap-4 mb-4">
|
|
371
|
-
<div className={`w-12 h-12 rounded-xl bg-gradient-to-r from-purple-500 to-pink-500 flex items-center justify-center`}>
|
|
372
|
-
<Zap className="w-6 h-6 text-white" />
|
|
373
|
-
</div>
|
|
374
|
-
<div>
|
|
375
|
-
<h2 className="text-xl font-semibold">{templateName}</h2>
|
|
376
|
-
<p className="text-gray-600 dark:text-gray-300">{templateDescription}</p>
|
|
377
|
-
</div>
|
|
378
|
-
</div>
|
|
379
|
-
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mt-6">
|
|
380
|
-
<div className="text-center p-3 rounded-xl bg-blue-500/10">
|
|
381
|
-
<Shield className="w-6 h-6 text-blue-400 mx-auto mb-2" />
|
|
382
|
-
<div className="text-sm font-medium">Authentication</div>
|
|
383
|
-
</div>
|
|
384
|
-
<div className="text-center p-3 rounded-xl bg-green-500/10">
|
|
385
|
-
<CreditCard className="w-6 h-6 text-green-400 mx-auto mb-2" />
|
|
386
|
-
<div className="text-sm font-medium">Payments</div>
|
|
387
|
-
</div>
|
|
388
|
-
<div className="text-center p-3 rounded-xl bg-purple-500/10">
|
|
389
|
-
<Brain className="w-6 h-6 text-purple-400 mx-auto mb-2" />
|
|
390
|
-
<div className="text-sm font-medium">AI Platform</div>
|
|
391
|
-
</div>
|
|
392
|
-
<div className="text-center p-3 rounded-xl bg-orange-500/10">
|
|
393
|
-
<Code2 className="w-6 h-6 text-orange-400 mx-auto mb-2" />
|
|
394
|
-
<div className="text-sm font-medium">Modern UI</div>
|
|
395
|
-
</div>
|
|
396
|
-
</div>
|
|
397
|
-
</div>
|
|
398
|
-
|
|
399
|
-
{/* Quick Start */}
|
|
400
|
-
<div className={`${glassCardRounded} p-6 mb-8`}>
|
|
401
|
-
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
402
|
-
<Zap className="w-5 h-5 text-yellow-400" />
|
|
403
|
-
Quick Start
|
|
404
|
-
</h3>
|
|
405
|
-
<div className="space-y-3 text-sm">
|
|
406
|
-
<div className="flex items-center gap-3">
|
|
407
|
-
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
408
|
-
<span>1. Set up your environment variables (see below)</span>
|
|
409
|
-
</div>
|
|
410
|
-
<div className="flex items-center gap-3">
|
|
411
|
-
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
412
|
-
<span>2. Configure Supabase database and authentication</span>
|
|
413
|
-
</div>
|
|
414
|
-
<div className="flex items-center gap-3">
|
|
415
|
-
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
416
|
-
<span>3. Set up Stripe for payment processing</span>
|
|
417
|
-
</div>
|
|
418
|
-
<div className="flex items-center gap-3">
|
|
419
|
-
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
420
|
-
<span>4. Connect your AI providers (OpenAI, ElevenLabs, Replicate)</span>
|
|
421
|
-
</div>
|
|
422
|
-
<div className="flex items-center gap-3">
|
|
423
|
-
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
424
|
-
<span>5. Run <code className="px-2 py-1 bg-gray-800 rounded text-green-400">npm run dev</code> to start developing</span>
|
|
425
|
-
</div>
|
|
426
|
-
</div>
|
|
427
|
-
</div>
|
|
428
|
-
|
|
429
|
-
{/* Environment Variables */}
|
|
430
|
-
<div className={`${glassCardRounded} p-6 mb-8`}>
|
|
431
|
-
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
432
|
-
<Key className="w-5 h-5 text-blue-400" />
|
|
433
|
-
Environment Variables
|
|
434
|
-
</h3>
|
|
435
|
-
<p className="text-sm text-gray-600 dark:text-gray-300 mb-4">
|
|
436
|
-
Copy these to your <code className="px-2 py-1 bg-gray-800 rounded">.env.local</code> file:
|
|
437
|
-
</p>
|
|
438
|
-
<div className="bg-gray-900 rounded-xl p-4 overflow-x-auto">
|
|
439
|
-
<pre className="text-sm text-green-400">
|
|
440
|
-
{allEnvVars.map(envVar => (
|
|
441
|
-
`${envVar.name}=${envVar.example}${envVar.required ? ' # Required' : ' # Optional'}`
|
|
442
|
-
)).join('\n')}
|
|
443
|
-
</pre>
|
|
444
|
-
<button
|
|
445
|
-
onClick={() => copyToClipboard(
|
|
446
|
-
allEnvVars.map(envVar => `${envVar.name}=${envVar.example}`).join('\n'),
|
|
447
|
-
'all-env-vars'
|
|
448
|
-
)}
|
|
449
|
-
className="mt-3 flex items-center gap-2 text-xs text-gray-400 hover:text-white transition-colors"
|
|
450
|
-
>
|
|
451
|
-
<Copy className="w-4 h-4" />
|
|
452
|
-
{copiedVar === 'all-env-vars' ? 'Copied!' : 'Copy all environment variables'}
|
|
453
|
-
</button>
|
|
454
|
-
</div>
|
|
455
|
-
</div>
|
|
456
|
-
|
|
457
|
-
{/* Services Configuration */}
|
|
458
|
-
<div className="space-y-6">
|
|
459
|
-
<h3 className="text-lg font-semibold flex items-center gap-2">
|
|
460
|
-
<Settings className="w-5 h-5 text-gray-400" />
|
|
461
|
-
Service Configuration
|
|
462
|
-
</h3>
|
|
463
|
-
|
|
464
|
-
{services.map((service, index) => {
|
|
465
|
-
const StatusIcon = getStatusIcon(service.status)
|
|
466
|
-
const ServiceIcon = service.icon
|
|
467
|
-
|
|
468
|
-
return (
|
|
469
|
-
<div key={service.name} className={`${glassCardRounded} p-6`}>
|
|
470
|
-
<div className="flex items-start justify-between mb-4">
|
|
471
|
-
<div className="flex items-center gap-3">
|
|
472
|
-
<div className={`w-10 h-10 rounded-xl bg-gray-800 flex items-center justify-center`}>
|
|
473
|
-
<ServiceIcon className="w-5 h-5 text-white" />
|
|
474
|
-
</div>
|
|
475
|
-
<div>
|
|
476
|
-
<h4 className="text-lg font-semibold flex items-center gap-2">
|
|
477
|
-
{service.name}
|
|
478
|
-
<StatusIcon className={`w-4 h-4 ${getStatusColor(service.status)}`} />
|
|
479
|
-
</h4>
|
|
480
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">{service.description}</p>
|
|
481
|
-
</div>
|
|
482
|
-
</div>
|
|
483
|
-
<span className={`px-3 py-1 rounded-full text-xs font-medium ${
|
|
484
|
-
service.status === 'required' ? 'bg-red-500/20 text-red-400' :
|
|
485
|
-
service.status === 'optional' ? 'bg-yellow-500/20 text-yellow-400' :
|
|
486
|
-
'bg-green-500/20 text-green-400'
|
|
487
|
-
}`}>
|
|
488
|
-
{service.status}
|
|
489
|
-
</span>
|
|
490
|
-
</div>
|
|
491
|
-
|
|
492
|
-
{/* Setup Steps */}
|
|
493
|
-
<div className="mb-6">
|
|
494
|
-
<h5 className="font-semibold mb-3">Setup Steps:</h5>
|
|
495
|
-
<div className="space-y-3">
|
|
496
|
-
{service.setupSteps.map((step, stepIndex) => (
|
|
497
|
-
<div key={stepIndex} className="flex gap-3">
|
|
498
|
-
<div className="w-6 h-6 rounded-full bg-blue-500 text-white text-xs flex items-center justify-center flex-shrink-0 mt-0.5">
|
|
499
|
-
{stepIndex + 1}
|
|
500
|
-
</div>
|
|
501
|
-
<div className="flex-1">
|
|
502
|
-
<h6 className="font-medium">{step.title}</h6>
|
|
503
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">{step.description}</p>
|
|
504
|
-
{step.link && (
|
|
505
|
-
<a
|
|
506
|
-
href={step.link}
|
|
507
|
-
target="_blank"
|
|
508
|
-
rel="noopener noreferrer"
|
|
509
|
-
className="inline-flex items-center gap-1 text-sm text-blue-400 hover:text-blue-300 mt-1"
|
|
510
|
-
>
|
|
511
|
-
Open Dashboard <ExternalLink className="w-3 h-3" />
|
|
512
|
-
</a>
|
|
513
|
-
)}
|
|
514
|
-
{step.code && (
|
|
515
|
-
<details className="mt-2">
|
|
516
|
-
<summary className="text-sm text-blue-400 cursor-pointer hover:text-blue-300">
|
|
517
|
-
Show code example
|
|
518
|
-
</summary>
|
|
519
|
-
<pre className="bg-gray-900 rounded-lg p-3 mt-2 text-xs overflow-x-auto">
|
|
520
|
-
<code className="text-green-400">{step.code}</code>
|
|
521
|
-
</pre>
|
|
522
|
-
</details>
|
|
523
|
-
)}
|
|
524
|
-
</div>
|
|
525
|
-
</div>
|
|
526
|
-
))}
|
|
527
|
-
</div>
|
|
528
|
-
</div>
|
|
529
|
-
|
|
530
|
-
{/* Environment Variables for this service */}
|
|
531
|
-
<div>
|
|
532
|
-
<h5 className="font-semibold mb-3">Environment Variables:</h5>
|
|
533
|
-
<div className="space-y-2">
|
|
534
|
-
{service.envVars.map((envVar, envIndex) => (
|
|
535
|
-
<div key={envIndex} className="bg-gray-800/50 rounded-lg p-3">
|
|
536
|
-
<div className="flex items-center justify-between mb-1">
|
|
537
|
-
<code className="text-blue-400 font-mono text-sm">{envVar.name}</code>
|
|
538
|
-
<div className="flex items-center gap-2">
|
|
539
|
-
<span className={`px-2 py-1 rounded text-xs ${
|
|
540
|
-
envVar.required ? 'bg-red-500/20 text-red-400' : 'bg-gray-500/20 text-gray-400'
|
|
541
|
-
}`}>
|
|
542
|
-
{envVar.required ? 'Required' : 'Optional'}
|
|
543
|
-
</span>
|
|
544
|
-
<button
|
|
545
|
-
onClick={() => copyToClipboard(`${envVar.name}=${envVar.example}`, envVar.name)}
|
|
546
|
-
className="p-1 hover:bg-gray-700 rounded transition-colors"
|
|
547
|
-
>
|
|
548
|
-
<Copy className="w-3 h-3" />
|
|
549
|
-
</button>
|
|
550
|
-
</div>
|
|
551
|
-
</div>
|
|
552
|
-
<p className="text-xs text-gray-400 mb-2">{envVar.description}</p>
|
|
553
|
-
<code className="text-xs text-gray-500 font-mono">{envVar.example}</code>
|
|
554
|
-
{copiedVar === envVar.name && (
|
|
555
|
-
<span className="text-xs text-green-400 ml-2">Copied!</span>
|
|
556
|
-
)}
|
|
557
|
-
</div>
|
|
558
|
-
))}
|
|
559
|
-
</div>
|
|
560
|
-
</div>
|
|
561
|
-
</div>
|
|
562
|
-
)
|
|
563
|
-
})}
|
|
564
|
-
</div>
|
|
565
|
-
|
|
566
|
-
{/* Next Steps */}
|
|
567
|
-
<div className={`${glassCardRounded} p-6 mt-8`}>
|
|
568
|
-
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
569
|
-
<Zap className="w-5 h-5 text-yellow-400" />
|
|
570
|
-
Next Steps
|
|
571
|
-
</h3>
|
|
572
|
-
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
|
573
|
-
Once you've configured your services, set up your development workflow and deploy your application.
|
|
574
|
-
</p>
|
|
575
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
576
|
-
<Link
|
|
577
|
-
href="/dev-setup"
|
|
578
|
-
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
579
|
-
>
|
|
580
|
-
<Code2 className="w-8 h-8 text-purple-400 mb-2" />
|
|
581
|
-
<h4 className="font-medium">Development & Deployment</h4>
|
|
582
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">Claude AI setup and hosting guides</p>
|
|
583
|
-
</Link>
|
|
584
|
-
<Link
|
|
585
|
-
href="/"
|
|
586
|
-
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
587
|
-
>
|
|
588
|
-
<Zap className="w-8 h-8 text-blue-400 mb-2" />
|
|
589
|
-
<h4 className="font-medium">Start Building</h4>
|
|
590
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">Go to your application and start coding</p>
|
|
591
|
-
</Link>
|
|
592
|
-
</div>
|
|
593
|
-
</div>
|
|
594
|
-
|
|
595
|
-
{/* Additional Resources */}
|
|
596
|
-
<div className={`${glassCardRounded} p-6 mt-8`}>
|
|
597
|
-
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
598
|
-
<BookOpen className="w-5 h-5 text-green-400" />
|
|
599
|
-
Additional Resources
|
|
600
|
-
</h3>
|
|
601
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
602
|
-
<a
|
|
603
|
-
href="https://docs.digilogiclabs.com"
|
|
604
|
-
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
605
|
-
>
|
|
606
|
-
<FileText className="w-8 h-8 text-blue-400 mb-2" />
|
|
607
|
-
<h4 className="font-medium">Documentation</h4>
|
|
608
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">Complete guides and API reference</p>
|
|
609
|
-
</a>
|
|
610
|
-
<a
|
|
611
|
-
href="https://github.com/digilogiclabs/examples"
|
|
612
|
-
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
613
|
-
>
|
|
614
|
-
<Code2 className="w-8 h-8 text-purple-400 mb-2" />
|
|
615
|
-
<h4 className="font-medium">Examples</h4>
|
|
616
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">Sample projects and code snippets</p>
|
|
617
|
-
</a>
|
|
618
|
-
</div>
|
|
619
|
-
</div>
|
|
620
|
-
|
|
621
|
-
{/* Support */}
|
|
622
|
-
<div className={`${glass.card} ${glass.border} rounded-2xl p-6 mt-8 text-center`}>
|
|
623
|
-
<h3 className="text-lg font-semibold mb-4">Need Help?</h3>
|
|
624
|
-
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
625
|
-
Our community and support team are here to help you get started.
|
|
626
|
-
</p>
|
|
627
|
-
<div className="flex justify-center gap-4">
|
|
628
|
-
<Button variant="outline" size="sm" asChild>
|
|
629
|
-
<a href="https://discord.gg/digilogiclabs" target="_blank" rel="noopener noreferrer">
|
|
630
|
-
Join Discord
|
|
631
|
-
</a>
|
|
632
|
-
</Button>
|
|
633
|
-
<Button size="sm" asChild>
|
|
634
|
-
<a href="https://docs.digilogiclabs.com/support" target="_blank" rel="noopener noreferrer">
|
|
635
|
-
Get Support
|
|
636
|
-
</a>
|
|
637
|
-
</Button>
|
|
638
|
-
</div>
|
|
639
|
-
</div>
|
|
640
|
-
</MobileContainer>
|
|
641
|
-
</div>
|
|
642
|
-
</main>
|
|
643
|
-
</PageTransition>
|
|
644
|
-
)
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Card,
|
|
5
|
+
Button,
|
|
6
|
+
PageTransition,
|
|
7
|
+
MobileContainer,
|
|
8
|
+
ResponsiveGrid,
|
|
9
|
+
useAnimationTokens,
|
|
10
|
+
useGlassmorphism
|
|
11
|
+
} from '@digilogiclabs/saas-factory-ui'
|
|
12
|
+
import {
|
|
13
|
+
ArrowLeft,
|
|
14
|
+
CheckCircle,
|
|
15
|
+
AlertCircle,
|
|
16
|
+
ExternalLink,
|
|
17
|
+
Copy,
|
|
18
|
+
Database,
|
|
19
|
+
CreditCard,
|
|
20
|
+
Shield,
|
|
21
|
+
Brain,
|
|
22
|
+
Key,
|
|
23
|
+
Globe,
|
|
24
|
+
Settings,
|
|
25
|
+
BookOpen,
|
|
26
|
+
Zap,
|
|
27
|
+
Server,
|
|
28
|
+
Code2,
|
|
29
|
+
FileText
|
|
30
|
+
} from 'lucide-react'
|
|
31
|
+
import Link from 'next/link'
|
|
32
|
+
import { useState } from 'react'
|
|
33
|
+
|
|
34
|
+
interface ServiceConfig {
|
|
35
|
+
name: string
|
|
36
|
+
status: 'required' | 'optional' | 'configured'
|
|
37
|
+
icon: any
|
|
38
|
+
description: string
|
|
39
|
+
setupSteps: Array<{
|
|
40
|
+
title: string
|
|
41
|
+
description: string
|
|
42
|
+
code?: string
|
|
43
|
+
link?: string
|
|
44
|
+
}>
|
|
45
|
+
envVars: Array<{
|
|
46
|
+
name: string
|
|
47
|
+
description: string
|
|
48
|
+
example: string
|
|
49
|
+
required: boolean
|
|
50
|
+
}>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default function SetupPage() {
|
|
54
|
+
const animations = useAnimationTokens()
|
|
55
|
+
const glass = useGlassmorphism()
|
|
56
|
+
|
|
57
|
+
// Static glassmorphism classes to avoid template literal corruption
|
|
58
|
+
const glassCard = "bg-white/10 backdrop-blur-lg border border-white/20"
|
|
59
|
+
const glassCardRounded = "bg-white/10 backdrop-blur-lg border border-white/20 rounded-2xl"
|
|
60
|
+
const glassBackground = "bg-gradient-to-br from-purple-900/20 via-blue-900/20 to-teal-900/20"
|
|
61
|
+
const [copiedVar, setCopiedVar] = useState<string | null>(null)
|
|
62
|
+
|
|
63
|
+
const projectName = "{{projectName}}"
|
|
64
|
+
const templateName = "Full-Stack AI Platform"
|
|
65
|
+
const templateDescription = "UI + Authentication + Payments + AI (Text, Audio, Video, Chat)"
|
|
66
|
+
|
|
67
|
+
const services: ServiceConfig[] = [
|
|
68
|
+
{
|
|
69
|
+
name: "Supabase (Database & Auth)",
|
|
70
|
+
status: 'required',
|
|
71
|
+
icon: Database,
|
|
72
|
+
description: "PostgreSQL database with built-in authentication, real-time subscriptions, and edge functions.",
|
|
73
|
+
setupSteps: [
|
|
74
|
+
{
|
|
75
|
+
title: "Create Supabase Project",
|
|
76
|
+
description: "Sign up at supabase.com and create a new project",
|
|
77
|
+
link: "https://supabase.com/dashboard"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
title: "Get API Keys",
|
|
81
|
+
description: "Go to Settings → API to find your project URL and anon key"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: "Configure Authentication",
|
|
85
|
+
description: "Enable email/password auth in Authentication → Settings"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: "Set up Database Tables",
|
|
89
|
+
description: "Create tables for user profiles, AI conversations, and usage tracking",
|
|
90
|
+
code: `-- User profiles table
|
|
91
|
+
CREATE TABLE profiles (
|
|
92
|
+
id UUID REFERENCES auth.users(id) PRIMARY KEY,
|
|
93
|
+
email TEXT,
|
|
94
|
+
full_name TEXT,
|
|
95
|
+
avatar_url TEXT,
|
|
96
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
-- AI conversations table
|
|
100
|
+
CREATE TABLE ai_conversations (
|
|
101
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
102
|
+
user_id UUID REFERENCES profiles(id),
|
|
103
|
+
message_type TEXT NOT NULL,
|
|
104
|
+
user_message TEXT NOT NULL,
|
|
105
|
+
ai_response TEXT NOT NULL,
|
|
106
|
+
metadata JSONB,
|
|
107
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
-- Enable RLS
|
|
111
|
+
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
|
|
112
|
+
ALTER TABLE ai_conversations ENABLE ROW LEVEL SECURITY;
|
|
113
|
+
|
|
114
|
+
-- RLS Policies
|
|
115
|
+
CREATE POLICY "Users can view own profile" ON profiles FOR SELECT USING (auth.uid() = id);
|
|
116
|
+
CREATE POLICY "Users can update own profile" ON profiles FOR UPDATE USING (auth.uid() = id);
|
|
117
|
+
CREATE POLICY "Users can view own conversations" ON ai_conversations FOR ALL USING (auth.uid() = user_id);`
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
envVars: [
|
|
121
|
+
{
|
|
122
|
+
name: "NEXT_PUBLIC_SUPABASE_URL",
|
|
123
|
+
description: "Your Supabase project URL",
|
|
124
|
+
example: "https://your-project.supabase.co",
|
|
125
|
+
required: true
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: "NEXT_PUBLIC_SUPABASE_ANON_KEY",
|
|
129
|
+
description: "Your Supabase anonymous key",
|
|
130
|
+
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
131
|
+
required: true
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "SUPABASE_SERVICE_ROLE_KEY",
|
|
135
|
+
description: "Service role key for server-side operations (optional)",
|
|
136
|
+
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
137
|
+
required: false
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "Stripe (Payments)",
|
|
143
|
+
status: 'required',
|
|
144
|
+
icon: <CreditCard className="w-4 h-4" />,
|
|
145
|
+
description: "Payment processing for subscriptions, one-time payments, and billing management.",
|
|
146
|
+
setupSteps: [
|
|
147
|
+
{
|
|
148
|
+
title: "Create Stripe Account",
|
|
149
|
+
description: "Sign up at stripe.com and complete account verification",
|
|
150
|
+
link: "https://dashboard.stripe.com/register"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
title: "Get API Keys",
|
|
154
|
+
description: "Go to Developers → API keys to find your publishable and secret keys"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
title: "Set up Products & Pricing",
|
|
158
|
+
description: "Create products and pricing plans in the Stripe dashboard"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
title: "Configure Webhooks",
|
|
162
|
+
description: "Set up webhooks to handle payment events",
|
|
163
|
+
code: `// Add to your API route: /api/webhooks/stripe
|
|
164
|
+
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET!
|
|
165
|
+
|
|
166
|
+
const sig = headers.get('stripe-signature')!
|
|
167
|
+
const payload = await request.text()
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
const event = stripe.webhooks.constructEvent(payload, sig, endpointSecret)
|
|
171
|
+
|
|
172
|
+
switch (event.type) {
|
|
173
|
+
case 'customer.subscription.created':
|
|
174
|
+
case 'customer.subscription.updated':
|
|
175
|
+
case 'customer.subscription.deleted':
|
|
176
|
+
// Handle subscription changes
|
|
177
|
+
break
|
|
178
|
+
case 'invoice.payment_succeeded':
|
|
179
|
+
// Handle successful payments
|
|
180
|
+
break
|
|
181
|
+
}
|
|
182
|
+
} catch (err) {
|
|
183
|
+
console.error('Webhook signature verification failed:', err)
|
|
184
|
+
return new Response('Webhook Error', { status: 400 })
|
|
185
|
+
}`
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
envVars: [
|
|
189
|
+
{
|
|
190
|
+
name: "NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY",
|
|
191
|
+
description: "Your Stripe publishable key",
|
|
192
|
+
example: "pk_test_51234567890abcdef...",
|
|
193
|
+
required: true
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "STRIPE_SECRET_KEY",
|
|
197
|
+
description: "Your Stripe secret key",
|
|
198
|
+
example: "sk_test_51234567890abcdef...",
|
|
199
|
+
required: true
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: "STRIPE_WEBHOOK_SECRET",
|
|
203
|
+
description: "Webhook endpoint secret for event verification",
|
|
204
|
+
example: "whsec_1234567890abcdef...",
|
|
205
|
+
required: true
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: "OpenAI (AI Provider)",
|
|
211
|
+
status: 'required',
|
|
212
|
+
icon: <Brain className="w-4 h-4" />,
|
|
213
|
+
description: "Primary AI provider for text generation, chat, and other AI capabilities.",
|
|
214
|
+
setupSteps: [
|
|
215
|
+
{
|
|
216
|
+
title: "Create OpenAI Account",
|
|
217
|
+
description: "Sign up at platform.openai.com and add billing information",
|
|
218
|
+
link: "https://platform.openai.com/signup"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
title: "Generate API Key",
|
|
222
|
+
description: "Go to API Keys section and create a new secret key"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
title: "Set Usage Limits",
|
|
226
|
+
description: "Configure usage limits and monitoring in your OpenAI dashboard"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
title: "Test Integration",
|
|
230
|
+
description: "Verify your API key works with a simple test request",
|
|
231
|
+
code: `// Test your OpenAI API key
|
|
232
|
+
import OpenAI from 'openai'
|
|
233
|
+
|
|
234
|
+
const openai = new OpenAI({
|
|
235
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
const response = await openai.chat.completions.create({
|
|
239
|
+
model: "gpt-4",
|
|
240
|
+
messages: [{ role: "user", content: "Hello, world!" }],
|
|
241
|
+
max_tokens: 50
|
|
242
|
+
})`
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
envVars: [
|
|
246
|
+
{
|
|
247
|
+
name: "OPENAI_API_KEY",
|
|
248
|
+
description: "Your OpenAI API key",
|
|
249
|
+
example: "sk-1234567890abcdef...",
|
|
250
|
+
required: true
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "OPENAI_ORG_ID",
|
|
254
|
+
description: "Your OpenAI organization ID (optional)",
|
|
255
|
+
example: "org-1234567890abcdef",
|
|
256
|
+
required: false
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: "ElevenLabs (Audio AI)",
|
|
262
|
+
status: 'optional',
|
|
263
|
+
icon: Server,
|
|
264
|
+
description: "Advanced voice synthesis and audio generation for high-quality AI voices.",
|
|
265
|
+
setupSteps: [
|
|
266
|
+
{
|
|
267
|
+
title: "Create ElevenLabs Account",
|
|
268
|
+
description: "Sign up at elevenlabs.io for voice synthesis",
|
|
269
|
+
link: "https://elevenlabs.io"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
title: "Get API Key",
|
|
273
|
+
description: "Generate an API key from your profile settings"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
title: "Choose Voice Models",
|
|
277
|
+
description: "Select or clone voices for your audio generation needs"
|
|
278
|
+
}
|
|
279
|
+
],
|
|
280
|
+
envVars: [
|
|
281
|
+
{
|
|
282
|
+
name: "ELEVENLABS_API_KEY",
|
|
283
|
+
description: "Your ElevenLabs API key for voice synthesis",
|
|
284
|
+
example: "sk-1234567890abcdef...",
|
|
285
|
+
required: false
|
|
286
|
+
}
|
|
287
|
+
]
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "Replicate (Video AI)",
|
|
291
|
+
status: 'optional',
|
|
292
|
+
icon: Globe,
|
|
293
|
+
description: "Video generation and processing using various AI models.",
|
|
294
|
+
setupSteps: [
|
|
295
|
+
{
|
|
296
|
+
title: "Create Replicate Account",
|
|
297
|
+
description: "Sign up at replicate.com for AI video generation",
|
|
298
|
+
link: "https://replicate.com"
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
title: "Get API Token",
|
|
302
|
+
description: "Generate an API token from your account settings"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
title: "Explore Models",
|
|
306
|
+
description: "Browse video generation models in the Replicate model library"
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
envVars: [
|
|
310
|
+
{
|
|
311
|
+
name: "REPLICATE_API_TOKEN",
|
|
312
|
+
description: "Your Replicate API token for video generation",
|
|
313
|
+
example: "r8_1234567890abcdef...",
|
|
314
|
+
required: false
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
|
|
320
|
+
const allEnvVars = services.flatMap(service => service.envVars)
|
|
321
|
+
|
|
322
|
+
const copyToClipboard = async (text: string, varName: string) => {
|
|
323
|
+
await navigator.clipboard.writeText(text)
|
|
324
|
+
setCopiedVar(varName)
|
|
325
|
+
setTimeout(() => setCopiedVar(null), 2000)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const getStatusColor = (status: ServiceConfig['status']) => {
|
|
329
|
+
switch (status) {
|
|
330
|
+
case 'required': return 'text-red-400'
|
|
331
|
+
case 'optional': return 'text-yellow-400'
|
|
332
|
+
case 'configured': return 'text-green-400'
|
|
333
|
+
default: return 'text-gray-400'
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const getStatusIcon = (status: ServiceConfig['status']) => {
|
|
338
|
+
switch (status) {
|
|
339
|
+
case 'required': return AlertCircle
|
|
340
|
+
case 'optional': return Settings
|
|
341
|
+
case 'configured': return CheckCircle
|
|
342
|
+
default: return AlertCircle
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return (
|
|
347
|
+
<PageTransition type="slide" direction="up" duration={300}>
|
|
348
|
+
<main className={`min-h-screen ${glassBackground} relative overflow-hidden`}>
|
|
349
|
+
<div className="absolute inset-0 bg-gradient-to-tr from-purple-500/10 to-blue-500/10 opacity-30" />
|
|
350
|
+
<div className="relative z-10">
|
|
351
|
+
<MobileContainer className="py-8">
|
|
352
|
+
{/* Header */}
|
|
353
|
+
<div className="flex items-center justify-between mb-8">
|
|
354
|
+
<div className="flex items-center gap-4">
|
|
355
|
+
<Link href="/" className={`${glassCard} p-2 rounded-xl ${animations.hover.scale}`}>
|
|
356
|
+
<ArrowLeft className="w-5 h-5" />
|
|
357
|
+
</Link>
|
|
358
|
+
<div>
|
|
359
|
+
<h1 className="text-2xl font-bold">Setup Guide</h1>
|
|
360
|
+
<p className="text-gray-600 dark:text-gray-300">{templateName}</p>
|
|
361
|
+
</div>
|
|
362
|
+
</div>
|
|
363
|
+
<div className={`${glassCard} px-4 py-2 rounded-xl`}>
|
|
364
|
+
<span className="text-sm font-medium">{projectName}</span>
|
|
365
|
+
</div>
|
|
366
|
+
</div>
|
|
367
|
+
|
|
368
|
+
{/* Template Overview */}
|
|
369
|
+
<div className={`${glassCardRounded} p-6 mb-8`}>
|
|
370
|
+
<div className="flex items-center gap-4 mb-4">
|
|
371
|
+
<div className={`w-12 h-12 rounded-xl bg-gradient-to-r from-purple-500 to-pink-500 flex items-center justify-center`}>
|
|
372
|
+
<Zap className="w-6 h-6 text-white" />
|
|
373
|
+
</div>
|
|
374
|
+
<div>
|
|
375
|
+
<h2 className="text-xl font-semibold">{templateName}</h2>
|
|
376
|
+
<p className="text-gray-600 dark:text-gray-300">{templateDescription}</p>
|
|
377
|
+
</div>
|
|
378
|
+
</div>
|
|
379
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mt-6">
|
|
380
|
+
<div className="text-center p-3 rounded-xl bg-blue-500/10">
|
|
381
|
+
<Shield className="w-6 h-6 text-blue-400 mx-auto mb-2" />
|
|
382
|
+
<div className="text-sm font-medium">Authentication</div>
|
|
383
|
+
</div>
|
|
384
|
+
<div className="text-center p-3 rounded-xl bg-green-500/10">
|
|
385
|
+
<CreditCard className="w-6 h-6 text-green-400 mx-auto mb-2" />
|
|
386
|
+
<div className="text-sm font-medium">Payments</div>
|
|
387
|
+
</div>
|
|
388
|
+
<div className="text-center p-3 rounded-xl bg-purple-500/10">
|
|
389
|
+
<Brain className="w-6 h-6 text-purple-400 mx-auto mb-2" />
|
|
390
|
+
<div className="text-sm font-medium">AI Platform</div>
|
|
391
|
+
</div>
|
|
392
|
+
<div className="text-center p-3 rounded-xl bg-orange-500/10">
|
|
393
|
+
<Code2 className="w-6 h-6 text-orange-400 mx-auto mb-2" />
|
|
394
|
+
<div className="text-sm font-medium">Modern UI</div>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
|
|
399
|
+
{/* Quick Start */}
|
|
400
|
+
<div className={`${glassCardRounded} p-6 mb-8`}>
|
|
401
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
402
|
+
<Zap className="w-5 h-5 text-yellow-400" />
|
|
403
|
+
Quick Start
|
|
404
|
+
</h3>
|
|
405
|
+
<div className="space-y-3 text-sm">
|
|
406
|
+
<div className="flex items-center gap-3">
|
|
407
|
+
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
408
|
+
<span>1. Set up your environment variables (see below)</span>
|
|
409
|
+
</div>
|
|
410
|
+
<div className="flex items-center gap-3">
|
|
411
|
+
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
412
|
+
<span>2. Configure Supabase database and authentication</span>
|
|
413
|
+
</div>
|
|
414
|
+
<div className="flex items-center gap-3">
|
|
415
|
+
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
416
|
+
<span>3. Set up Stripe for payment processing</span>
|
|
417
|
+
</div>
|
|
418
|
+
<div className="flex items-center gap-3">
|
|
419
|
+
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
420
|
+
<span>4. Connect your AI providers (OpenAI, ElevenLabs, Replicate)</span>
|
|
421
|
+
</div>
|
|
422
|
+
<div className="flex items-center gap-3">
|
|
423
|
+
<CheckCircle className="w-5 h-5 text-green-400" />
|
|
424
|
+
<span>5. Run <code className="px-2 py-1 bg-gray-800 rounded text-green-400">npm run dev</code> to start developing</span>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
|
|
429
|
+
{/* Environment Variables */}
|
|
430
|
+
<div className={`${glassCardRounded} p-6 mb-8`}>
|
|
431
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
432
|
+
<Key className="w-5 h-5 text-blue-400" />
|
|
433
|
+
Environment Variables
|
|
434
|
+
</h3>
|
|
435
|
+
<p className="text-sm text-gray-600 dark:text-gray-300 mb-4">
|
|
436
|
+
Copy these to your <code className="px-2 py-1 bg-gray-800 rounded">.env.local</code> file:
|
|
437
|
+
</p>
|
|
438
|
+
<div className="bg-gray-900 rounded-xl p-4 overflow-x-auto">
|
|
439
|
+
<pre className="text-sm text-green-400">
|
|
440
|
+
{allEnvVars.map(envVar => (
|
|
441
|
+
`${envVar.name}=${envVar.example}${envVar.required ? ' # Required' : ' # Optional'}`
|
|
442
|
+
)).join('\n')}
|
|
443
|
+
</pre>
|
|
444
|
+
<button
|
|
445
|
+
onClick={() => copyToClipboard(
|
|
446
|
+
allEnvVars.map(envVar => `${envVar.name}=${envVar.example}`).join('\n'),
|
|
447
|
+
'all-env-vars'
|
|
448
|
+
)}
|
|
449
|
+
className="mt-3 flex items-center gap-2 text-xs text-gray-400 hover:text-white transition-colors"
|
|
450
|
+
>
|
|
451
|
+
<Copy className="w-4 h-4" />
|
|
452
|
+
{copiedVar === 'all-env-vars' ? 'Copied!' : 'Copy all environment variables'}
|
|
453
|
+
</button>
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
|
|
457
|
+
{/* Services Configuration */}
|
|
458
|
+
<div className="space-y-6">
|
|
459
|
+
<h3 className="text-lg font-semibold flex items-center gap-2">
|
|
460
|
+
<Settings className="w-5 h-5 text-gray-400" />
|
|
461
|
+
Service Configuration
|
|
462
|
+
</h3>
|
|
463
|
+
|
|
464
|
+
{services.map((service, index) => {
|
|
465
|
+
const StatusIcon = getStatusIcon(service.status)
|
|
466
|
+
const ServiceIcon = service.icon
|
|
467
|
+
|
|
468
|
+
return (
|
|
469
|
+
<div key={service.name} className={`${glassCardRounded} p-6`}>
|
|
470
|
+
<div className="flex items-start justify-between mb-4">
|
|
471
|
+
<div className="flex items-center gap-3">
|
|
472
|
+
<div className={`w-10 h-10 rounded-xl bg-gray-800 flex items-center justify-center`}>
|
|
473
|
+
<ServiceIcon className="w-5 h-5 text-white" />
|
|
474
|
+
</div>
|
|
475
|
+
<div>
|
|
476
|
+
<h4 className="text-lg font-semibold flex items-center gap-2">
|
|
477
|
+
{service.name}
|
|
478
|
+
<StatusIcon className={`w-4 h-4 ${getStatusColor(service.status)}`} />
|
|
479
|
+
</h4>
|
|
480
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">{service.description}</p>
|
|
481
|
+
</div>
|
|
482
|
+
</div>
|
|
483
|
+
<span className={`px-3 py-1 rounded-full text-xs font-medium ${
|
|
484
|
+
service.status === 'required' ? 'bg-red-500/20 text-red-400' :
|
|
485
|
+
service.status === 'optional' ? 'bg-yellow-500/20 text-yellow-400' :
|
|
486
|
+
'bg-green-500/20 text-green-400'
|
|
487
|
+
}`}>
|
|
488
|
+
{service.status}
|
|
489
|
+
</span>
|
|
490
|
+
</div>
|
|
491
|
+
|
|
492
|
+
{/* Setup Steps */}
|
|
493
|
+
<div className="mb-6">
|
|
494
|
+
<h5 className="font-semibold mb-3">Setup Steps:</h5>
|
|
495
|
+
<div className="space-y-3">
|
|
496
|
+
{service.setupSteps.map((step, stepIndex) => (
|
|
497
|
+
<div key={stepIndex} className="flex gap-3">
|
|
498
|
+
<div className="w-6 h-6 rounded-full bg-blue-500 text-white text-xs flex items-center justify-center flex-shrink-0 mt-0.5">
|
|
499
|
+
{stepIndex + 1}
|
|
500
|
+
</div>
|
|
501
|
+
<div className="flex-1">
|
|
502
|
+
<h6 className="font-medium">{step.title}</h6>
|
|
503
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">{step.description}</p>
|
|
504
|
+
{step.link && (
|
|
505
|
+
<a
|
|
506
|
+
href={step.link}
|
|
507
|
+
target="_blank"
|
|
508
|
+
rel="noopener noreferrer"
|
|
509
|
+
className="inline-flex items-center gap-1 text-sm text-blue-400 hover:text-blue-300 mt-1"
|
|
510
|
+
>
|
|
511
|
+
Open Dashboard <ExternalLink className="w-3 h-3" />
|
|
512
|
+
</a>
|
|
513
|
+
)}
|
|
514
|
+
{step.code && (
|
|
515
|
+
<details className="mt-2">
|
|
516
|
+
<summary className="text-sm text-blue-400 cursor-pointer hover:text-blue-300">
|
|
517
|
+
Show code example
|
|
518
|
+
</summary>
|
|
519
|
+
<pre className="bg-gray-900 rounded-lg p-3 mt-2 text-xs overflow-x-auto">
|
|
520
|
+
<code className="text-green-400">{step.code}</code>
|
|
521
|
+
</pre>
|
|
522
|
+
</details>
|
|
523
|
+
)}
|
|
524
|
+
</div>
|
|
525
|
+
</div>
|
|
526
|
+
))}
|
|
527
|
+
</div>
|
|
528
|
+
</div>
|
|
529
|
+
|
|
530
|
+
{/* Environment Variables for this service */}
|
|
531
|
+
<div>
|
|
532
|
+
<h5 className="font-semibold mb-3">Environment Variables:</h5>
|
|
533
|
+
<div className="space-y-2">
|
|
534
|
+
{service.envVars.map((envVar, envIndex) => (
|
|
535
|
+
<div key={envIndex} className="bg-gray-800/50 rounded-lg p-3">
|
|
536
|
+
<div className="flex items-center justify-between mb-1">
|
|
537
|
+
<code className="text-blue-400 font-mono text-sm">{envVar.name}</code>
|
|
538
|
+
<div className="flex items-center gap-2">
|
|
539
|
+
<span className={`px-2 py-1 rounded text-xs ${
|
|
540
|
+
envVar.required ? 'bg-red-500/20 text-red-400' : 'bg-gray-500/20 text-gray-400'
|
|
541
|
+
}`}>
|
|
542
|
+
{envVar.required ? 'Required' : 'Optional'}
|
|
543
|
+
</span>
|
|
544
|
+
<button
|
|
545
|
+
onClick={() => copyToClipboard(`${envVar.name}=${envVar.example}`, envVar.name)}
|
|
546
|
+
className="p-1 hover:bg-gray-700 rounded transition-colors"
|
|
547
|
+
>
|
|
548
|
+
<Copy className="w-3 h-3" />
|
|
549
|
+
</button>
|
|
550
|
+
</div>
|
|
551
|
+
</div>
|
|
552
|
+
<p className="text-xs text-gray-400 mb-2">{envVar.description}</p>
|
|
553
|
+
<code className="text-xs text-gray-500 font-mono">{envVar.example}</code>
|
|
554
|
+
{copiedVar === envVar.name && (
|
|
555
|
+
<span className="text-xs text-green-400 ml-2">Copied!</span>
|
|
556
|
+
)}
|
|
557
|
+
</div>
|
|
558
|
+
))}
|
|
559
|
+
</div>
|
|
560
|
+
</div>
|
|
561
|
+
</div>
|
|
562
|
+
)
|
|
563
|
+
})}
|
|
564
|
+
</div>
|
|
565
|
+
|
|
566
|
+
{/* Next Steps */}
|
|
567
|
+
<div className={`${glassCardRounded} p-6 mt-8`}>
|
|
568
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
569
|
+
<Zap className="w-5 h-5 text-yellow-400" />
|
|
570
|
+
Next Steps
|
|
571
|
+
</h3>
|
|
572
|
+
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
|
573
|
+
Once you've configured your services, set up your development workflow and deploy your application.
|
|
574
|
+
</p>
|
|
575
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
576
|
+
<Link
|
|
577
|
+
href="/dev-setup"
|
|
578
|
+
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
579
|
+
>
|
|
580
|
+
<Code2 className="w-8 h-8 text-purple-400 mb-2" />
|
|
581
|
+
<h4 className="font-medium">Development & Deployment</h4>
|
|
582
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Claude AI setup and hosting guides</p>
|
|
583
|
+
</Link>
|
|
584
|
+
<Link
|
|
585
|
+
href="/"
|
|
586
|
+
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
587
|
+
>
|
|
588
|
+
<Zap className="w-8 h-8 text-blue-400 mb-2" />
|
|
589
|
+
<h4 className="font-medium">Start Building</h4>
|
|
590
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Go to your application and start coding</p>
|
|
591
|
+
</Link>
|
|
592
|
+
</div>
|
|
593
|
+
</div>
|
|
594
|
+
|
|
595
|
+
{/* Additional Resources */}
|
|
596
|
+
<div className={`${glassCardRounded} p-6 mt-8`}>
|
|
597
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
598
|
+
<BookOpen className="w-5 h-5 text-green-400" />
|
|
599
|
+
Additional Resources
|
|
600
|
+
</h3>
|
|
601
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
602
|
+
<a
|
|
603
|
+
href="https://docs.digilogiclabs.com"
|
|
604
|
+
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
605
|
+
>
|
|
606
|
+
<FileText className="w-8 h-8 text-blue-400 mb-2" />
|
|
607
|
+
<h4 className="font-medium">Documentation</h4>
|
|
608
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Complete guides and API reference</p>
|
|
609
|
+
</a>
|
|
610
|
+
<a
|
|
611
|
+
href="https://github.com/digilogiclabs/examples"
|
|
612
|
+
className={`${glassCard} p-4 rounded-xl ${animations.hover.scale} block`}
|
|
613
|
+
>
|
|
614
|
+
<Code2 className="w-8 h-8 text-purple-400 mb-2" />
|
|
615
|
+
<h4 className="font-medium">Examples</h4>
|
|
616
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Sample projects and code snippets</p>
|
|
617
|
+
</a>
|
|
618
|
+
</div>
|
|
619
|
+
</div>
|
|
620
|
+
|
|
621
|
+
{/* Support */}
|
|
622
|
+
<div className={`${glass.card} ${glass.border} rounded-2xl p-6 mt-8 text-center`}>
|
|
623
|
+
<h3 className="text-lg font-semibold mb-4">Need Help?</h3>
|
|
624
|
+
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
625
|
+
Our community and support team are here to help you get started.
|
|
626
|
+
</p>
|
|
627
|
+
<div className="flex justify-center gap-4">
|
|
628
|
+
<Button variant="outline" size="sm" asChild>
|
|
629
|
+
<a href="https://discord.gg/digilogiclabs" target="_blank" rel="noopener noreferrer">
|
|
630
|
+
Join Discord
|
|
631
|
+
</a>
|
|
632
|
+
</Button>
|
|
633
|
+
<Button size="sm" asChild>
|
|
634
|
+
<a href="https://docs.digilogiclabs.com/support" target="_blank" rel="noopener noreferrer">
|
|
635
|
+
Get Support
|
|
636
|
+
</a>
|
|
637
|
+
</Button>
|
|
638
|
+
</div>
|
|
639
|
+
</div>
|
|
640
|
+
</MobileContainer>
|
|
641
|
+
</div>
|
|
642
|
+
</main>
|
|
643
|
+
</PageTransition>
|
|
644
|
+
)
|
|
645
645
|
}
|