@digilogiclabs/create-saas-app 1.1.0 → 1.1.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/CHANGELOG.md +1 -1
- package/bin/index.js +36 -3
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.js +390 -20094
- package/dist/index.js.map +1 -1
- package/dist/mobile/base/template/.env.example +15 -0
- package/dist/templates/mobile/base/template/.env.example +15 -0
- package/dist/templates/mobile/base/template/App.tsx +88 -0
- package/dist/templates/mobile/base/template/app/(auth)/login.tsx +44 -0
- package/dist/templates/mobile/base/template/app/(auth)/signup.tsx +43 -0
- package/dist/templates/mobile/base/template/app/checkout.tsx +20 -0
- package/dist/templates/mobile/base/template/package.json +38 -0
- package/dist/templates/shared/auth/firebase/web/config.ts +23 -0
- package/dist/templates/shared/auth/supabase/web/config.ts +8 -0
- package/dist/templates/web/base/template/.env.example +15 -0
- package/dist/templates/web/base/template/.eslintrc.js +8 -0
- package/dist/templates/web/base/template/README.md +68 -0
- package/dist/templates/web/base/template/next.config.js +15 -0
- package/dist/templates/web/base/template/package.json +48 -0
- package/dist/templates/web/base/template/postcss.config.js +7 -0
- package/dist/templates/web/base/template/src/app/auth/callback/route.ts +18 -0
- package/dist/templates/web/base/template/src/app/checkout/page.tsx +28 -0
- package/dist/templates/web/base/template/src/app/globals.css +60 -0
- package/dist/templates/web/base/template/src/app/layout.tsx +29 -0
- package/dist/templates/web/base/template/src/app/login/page.tsx +39 -0
- package/dist/templates/web/base/template/src/app/page.tsx +132 -0
- package/dist/templates/web/base/template/src/app/signup/page.tsx +39 -0
- package/dist/templates/web/base/template/src/components/providers/app-providers.tsx +29 -0
- package/dist/templates/web/base/template/src/components/shared/header.tsx +42 -0
- package/dist/templates/web/base/template/src/components/ui/badge.tsx +36 -0
- package/dist/templates/web/base/template/src/components/ui/button.tsx +56 -0
- package/dist/templates/web/base/template/src/components/ui/card.tsx +71 -0
- package/dist/templates/web/base/template/src/lib/utils.ts +7 -0
- package/dist/templates/web/base/template/tailwind.config.js +77 -0
- package/dist/templates/web/base/template/tsconfig.json +33 -0
- package/dist/templates/web/base/template.backup/.env.example +15 -0
- package/dist/templates/web/base/template.backup.20250817/.env.example +15 -0
- package/dist/templates/web/ui-package-test/template/package.json +42 -0
- package/dist/templates/web/ui-package-test/template/src/app/page.tsx +106 -0
- package/dist/templates/web/ui-package-test/template/tsconfig.json +41 -0
- package/dist/templates/web/web-ui-package/template/.env.example +15 -0
- package/dist/templates/web/web-ui-package/template/.eslintrc.js +8 -0
- package/dist/templates/web/web-ui-package/template/README.md +68 -0
- package/dist/templates/web/web-ui-package/template/next.config.js +15 -0
- package/dist/templates/web/web-ui-package/template/package.json +39 -0
- package/dist/templates/web/web-ui-package/template/postcss.config.js +7 -0
- package/dist/templates/web/web-ui-package/template/src/app/auth/callback/route.ts +18 -0
- package/dist/templates/web/web-ui-package/template/src/app/checkout/page.tsx +28 -0
- package/dist/templates/web/web-ui-package/template/src/app/globals.css +42 -0
- package/dist/templates/web/web-ui-package/template/src/app/layout.tsx +29 -0
- package/dist/templates/web/web-ui-package/template/src/app/login/page.tsx +39 -0
- package/dist/templates/web/web-ui-package/template/src/app/page.tsx +91 -0
- package/dist/templates/web/web-ui-package/template/src/app/signup/page.tsx +39 -0
- package/dist/templates/web/web-ui-package/template/src/components/providers/app-providers.tsx +29 -0
- package/dist/templates/web/web-ui-package/template/src/components/shared/header.tsx +42 -0
- package/dist/templates/web/web-ui-package/template/src/components/ui/badge.tsx +36 -0
- package/dist/templates/web/web-ui-package/template/src/lib/utils.ts +7 -0
- package/dist/templates/web/web-ui-package/template/tailwind.config.js +77 -0
- package/dist/templates/web/web-ui-package/template/tsconfig.json +33 -0
- package/dist/templates/web/web-ui-package/template.backup/.env.example +15 -0
- package/dist/templates/web/web-ui-package/template.backup.20250817/.env.example +15 -0
- package/dist/web/base/template/.env.example +15 -0
- package/dist/web/base/template/.eslintrc.js +8 -0
- package/dist/web/base/template.backup/.env.example +15 -0
- package/dist/web/base/template.backup.20250817/.env.example +15 -0
- package/dist/web/ui-package-test/template/.env.example +15 -0
- package/dist/web/ui-package-test/template/.eslintrc.js +8 -0
- package/dist/web/ui-package-test/template.backup/.env.example +15 -0
- package/dist/web/ui-package-test/template.backup.20250817/.env.example +15 -0
- package/dist/web/web-ui-package/template/.env.example +15 -0
- package/dist/web/web-ui-package/template/.eslintrc.js +8 -0
- package/dist/web/web-ui-package/template.backup/.env.example +15 -0
- package/dist/web/web-ui-package/template.backup.20250817/.env.example +15 -0
- package/package.json +105 -105
- package/src/templates/mobile/base/template/.env.example +15 -0
- package/src/templates/mobile/base/template/App.tsx +51 -10
- package/src/templates/mobile/base/template/app/(auth)/login.tsx +44 -0
- package/src/templates/mobile/base/template/app/(auth)/signup.tsx +43 -0
- package/src/templates/mobile/base/template/app/checkout.tsx +20 -0
- package/src/templates/mobile/base/template/package.json +6 -6
- package/src/templates/shared/auth/firebase/web/config.ts +23 -24
- package/src/templates/shared/auth/supabase/web/config.ts +8 -9
- package/src/templates/web/base/template/.env.example +12 -31
- package/src/templates/web/base/template/package.json +6 -6
- package/src/templates/web/base/template/src/app/auth/callback/route.ts +18 -0
- package/src/templates/web/base/template/src/app/checkout/page.tsx +28 -0
- package/src/templates/web/base/template/src/app/layout.tsx +2 -1
- package/src/templates/web/base/template/src/app/login/page.tsx +39 -0
- package/src/templates/web/base/template/src/app/page.tsx +33 -9
- package/src/templates/web/base/template/src/app/signup/page.tsx +39 -0
- package/src/templates/web/base/template/src/components/providers/app-providers.tsx +17 -9
- package/src/templates/web/base/template/src/components/shared/header.tsx +42 -0
- package/src/templates/web/base/template/tailwind.config.js +1 -1
- package/src/templates/web/base/template.backup/.env.example +15 -0
- package/src/templates/web/base/template.backup.20250817/.env.example +15 -0
- package/src/templates/web/ui-package-test/template/next-env.d.ts +5 -0
- package/src/templates/web/ui-package-test/template/package.json +42 -0
- package/src/templates/web/ui-package-test/template/src/app/page.tsx +106 -0
- package/src/templates/web/ui-package-test/template/tsconfig.json +41 -0
- package/src/templates/web/web-ui-package/template/.env.example +15 -0
- package/src/templates/web/web-ui-package/template/.eslintrc.js +8 -0
- package/src/templates/web/web-ui-package/template/README.md +68 -0
- package/src/templates/web/web-ui-package/template/next.config.js +15 -0
- package/src/templates/web/web-ui-package/template/package.json +39 -0
- package/src/templates/web/web-ui-package/template/postcss.config.js +7 -0
- package/src/templates/web/web-ui-package/template/src/app/auth/callback/route.ts +18 -0
- package/src/templates/web/web-ui-package/template/src/app/checkout/page.tsx +28 -0
- package/src/templates/web/web-ui-package/template/src/app/globals.css +42 -0
- package/src/templates/web/web-ui-package/template/src/app/layout.tsx +29 -0
- package/src/templates/web/web-ui-package/template/src/app/login/page.tsx +39 -0
- package/src/templates/web/web-ui-package/template/src/app/page.tsx +91 -0
- package/src/templates/web/web-ui-package/template/src/app/signup/page.tsx +39 -0
- package/src/templates/web/web-ui-package/template/src/components/providers/app-providers.tsx +29 -0
- package/src/templates/web/web-ui-package/template/src/components/shared/header.tsx +42 -0
- package/src/templates/web/web-ui-package/template/src/components/ui/badge.tsx +36 -0
- package/src/templates/web/web-ui-package/template/src/lib/utils.ts +7 -0
- package/src/templates/web/web-ui-package/template/tailwind.config.js +77 -0
- package/src/templates/web/web-ui-package/template/tsconfig.json +33 -0
- package/src/templates/web/web-ui-package/template.backup/.env.example +15 -0
- package/src/templates/web/web-ui-package/template.backup.20250817/.env.example +15 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Auth Configuration
|
|
2
|
+
NEXT_PUBLIC_AUTH_PROVIDER=supabase|firebase
|
|
3
|
+
|
|
4
|
+
# Supabase
|
|
5
|
+
NEXT_PUBLIC_SUPABASE_URL=
|
|
6
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
7
|
+
|
|
8
|
+
# Firebase
|
|
9
|
+
NEXT_PUBLIC_FIREBASE_API_KEY=
|
|
10
|
+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
|
|
11
|
+
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
|
|
12
|
+
|
|
13
|
+
# Payments
|
|
14
|
+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
|
15
|
+
STRIPE_SECRET_KEY=
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Auth Configuration
|
|
2
|
+
NEXT_PUBLIC_AUTH_PROVIDER=supabase|firebase
|
|
3
|
+
|
|
4
|
+
# Supabase
|
|
5
|
+
NEXT_PUBLIC_SUPABASE_URL=
|
|
6
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
7
|
+
|
|
8
|
+
# Firebase
|
|
9
|
+
NEXT_PUBLIC_FIREBASE_API_KEY=
|
|
10
|
+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
|
|
11
|
+
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
|
|
12
|
+
|
|
13
|
+
# Payments
|
|
14
|
+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
|
15
|
+
STRIPE_SECRET_KEY=
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StatusBar } from 'expo-status-bar';
|
|
3
|
+
import { StyleSheet, Text, View, Button } from 'react-native';
|
|
4
|
+
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
5
|
+
import { AuthProvider, useAuth } from '@digilogiclabs/saas-factory-auth/native';
|
|
6
|
+
import { StripeProvider } from '@digilogiclabs/saas-factory-payments/native';
|
|
7
|
+
import { Link, Slot } from 'expo-router';
|
|
8
|
+
|
|
9
|
+
function AppContent() {
|
|
10
|
+
const { user, signOut } = useAuth();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<View style={styles.container}>
|
|
14
|
+
{user ? (
|
|
15
|
+
<>
|
|
16
|
+
<Text style={styles.title}>Welcome back!</Text>
|
|
17
|
+
<Text style={styles.subtitle}>You are signed in.</Text>
|
|
18
|
+
<Link href="/checkout" style={styles.link}>
|
|
19
|
+
<Text>Checkout</Text>
|
|
20
|
+
</Link>
|
|
21
|
+
<Button title="Sign Out" onPress={signOut} />
|
|
22
|
+
</>
|
|
23
|
+
) : (
|
|
24
|
+
<>
|
|
25
|
+
<Text style={styles.title}>Welcome to {{titleCaseName}}</Text>
|
|
26
|
+
<Text style={styles.subtitle}>{{description}}</Text>
|
|
27
|
+
<Link href="/login" style={styles.link}>
|
|
28
|
+
<Text>Login</Text>
|
|
29
|
+
</Link>
|
|
30
|
+
<Link href="/signup" style={styles.link}>
|
|
31
|
+
<Text>Sign Up</Text>
|
|
32
|
+
</Link>
|
|
33
|
+
</>
|
|
34
|
+
)}
|
|
35
|
+
<StatusBar style="auto" />
|
|
36
|
+
</View>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default function App() {
|
|
41
|
+
return (
|
|
42
|
+
<SafeAreaProvider>
|
|
43
|
+
<AuthProvider>
|
|
44
|
+
<StripeProvider
|
|
45
|
+
stripeKey={process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY!}
|
|
46
|
+
>
|
|
47
|
+
<AppContent />
|
|
48
|
+
</StripeProvider>
|
|
49
|
+
</AuthProvider>
|
|
50
|
+
</SafeAreaProvider>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const styles = StyleSheet.create({
|
|
55
|
+
container: {
|
|
56
|
+
flex: 1,
|
|
57
|
+
backgroundColor: '#fff',
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
justifyContent: 'center',
|
|
60
|
+
padding: 20,
|
|
61
|
+
},
|
|
62
|
+
title: {
|
|
63
|
+
fontSize: 24,
|
|
64
|
+
fontWeight: 'bold',
|
|
65
|
+
marginBottom: 10,
|
|
66
|
+
textAlign: 'center',
|
|
67
|
+
},
|
|
68
|
+
subtitle: {
|
|
69
|
+
fontSize: 16,
|
|
70
|
+
color: '#666',
|
|
71
|
+
marginBottom: 20,
|
|
72
|
+
textAlign: 'center',
|
|
73
|
+
},
|
|
74
|
+
description: {
|
|
75
|
+
fontSize: 14,
|
|
76
|
+
color: '#999',
|
|
77
|
+
textAlign: 'center',
|
|
78
|
+
},
|
|
79
|
+
link: {
|
|
80
|
+
marginTop: 15,
|
|
81
|
+
paddingVertical: 15,
|
|
82
|
+
borderWidth: 1,
|
|
83
|
+
borderColor: '#DDD',
|
|
84
|
+
borderRadius: 5,
|
|
85
|
+
textAlign: 'center',
|
|
86
|
+
width: '80%',
|
|
87
|
+
},
|
|
88
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { LoginForm } from '@digilogiclabs/saas-factory-ui/native';
|
|
2
|
+
import { AuthProvider } from '@digilogiclabs/saas-factory-auth/native';
|
|
3
|
+
import { createBrowserClient } from '@supabase/ssr';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { View } from 'react-native';
|
|
6
|
+
import * as WebBrowser from 'expo-web-browser';
|
|
7
|
+
import { useOAuth } from '@clerk/clerk-expo';
|
|
8
|
+
|
|
9
|
+
export default function LoginPage() {
|
|
10
|
+
const supabase = createBrowserClient(
|
|
11
|
+
process.env.EXPO_PUBLIC_SUPABASE_URL!,
|
|
12
|
+
process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY!
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const handleLogin = async (values: any) => {
|
|
16
|
+
await supabase.auth.signInWithPassword({
|
|
17
|
+
email: values.email,
|
|
18
|
+
password: values.password,
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const handleGoogleLogin = async () => {
|
|
23
|
+
const { data, error } = await supabase.auth.signInWithOAuth({
|
|
24
|
+
provider: 'google',
|
|
25
|
+
options: {
|
|
26
|
+
redirectTo: 'exp://localhost:8081/auth/callback',
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (data.url) {
|
|
31
|
+
await WebBrowser.openAuthSessionAsync(data.url);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
37
|
+
<LoginForm
|
|
38
|
+
onSubmit={handleLogin}
|
|
39
|
+
onGoogleSignIn={handleGoogleLogin}
|
|
40
|
+
authProvider={AuthProvider.SUPABASE}
|
|
41
|
+
/>
|
|
42
|
+
</View>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SignupForm } from '@digilogiclabs/saas-factory-ui/native';
|
|
2
|
+
import { AuthProvider } from '@digilogiclabs/saas-factory-auth/native';
|
|
3
|
+
import { createBrowserClient } from '@supabase/ssr';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { View } from 'react-native';
|
|
6
|
+
import * as WebBrowser from 'expo-web-browser';
|
|
7
|
+
|
|
8
|
+
export default function SignupPage() {
|
|
9
|
+
const supabase = createBrowserClient(
|
|
10
|
+
process.env.EXPO_PUBLIC_SUPABASE_URL!,
|
|
11
|
+
process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY!
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const handleSignup = async (values: any) => {
|
|
15
|
+
await supabase.auth.signUp({
|
|
16
|
+
email: values.email,
|
|
17
|
+
password: values.password,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const handleGoogleSignup = async () => {
|
|
22
|
+
const { data, error } = await supabase.auth.signInWithOAuth({
|
|
23
|
+
provider: 'google',
|
|
24
|
+
options: {
|
|
25
|
+
redirectTo: 'exp://localhost:8081/auth/callback',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (data.url) {
|
|
30
|
+
await WebBrowser.openAuthSessionAsync(data.url);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
36
|
+
<SignupForm
|
|
37
|
+
onSubmit={handleSignup}
|
|
38
|
+
onGoogleSignIn={handleGoogleSignup}
|
|
39
|
+
authProvider={AuthProvider.SUPABASE}
|
|
40
|
+
/>
|
|
41
|
+
</View>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, Button } from 'react-native';
|
|
3
|
+
import { useStripe } from '@digilogiclabs/saas-factory-payments/native';
|
|
4
|
+
|
|
5
|
+
export default function CheckoutScreen() {
|
|
6
|
+
const { handleCheckout } = useStripe();
|
|
7
|
+
|
|
8
|
+
const onCheckout = async () => {
|
|
9
|
+
await handleCheckout({
|
|
10
|
+
priceId: 'price_12345', // Replace with your actual price ID
|
|
11
|
+
returnUrl: 'exp://localhost:8081/dashboard',
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
17
|
+
<Button title="Proceed to Checkout" onPress={onCheckout} />
|
|
18
|
+
</View>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"main": "node_modules/expo/AppEntry.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "expo start",
|
|
8
|
+
"android": "expo start --android",
|
|
9
|
+
"ios": "expo start --ios",
|
|
10
|
+
"web": "expo start --web",
|
|
11
|
+
"build": "eas build",
|
|
12
|
+
"eject": "expo eject"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"expo": "~49.0.0",
|
|
16
|
+
"react": "18.2.0",
|
|
17
|
+
"react-native": "0.72.6",
|
|
18
|
+
"@expo/vector-icons": "^13.0.0",
|
|
19
|
+
"@react-navigation/native": "^6.1.0",
|
|
20
|
+
"@react-navigation/stack": "^6.3.0",
|
|
21
|
+
"@react-navigation/bottom-tabs": "^6.5.0",
|
|
22
|
+
"react-native-screens": "~3.22.0",
|
|
23
|
+
"react-native-safe-area-context": "4.6.3",
|
|
24
|
+
"react-native-gesture-handler": "~2.12.0",
|
|
25
|
+
"@digilogiclabs/saas-factory-ui": "^0.7.2",
|
|
26
|
+
"@digilogiclabs/saas-factory-auth": "^0.4.3",
|
|
27
|
+
"@digilogiclabs/saas-factory-payments": "^0.2.0",
|
|
28
|
+
"firebase": "^10.0.0",
|
|
29
|
+
"@supabase/supabase-js": "^2.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@babel/core": "^7.20.0",
|
|
33
|
+
"@types/react": "~18.2.14",
|
|
34
|
+
"@types/react-native": "~0.72.2",
|
|
35
|
+
"typescript": "^5.1.3"
|
|
36
|
+
},
|
|
37
|
+
"private": true
|
|
38
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { initializeApp } from 'firebase/app';
|
|
2
|
+
import { getAuth } from 'firebase/auth';
|
|
3
|
+
import { getFirestore } from 'firebase/firestore';
|
|
4
|
+
|
|
5
|
+
const firebaseConfig = {
|
|
6
|
+
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
|
|
7
|
+
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
|
|
8
|
+
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
|
|
9
|
+
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
|
|
10
|
+
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
|
|
11
|
+
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Initialize Firebase
|
|
15
|
+
const app = initializeApp(firebaseConfig);
|
|
16
|
+
|
|
17
|
+
// Initialize Firebase Authentication and get a reference to the service
|
|
18
|
+
export const auth = getAuth(app);
|
|
19
|
+
|
|
20
|
+
// Initialize Cloud Firestore and get a reference to the service
|
|
21
|
+
export const db = getFirestore(app);
|
|
22
|
+
|
|
23
|
+
export default app;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createClient } from '@supabase/supabase-js';
|
|
2
|
+
|
|
3
|
+
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
|
|
4
|
+
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
|
|
5
|
+
|
|
6
|
+
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
|
|
7
|
+
|
|
8
|
+
export default supabase;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Auth Configuration
|
|
2
|
+
NEXT_PUBLIC_AUTH_PROVIDER=supabase|firebase
|
|
3
|
+
|
|
4
|
+
# Supabase
|
|
5
|
+
NEXT_PUBLIC_SUPABASE_URL=
|
|
6
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
7
|
+
|
|
8
|
+
# Firebase
|
|
9
|
+
NEXT_PUBLIC_FIREBASE_API_KEY=
|
|
10
|
+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
|
|
11
|
+
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
|
|
12
|
+
|
|
13
|
+
# Payments
|
|
14
|
+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
|
15
|
+
STRIPE_SECRET_KEY=
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# {{titleCaseName}}
|
|
2
|
+
|
|
3
|
+
{{description}}
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
First, run the development server:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run dev
|
|
11
|
+
# or
|
|
12
|
+
yarn dev
|
|
13
|
+
# or
|
|
14
|
+
pnpm dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- ⚡ **Next.js 14** - React framework with App Router
|
|
22
|
+
- 🎨 **Tailwind CSS** - Utility-first CSS framework
|
|
23
|
+
- 🔒 **{{#auth}}{{#firebase}}Firebase{{/firebase}}{{#supabase}}Supabase{{/supabase}}{{/auth}} Auth** - Authentication ready
|
|
24
|
+
- 📱 **Responsive Design** - Mobile-first approach
|
|
25
|
+
- 🌙 **Dark Mode** - Built-in theme switching
|
|
26
|
+
- 📦 **TypeScript** - Type-safe development
|
|
27
|
+
- 🎯 **ESLint & Prettier** - Code quality tools
|
|
28
|
+
|
|
29
|
+
## Project Structure
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
src/
|
|
33
|
+
├── app/ # Next.js App Router
|
|
34
|
+
│ ├── globals.css # Global styles
|
|
35
|
+
│ ├── layout.tsx # Root layout
|
|
36
|
+
│ └── page.tsx # Home page
|
|
37
|
+
├── components/ # React components
|
|
38
|
+
│ ├── ui/ # UI components
|
|
39
|
+
│ └── providers/ # Context providers
|
|
40
|
+
├── lib/ # Utility functions
|
|
41
|
+
├── hooks/ # Custom React hooks
|
|
42
|
+
└── types/ # TypeScript definitions
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Environment Variables
|
|
46
|
+
|
|
47
|
+
Copy `.env.example` to `.env.local` and fill in your configuration:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cp .env.example .env.local
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Deployment
|
|
54
|
+
|
|
55
|
+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new).
|
|
56
|
+
|
|
57
|
+
Check out the [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
|
58
|
+
|
|
59
|
+
## Learn More
|
|
60
|
+
|
|
61
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|
|
62
|
+
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
|
63
|
+
- [{{#auth}}{{#firebase}}Firebase Documentation{{/firebase}}{{#supabase}}Supabase Documentation{{/supabase}}{{/auth}}]({{#auth}}{{#firebase}}https://firebase.google.com/docs{{/firebase}}{{#supabase}}https://supabase.com/docs{{/supabase}}{{/auth}})
|
|
64
|
+
|
|
65
|
+
## Support
|
|
66
|
+
|
|
67
|
+
For support, email support@digilogiclabs.com or join our Discord community.
|
|
68
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "next dev",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"start": "next start",
|
|
10
|
+
"lint": "next lint",
|
|
11
|
+
"type-check": "tsc --noEmit"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"next": "^14.0.0",
|
|
15
|
+
"react": "^18.0.0",
|
|
16
|
+
"react-dom": "^18.0.0",
|
|
17
|
+
"@digilogiclabs/saas-factory-ui": "^0.7.2",
|
|
18
|
+
"@digilogiclabs/saas-factory-auth": "^0.4.3",
|
|
19
|
+
"@digilogiclabs/saas-factory-payments": "^0.2.0",
|
|
20
|
+
"tailwindcss": "^3.3.0",
|
|
21
|
+
"autoprefixer": "^10.4.16",
|
|
22
|
+
"postcss": "^8.4.31",
|
|
23
|
+
"clsx": "^2.0.0",
|
|
24
|
+
"class-variance-authority": "^0.7.0",
|
|
25
|
+
"tailwind-merge": "^2.0.0",
|
|
26
|
+
"next-themes": "^0.2.1",
|
|
27
|
+
"@radix-ui/react-slot": "^1.0.2",
|
|
28
|
+
"tailwindcss-animate": "^1.0.7",
|
|
29
|
+
"lucide-react": "^0.292.0",
|
|
30
|
+
"firebase": "^10.0.0",
|
|
31
|
+
"@supabase/supabase-js": "^2.0.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"typescript": "^5.0.0",
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"@types/react": "^18.0.0",
|
|
37
|
+
"@types/react-dom": "^18.0.0",
|
|
38
|
+
"eslint": "^8.0.0",
|
|
39
|
+
"eslint-config-next": "^14.0.0",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
41
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
42
|
+
"prettier": "^3.0.0",
|
|
43
|
+
"prettier-plugin-tailwindcss": "^0.5.0"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
|
|
2
|
+
import { cookies } from 'next/headers';
|
|
3
|
+
import { NextResponse } from 'next/server';
|
|
4
|
+
|
|
5
|
+
import type { NextRequest } from 'next/server';
|
|
6
|
+
|
|
7
|
+
export async function GET(request: NextRequest) {
|
|
8
|
+
const requestUrl = new URL(request.url);
|
|
9
|
+
const code = requestUrl.searchParams.get('code');
|
|
10
|
+
|
|
11
|
+
if (code) {
|
|
12
|
+
const supabase = createRouteHandlerClient({ cookies });
|
|
13
|
+
await supabase.auth.exchangeCodeForSession(code);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// URL to redirect to after sign in process completes
|
|
17
|
+
return NextResponse.redirect(requestUrl.origin);
|
|
18
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useStripe } from '@digilogiclabs/saas-factory-payments';
|
|
5
|
+
import { Button } from '@/components/ui/button';
|
|
6
|
+
|
|
7
|
+
export default function CheckoutPage() {
|
|
8
|
+
const { handleCheckout } = useStripe();
|
|
9
|
+
|
|
10
|
+
const onCheckout = async () => {
|
|
11
|
+
await handleCheckout({
|
|
12
|
+
priceId: 'price_12345', // Replace with your actual price ID
|
|
13
|
+
returnUrl: `${window.location.origin}/dashboard`,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
|
19
|
+
<div className="p-8 bg-white rounded-lg shadow-md">
|
|
20
|
+
<h1 className="text-2xl font-bold mb-4">Checkout</h1>
|
|
21
|
+
<p className="mb-6">Click the button below to proceed to payment.</p>
|
|
22
|
+
<Button onClick={onCheckout}>
|
|
23
|
+
Proceed to Checkout
|
|
24
|
+
</Button>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer base {
|
|
6
|
+
:root {
|
|
7
|
+
--background: 0 0% 100%;
|
|
8
|
+
--foreground: 222.2 84% 4.9%;
|
|
9
|
+
--card: 0 0% 100%;
|
|
10
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
11
|
+
--popover: 0 0% 100%;
|
|
12
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
13
|
+
--primary: 221.2 83.2% 53.3%;
|
|
14
|
+
--primary-foreground: 210 40% 98%;
|
|
15
|
+
--secondary: 210 40% 96%;
|
|
16
|
+
--secondary-foreground: 222.2 84% 4.9%;
|
|
17
|
+
--muted: 210 40% 96%;
|
|
18
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
19
|
+
--accent: 210 40% 96%;
|
|
20
|
+
--accent-foreground: 222.2 84% 4.9%;
|
|
21
|
+
--destructive: 0 84.2% 60.2%;
|
|
22
|
+
--destructive-foreground: 210 40% 98%;
|
|
23
|
+
--border: 214.3 31.8% 91.4%;
|
|
24
|
+
--input: 214.3 31.8% 91.4%;
|
|
25
|
+
--ring: 221.2 83.2% 53.3%;
|
|
26
|
+
--radius: 0.5rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.dark {
|
|
30
|
+
--background: 222.2 84% 4.9%;
|
|
31
|
+
--foreground: 210 40% 98%;
|
|
32
|
+
--card: 222.2 84% 4.9%;
|
|
33
|
+
--card-foreground: 210 40% 98%;
|
|
34
|
+
--popover: 222.2 84% 4.9%;
|
|
35
|
+
--popover-foreground: 210 40% 98%;
|
|
36
|
+
--primary: 217.2 91.2% 59.8%;
|
|
37
|
+
--primary-foreground: 222.2 84% 4.9%;
|
|
38
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
39
|
+
--secondary-foreground: 210 40% 98%;
|
|
40
|
+
--muted: 217.2 32.6% 17.5%;
|
|
41
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
42
|
+
--accent: 217.2 32.6% 17.5%;
|
|
43
|
+
--accent-foreground: 210 40% 98%;
|
|
44
|
+
--destructive: 0 62.8% 30.6%;
|
|
45
|
+
--destructive-foreground: 210 40% 98%;
|
|
46
|
+
--border: 217.2 32.6% 17.5%;
|
|
47
|
+
--input: 217.2 32.6% 17.5%;
|
|
48
|
+
--ring: 224.3 76.3% 94.1%;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@layer base {
|
|
53
|
+
* {
|
|
54
|
+
@apply border-border;
|
|
55
|
+
}
|
|
56
|
+
body {
|
|
57
|
+
@apply bg-background text-foreground;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Metadata } from 'next'
|
|
2
|
+
import { Inter } from 'next/font/google'
|
|
3
|
+
import './globals.css'
|
|
4
|
+
import { AppProviders } from '@/components/providers/app-providers'
|
|
5
|
+
import { Header } from '@/components/shared/header'
|
|
6
|
+
|
|
7
|
+
const inter = Inter({ subsets: ['latin'] })
|
|
8
|
+
|
|
9
|
+
export const metadata: Metadata = {
|
|
10
|
+
title: '{{titleCaseName}}',
|
|
11
|
+
description: '{{description}}',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function RootLayout({
|
|
15
|
+
children,
|
|
16
|
+
}: {
|
|
17
|
+
children: React.ReactNode
|
|
18
|
+
}) {
|
|
19
|
+
return (
|
|
20
|
+
<html lang="en" suppressHydrationWarning>
|
|
21
|
+
<body className={inter.className}>
|
|
22
|
+
<AppProviders>
|
|
23
|
+
<Header />
|
|
24
|
+
{children}
|
|
25
|
+
</AppProviders>
|
|
26
|
+
</body>
|
|
27
|
+
</html>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { LoginForm } from '@digilogiclabs/saas-factory-ui';
|
|
4
|
+
import { AuthProvider } from '@digilogiclabs/saas-factory-auth';
|
|
5
|
+
import { createBrowserClient } from '@supabase/ssr';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
export default function LoginPage() {
|
|
9
|
+
const supabase = createBrowserClient(
|
|
10
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
11
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const handleLogin = async (values: any) => {
|
|
15
|
+
await supabase.auth.signInWithPassword({
|
|
16
|
+
email: values.email,
|
|
17
|
+
password: values.password,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const handleGoogleLogin = async () => {
|
|
22
|
+
await supabase.auth.signInWithOAuth({
|
|
23
|
+
provider: 'google',
|
|
24
|
+
options: {
|
|
25
|
+
redirectTo: `${location.origin}/auth/callback`,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
|
32
|
+
<LoginForm
|
|
33
|
+
onSubmit={handleLogin}
|
|
34
|
+
onGoogleSignIn={handleGoogleLogin}
|
|
35
|
+
authProvider={AuthProvider.SUPABASE}
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
}
|