From ed83aebf32222aeff17f9a102aaa35eed43b89d2 Mon Sep 17 00:00:00 2001 From: vgcman16 <155417613+vgcman16@users.noreply.github.com> Date: Thu, 5 Jun 2025 19:18:32 -0500 Subject: [PATCH] feat: add supabase and firebase setup wizard --- .env.example | 9 ++ .env.production | 11 ++- README.md | 1 + app/components/chat/ChatBox.tsx | 2 + app/components/setup/SetupWizard.tsx | 135 +++++++++++++++++++++++++++ app/lib/stores/firebase.ts | 23 +++++ app/types/firebase.ts | 5 + docs/docs/index.md | 10 ++ examples/firebase.ts | 13 +++ examples/supabaseClient.ts | 6 ++ 10 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 app/components/setup/SetupWizard.tsx create mode 100644 app/lib/stores/firebase.ts create mode 100644 app/types/firebase.ts create mode 100644 examples/firebase.ts create mode 100644 examples/supabaseClient.ts diff --git a/.env.example b/.env.example index 3c7840a9..82624f4a 100644 --- a/.env.example +++ b/.env.example @@ -120,3 +120,12 @@ VITE_GITHUB_TOKEN_TYPE=classic # DEFAULT_NUM_CTX=12288 # Consumes 26GB of VRAM # DEFAULT_NUM_CTX=6144 # Consumes 24GB of VRAM DEFAULT_NUM_CTX= + +# Supabase credentials +VITE_SUPABASE_URL= +VITE_SUPABASE_ANON_KEY= + +# Firebase credentials +VITE_FIREBASE_API_KEY= +VITE_FIREBASE_AUTH_DOMAIN= +VITE_FIREBASE_PROJECT_ID= diff --git a/.env.production b/.env.production index 60b9d494..995d12bc 100644 --- a/.env.production +++ b/.env.production @@ -116,4 +116,13 @@ VITE_CLOUDFLARE_ACCOUNT_ID= # DEFAULT_NUM_CTX=24576 # Consumes 32GB of VRAM # DEFAULT_NUM_CTX=12288 # Consumes 26GB of VRAM # DEFAULT_NUM_CTX=6144 # Consumes 24GB of VRAM -DEFAULT_NUM_CTX= \ No newline at end of file +DEFAULT_NUM_CTX= + +# Supabase credentials +VITE_SUPABASE_URL= +VITE_SUPABASE_ANON_KEY= + +# Firebase credentials +VITE_FIREBASE_API_KEY= +VITE_FIREBASE_AUTH_DOMAIN= +VITE_FIREBASE_PROJECT_ID= diff --git a/README.md b/README.md index f0ea1d78..cf4f19e6 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ project, please check the [project management guide](./PROJECT.md) to get starte - **Download projects as ZIP** for easy portability Sync to a folder on the host. - **Integration-ready Docker support** for a hassle-free setup. - **Deploy** directly to **Netlify**, **Vercel**, or **Cloudflare Pages** +- **Guided Setup Wizard** for Supabase and Firebase connections - **Import Figma designs** to generate starter UI code. ## Setup diff --git a/app/components/chat/ChatBox.tsx b/app/components/chat/ChatBox.tsx index c1ce6679..3eaab0cd 100644 --- a/app/components/chat/ChatBox.tsx +++ b/app/components/chat/ChatBox.tsx @@ -14,6 +14,7 @@ import { toast } from 'react-toastify'; import { extractTextFromFile } from '~/utils/fileExtract'; import { SpeechRecognitionButton } from '~/components/chat/SpeechRecognition'; import { SupabaseConnection } from './SupabaseConnection'; +import { SetupWizard } from '~/components/setup/SetupWizard'; import { ExpoQrModal } from '~/components/workbench/ExpoQrModal'; import styles from './BaseChat.module.scss'; import type { ProviderInfo } from '~/types/model'; @@ -353,6 +354,7 @@ export const ChatBox: React.FC = (props) => { ) : null} + props.setQrModalOpen(false)} /> diff --git a/app/components/setup/SetupWizard.tsx b/app/components/setup/SetupWizard.tsx new file mode 100644 index 00000000..f08cccf8 --- /dev/null +++ b/app/components/setup/SetupWizard.tsx @@ -0,0 +1,135 @@ +import { useStore } from '@nanostores/react'; +import { useState } from 'react'; +import { DialogRoot, Dialog, DialogTitle, DialogButton, DialogClose } from '~/components/ui/Dialog'; +import { Input } from '~/components/ui/Input'; +import { useSupabaseConnection } from '~/lib/hooks/useSupabaseConnection'; +import { firebaseConfig, updateFirebaseConfig } from '~/lib/stores/firebase'; + +export function SetupWizard() { + const [open, setOpen] = useState(false); + const [provider, setProvider] = useState<'supabase' | 'firebase' | null>(null); + const [step, setStep] = useState(1); + + const firebase = useStore(firebaseConfig); + + const { + connection: supabaseConn, + connecting, + handleConnect, + selectProject, + fetchProjectApiKeys, + updateToken, + } = useSupabaseConnection(); + + const startWizard = () => { + setProvider(null); + setStep(1); + setOpen(true); + }; + + const handleFirebaseSave = () => { + updateFirebaseConfig(firebase); + setStep(3); + }; + + return ( +
+ + + {open && ( + + {step === 1 && ( +
+ Select a Provider +
+ { setProvider('supabase'); setStep(2); }}> + Supabase + + { setProvider('firebase'); setStep(2); }}> + Firebase + +
+
+ )} + {provider === 'supabase' && step === 2 && ( +
+ Connect Supabase + updateToken(e.currentTarget.value)} + /> + + {connecting ? 'Connecting...' : 'Connect'} + + {supabaseConn.stats?.projects && ( +
+ {supabaseConn.stats.projects.map((p) => ( + + ))} +
+ )} + {supabaseConn.credentials && ( +
+
Add these to your .env.local:
+
{`VITE_SUPABASE_URL=${supabaseConn.credentials.supabaseUrl}\nVITE_SUPABASE_ANON_KEY=${supabaseConn.credentials.anonKey}`}
+
Sample code:
+
{`import { createClient } from '@supabase/supabase-js';\n\nexport const supabase = createClient(import.meta.env.VITE_SUPABASE_URL!, import.meta.env.VITE_SUPABASE_ANON_KEY!);`}
+
+ )} +
+ )} + {provider === 'firebase' && step === 2 && ( +
+ Firebase Configuration + updateFirebaseConfig({ apiKey: e.currentTarget.value })} + /> + updateFirebaseConfig({ authDomain: e.currentTarget.value })} + /> + updateFirebaseConfig({ projectId: e.currentTarget.value })} + /> + Save +
+ )} + {provider === 'firebase' && step === 3 && ( +
+
Add these to your .env.local:
+
{`VITE_FIREBASE_API_KEY=${firebase.apiKey}\nVITE_FIREBASE_AUTH_DOMAIN=${firebase.authDomain}\nVITE_FIREBASE_PROJECT_ID=${firebase.projectId}`}
+
Sample code:
+
{`import { initializeApp } from 'firebase/app';\nimport { getAuth } from 'firebase/auth';\nimport { getFirestore } from 'firebase/firestore';\n\nconst firebaseConfig = {\n  apiKey: import.meta.env.VITE_FIREBASE_API_KEY!,\n  authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN!,\n  projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID!,\n};\n\nconst app = initializeApp(firebaseConfig);\nexport const auth = getAuth(app);\nexport const db = getFirestore(app);`}
+
+ )} +
+ + Close + +
+
+ )} +
+
+ ); +} diff --git a/app/lib/stores/firebase.ts b/app/lib/stores/firebase.ts new file mode 100644 index 00000000..0cac4f71 --- /dev/null +++ b/app/lib/stores/firebase.ts @@ -0,0 +1,23 @@ +import { atom } from 'nanostores'; + +export interface FirebaseConfig { + apiKey: string; + authDomain: string; + projectId: string; +} + +const saved = typeof localStorage !== 'undefined' ? localStorage.getItem('firebase_config') : null; + +export const firebaseConfig = atom( + saved ? JSON.parse(saved) : { apiKey: '', authDomain: '', projectId: '' }, +); + +export function updateFirebaseConfig(config: Partial) { + const current = firebaseConfig.get(); + const newConfig = { ...current, ...config }; + firebaseConfig.set(newConfig); + + if (typeof localStorage !== 'undefined') { + localStorage.setItem('firebase_config', JSON.stringify(newConfig)); + } +} diff --git a/app/types/firebase.ts b/app/types/firebase.ts new file mode 100644 index 00000000..754da6e7 --- /dev/null +++ b/app/types/firebase.ts @@ -0,0 +1,5 @@ +export interface FirebaseConfig { + apiKey: string; + authDomain: string; + projectId: string; +} diff --git a/docs/docs/index.md b/docs/docs/index.md index b5dbbb10..590cacbd 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -12,6 +12,7 @@ bolt.diy allows you to choose the LLM that you use for each prompt! Currently, y - [Entering API Keys](#entering-api-keys) - [1. Set API Keys in the `.env.local` File](#1-set-api-keys-in-the-envlocal-file) - [2. Configure API Keys Directly in the Application](#2-configure-api-keys-directly-in-the-application) + - [Supabase / Firebase Setup Wizard](#supabase--firebase-setup-wizard) - [Run the Application](#run-the-application) - [Option 1: Without Docker](#option-1-without-docker) - [Option 2: With Docker](#option-2-with-docker) @@ -118,6 +119,15 @@ Once you've configured your keys, the application will be ready to use the selec --- +### Supabase / Firebase Setup Wizard + +bolt.diy now includes a simple setup wizard for connecting to either Supabase or Firebase. +Open the **Setup Wizard** from the chat box to enter your API keys and automatically generate +the necessary environment variables. Once connected, the wizard provides sample code for +initializing the selected service using the values from your `.env.local` file. + +--- + ## Run the Application ### Option 1: Without Docker diff --git a/examples/firebase.ts b/examples/firebase.ts new file mode 100644 index 00000000..4482e591 --- /dev/null +++ b/examples/firebase.ts @@ -0,0 +1,13 @@ +import { initializeApp } from 'firebase/app'; +import { getAuth } from 'firebase/auth'; +import { getFirestore } from 'firebase/firestore'; + +const firebaseConfig = { + apiKey: import.meta.env.VITE_FIREBASE_API_KEY!, + authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN!, + projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID!, +}; + +const app = initializeApp(firebaseConfig); +export const auth = getAuth(app); +export const db = getFirestore(app); diff --git a/examples/supabaseClient.ts b/examples/supabaseClient.ts new file mode 100644 index 00000000..98f410f7 --- /dev/null +++ b/examples/supabaseClient.ts @@ -0,0 +1,6 @@ +import { createClient } from '@supabase/supabase-js'; + +const supabaseUrl = import.meta.env.VITE_SUPABASE_URL!; +const anonKey = import.meta.env.VITE_SUPABASE_ANON_KEY!; + +export const supabase = createClient(supabaseUrl, anonKey);