@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
|
@@ -1,19 +1,52 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { StatusBar } from 'expo-status-bar';
|
|
3
|
-
import { StyleSheet, Text, View } from 'react-native';
|
|
3
|
+
import { StyleSheet, Text, View, Button } from 'react-native';
|
|
4
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
|
+
}
|
|
5
39
|
|
|
6
40
|
export default function App() {
|
|
7
41
|
return (
|
|
8
42
|
<SafeAreaProvider>
|
|
9
|
-
<
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
</
|
|
15
|
-
|
|
16
|
-
</View>
|
|
43
|
+
<AuthProvider>
|
|
44
|
+
<StripeProvider
|
|
45
|
+
stripeKey={process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY!}
|
|
46
|
+
>
|
|
47
|
+
<AppContent />
|
|
48
|
+
</StripeProvider>
|
|
49
|
+
</AuthProvider>
|
|
17
50
|
</SafeAreaProvider>
|
|
18
51
|
);
|
|
19
52
|
}
|
|
@@ -43,5 +76,13 @@ const styles = StyleSheet.create({
|
|
|
43
76
|
color: '#999',
|
|
44
77
|
textAlign: 'center',
|
|
45
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
|
+
},
|
|
46
88
|
});
|
|
47
|
-
|
|
@@ -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
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"android": "expo start --android",
|
|
9
9
|
"ios": "expo start --ios",
|
|
10
10
|
"web": "expo start --web",
|
|
11
|
-
"build": "
|
|
11
|
+
"build": "eas build",
|
|
12
12
|
"eject": "expo eject"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
@@ -22,10 +22,11 @@
|
|
|
22
22
|
"react-native-screens": "~3.22.0",
|
|
23
23
|
"react-native-safe-area-context": "4.6.3",
|
|
24
24
|
"react-native-gesture-handler": "~2.12.0",
|
|
25
|
-
"@digilogiclabs/saas-factory-ui": "^
|
|
26
|
-
"@digilogiclabs/saas-factory-auth": "^
|
|
27
|
-
"
|
|
28
|
-
"
|
|
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"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@babel/core": "^7.20.0",
|
|
@@ -35,4 +36,3 @@
|
|
|
35
36
|
},
|
|
36
37
|
"private": true
|
|
37
38
|
}
|
|
38
|
-
|
|
@@ -1,24 +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;
|
|
24
|
-
|
|
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;
|
|
@@ -1,9 +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;
|
|
9
|
-
|
|
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;
|
|
@@ -1,34 +1,15 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
1
|
+
# Auth Configuration
|
|
2
|
+
NEXT_PUBLIC_AUTH_PROVIDER=supabase|firebase
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
NEXT_PUBLIC_FIREBASE_API_KEY=your_firebase_api_key
|
|
9
|
-
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
|
|
10
|
-
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
|
|
11
|
-
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
|
|
12
|
-
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
|
|
13
|
-
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
|
|
14
|
-
{{/firebase}}
|
|
15
|
-
{{#supabase}}
|
|
16
|
-
# Supabase Configuration
|
|
17
|
-
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
|
|
18
|
-
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
|
|
19
|
-
{{/supabase}}
|
|
20
|
-
{{/auth}}
|
|
4
|
+
# Supabase
|
|
5
|
+
NEXT_PUBLIC_SUPABASE_URL=
|
|
6
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
21
7
|
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{{/supabase}}
|
|
27
|
-
{{#firebase}}
|
|
28
|
-
# Firebase Admin (Server-side)
|
|
29
|
-
FIREBASE_ADMIN_PROJECT_ID=your_project_id
|
|
30
|
-
FIREBASE_ADMIN_CLIENT_EMAIL=your_service_account_email
|
|
31
|
-
FIREBASE_ADMIN_PRIVATE_KEY=your_private_key
|
|
32
|
-
{{/firebase}}
|
|
33
|
-
{{/database}}
|
|
8
|
+
# Firebase
|
|
9
|
+
NEXT_PUBLIC_FIREBASE_API_KEY=
|
|
10
|
+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
|
|
11
|
+
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
|
|
34
12
|
|
|
13
|
+
# Payments
|
|
14
|
+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
|
15
|
+
STRIPE_SECRET_KEY=
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
"next": "^14.0.0",
|
|
15
15
|
"react": "^18.0.0",
|
|
16
16
|
"react-dom": "^18.0.0",
|
|
17
|
-
"@digilogiclabs/saas-factory-ui": "^
|
|
18
|
-
"@digilogiclabs/saas-factory-auth": "^
|
|
17
|
+
"@digilogiclabs/saas-factory-ui": "^0.7.2",
|
|
18
|
+
"@digilogiclabs/saas-factory-auth": "^0.4.3",
|
|
19
|
+
"@digilogiclabs/saas-factory-payments": "^0.2.0",
|
|
19
20
|
"tailwindcss": "^3.3.0",
|
|
20
21
|
"autoprefixer": "^10.4.16",
|
|
21
22
|
"postcss": "^8.4.31",
|
|
@@ -25,9 +26,9 @@
|
|
|
25
26
|
"next-themes": "^0.2.1",
|
|
26
27
|
"@radix-ui/react-slot": "^1.0.2",
|
|
27
28
|
"tailwindcss-animate": "^1.0.7",
|
|
28
|
-
"lucide-react": "^0.292.0"
|
|
29
|
-
"firebase": "^10.0.0"
|
|
30
|
-
"@supabase/supabase-js": "^2.0.0"
|
|
29
|
+
"lucide-react": "^0.292.0",
|
|
30
|
+
"firebase": "^10.0.0",
|
|
31
|
+
"@supabase/supabase-js": "^2.0.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"typescript": "^5.0.0",
|
|
@@ -45,4 +46,3 @@
|
|
|
45
46
|
"node": ">=18.0.0"
|
|
46
47
|
}
|
|
47
48
|
}
|
|
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
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { Metadata } from 'next'
|
|
|
2
2
|
import { Inter } from 'next/font/google'
|
|
3
3
|
import './globals.css'
|
|
4
4
|
import { AppProviders } from '@/components/providers/app-providers'
|
|
5
|
+
import { Header } from '@/components/shared/header'
|
|
5
6
|
|
|
6
7
|
const inter = Inter({ subsets: ['latin'] })
|
|
7
8
|
|
|
@@ -19,10 +20,10 @@ export default function RootLayout({
|
|
|
19
20
|
<html lang="en" suppressHydrationWarning>
|
|
20
21
|
<body className={inter.className}>
|
|
21
22
|
<AppProviders>
|
|
23
|
+
<Header />
|
|
22
24
|
{children}
|
|
23
25
|
</AppProviders>
|
|
24
26
|
</body>
|
|
25
27
|
</html>
|
|
26
28
|
)
|
|
27
29
|
}
|
|
28
|
-
|
|
@@ -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
|
+
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
1
3
|
import { Button } from '@/components/ui/button'
|
|
2
4
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
3
5
|
import { Badge } from '@/components/ui/badge'
|
|
4
|
-
import { ArrowRight, Zap, Shield, Rocket } from 'lucide-react'
|
|
6
|
+
import { ArrowRight, Zap, Shield, Rocket, LogOut } from 'lucide-react'
|
|
7
|
+
import { useAuth } from '@digilogiclabs/saas-factory-auth'
|
|
8
|
+
import Link from 'next/link'
|
|
5
9
|
|
|
6
10
|
export default function Home() {
|
|
11
|
+
const { user, signOut } = useAuth()
|
|
12
|
+
|
|
7
13
|
return (
|
|
8
14
|
<main className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-gray-900 dark:to-gray-800">
|
|
9
15
|
<div className="container mx-auto px-4 py-16">
|
|
@@ -23,13 +29,32 @@ export default function Home() {
|
|
|
23
29
|
</code>
|
|
24
30
|
</p>
|
|
25
31
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
{!user ? (
|
|
33
|
+
<>
|
|
34
|
+
<Button size="lg" className="text-lg px-8" asChild>
|
|
35
|
+
<Link href="/signup">
|
|
36
|
+
Get Started
|
|
37
|
+
<ArrowRight className="ml-2 h-5 w-5" />
|
|
38
|
+
</Link>
|
|
39
|
+
</Button>
|
|
40
|
+
<Button variant="outline" size="lg" className="text-lg px-8" asChild>
|
|
41
|
+
<Link href="/login">Learn More</Link>
|
|
42
|
+
</Button>
|
|
43
|
+
</>
|
|
44
|
+
) : (
|
|
45
|
+
<>
|
|
46
|
+
<Button size="lg" className="text-lg px-8" asChild>
|
|
47
|
+
<Link href="/dashboard">
|
|
48
|
+
Go to Dashboard
|
|
49
|
+
<ArrowRight className="ml-2 h-5 w-5" />
|
|
50
|
+
</Link>
|
|
51
|
+
</Button>
|
|
52
|
+
<Button variant="outline" size="lg" className="text-lg px-8" onClick={signOut}>
|
|
53
|
+
<LogOut className="mr-2 h-5 w-5" />
|
|
54
|
+
Sign Out
|
|
55
|
+
</Button>
|
|
56
|
+
</>
|
|
57
|
+
)}
|
|
33
58
|
</div>
|
|
34
59
|
</div>
|
|
35
60
|
|
|
@@ -105,4 +130,3 @@ export default function Home() {
|
|
|
105
130
|
</main>
|
|
106
131
|
)
|
|
107
132
|
}
|
|
108
|
-
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { SignupForm } 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 SignupPage() {
|
|
9
|
+
const supabase = createBrowserClient(
|
|
10
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
11
|
+
process.env.NEXT_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
|
+
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
|
+
<SignupForm
|
|
33
|
+
onSubmit={handleSignup}
|
|
34
|
+
onGoogleSignIn={handleGoogleSignup}
|
|
35
|
+
authProvider={AuthProvider.SUPABASE}
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { AuthProvider } from '@digilogiclabs/saas-factory-auth'
|
|
3
5
|
import { ThemeProvider } from 'next-themes'
|
|
6
|
+
import { StripeProvider } from '@digilogiclabs/saas-factory-payments'
|
|
4
7
|
|
|
5
8
|
interface AppProvidersProps {
|
|
6
9
|
children: React.ReactNode
|
|
@@ -8,14 +11,19 @@ interface AppProvidersProps {
|
|
|
8
11
|
|
|
9
12
|
export function AppProviders({ children }: AppProvidersProps) {
|
|
10
13
|
return (
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
<AuthProvider provider="supabase">
|
|
15
|
+
<StripeProvider
|
|
16
|
+
stripeKey={process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!}
|
|
17
|
+
>
|
|
18
|
+
<ThemeProvider
|
|
19
|
+
attribute="class"
|
|
20
|
+
defaultTheme="system"
|
|
21
|
+
enableSystem
|
|
22
|
+
disableTransitionOnChange
|
|
23
|
+
>
|
|
24
|
+
{children}
|
|
25
|
+
</ThemeProvider>
|
|
26
|
+
</StripeProvider>
|
|
27
|
+
</AuthProvider>
|
|
19
28
|
)
|
|
20
29
|
}
|
|
21
|
-
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import Link from 'next/link';
|
|
5
|
+
import { useAuth } from '@digilogiclabs/saas-factory-auth';
|
|
6
|
+
import { Button } from '@/components/ui/button';
|
|
7
|
+
import { LogOut } from 'lucide-react';
|
|
8
|
+
|
|
9
|
+
export function Header() {
|
|
10
|
+
const { user, signOut } = useAuth();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<header className="bg-white dark:bg-gray-800 shadow-md">
|
|
14
|
+
<div className="container mx-auto px-4 py-4 flex justify-between items-center">
|
|
15
|
+
<Link href="/" className="text-2xl font-bold text-gray-900 dark:text-white">
|
|
16
|
+
{{titleCaseName}}
|
|
17
|
+
</Link>
|
|
18
|
+
<nav className="flex items-center gap-4">
|
|
19
|
+
{user ? (
|
|
20
|
+
<>
|
|
21
|
+
<Link href="/dashboard" className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
|
|
22
|
+
Dashboard
|
|
23
|
+
</Link>
|
|
24
|
+
<Button variant="ghost" size="icon" onClick={signOut}>
|
|
25
|
+
<LogOut className="h-5 w-5" />
|
|
26
|
+
</Button>
|
|
27
|
+
</>
|
|
28
|
+
) : (
|
|
29
|
+
<>
|
|
30
|
+
<Link href="/login" className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
|
|
31
|
+
Login
|
|
32
|
+
</Link>
|
|
33
|
+
<Button asChild>
|
|
34
|
+
<Link href="/signup">Sign Up</Link>
|
|
35
|
+
</Button>
|
|
36
|
+
</>
|
|
37
|
+
)}
|
|
38
|
+
</nav>
|
|
39
|
+
</div>
|
|
40
|
+
</header>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -6,6 +6,7 @@ module.exports = {
|
|
|
6
6
|
'./components/**/*.{ts,tsx}',
|
|
7
7
|
'./app/**/*.{ts,tsx}',
|
|
8
8
|
'./src/**/*.{ts,tsx}',
|
|
9
|
+
'../../node_modules/@digilogiclabs/saas-factory-ui/dist/**/*.{js,ts,jsx,tsx}',
|
|
9
10
|
],
|
|
10
11
|
theme: {
|
|
11
12
|
container: {
|
|
@@ -74,4 +75,3 @@ module.exports = {
|
|
|
74
75
|
},
|
|
75
76
|
plugins: [require("tailwindcss-animate")],
|
|
76
77
|
}
|
|
77
|
-
|