your-ai-workflow-firebase-os 1.2.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.
Files changed (143) hide show
  1. package/README.md +236 -0
  2. package/dist/FirebaseOS.d.ts +33 -0
  3. package/dist/_redirects +1 -0
  4. package/dist/contactForm.config-BHvMbfxM.js +42 -0
  5. package/dist/contactForm.config-DLeI_ZEj.js +2 -0
  6. package/dist/contactForm.config-Y2AYSH9s.cjs +1 -0
  7. package/dist/contactForm.config-ki9OzidM.cjs +1 -0
  8. package/dist/favicon.svg +5 -0
  9. package/dist/icons.svg +24 -0
  10. package/dist/index.d.ts +9 -0
  11. package/dist/lib/AuthContext.d.ts +25 -0
  12. package/dist/lib/ConfigContext.d.ts +31 -0
  13. package/dist/lib/ThemeContext.d.ts +18 -0
  14. package/dist/supportForm.config-74T-eSSH.js +2 -0
  15. package/dist/supportForm.config-BwZqJ5CZ.cjs +1 -0
  16. package/dist/supportForm.config-D5ZRFZtU.js +35 -0
  17. package/dist/supportForm.config-NfLDtLTB.cjs +1 -0
  18. package/dist/theme.config-BbEzcEDR.js +2 -0
  19. package/dist/theme.config-DJqqr_kx.cjs +1 -0
  20. package/dist/theme.config-DKqbHSSM.cjs +1 -0
  21. package/dist/theme.config-q93xMCw6.js +68 -0
  22. package/dist/your-ai-workflow-firebase-os.cjs.js +618 -0
  23. package/dist/your-ai-workflow-firebase-os.css +2 -0
  24. package/dist/your-ai-workflow-firebase-os.es.js +90443 -0
  25. package/package.json +81 -0
  26. package/scripts/postinstall.js +245 -0
  27. package/src/App.css +184 -0
  28. package/src/App.tsx +214 -0
  29. package/src/FirebaseOS.tsx +87 -0
  30. package/src/assets/hero.png +0 -0
  31. package/src/assets/react.svg +1 -0
  32. package/src/assets/vite.svg +1 -0
  33. package/src/components/AdminNotifications.test.tsx +98 -0
  34. package/src/components/AdminNotifications.tsx +194 -0
  35. package/src/components/Button.test.tsx +22 -0
  36. package/src/components/Button.tsx +53 -0
  37. package/src/components/ConfirmModal.test.tsx +98 -0
  38. package/src/components/ConfirmModal.tsx +73 -0
  39. package/src/components/ContactPopup.test.tsx +98 -0
  40. package/src/components/ContactPopup.tsx +437 -0
  41. package/src/components/CustomSelect.test.tsx +47 -0
  42. package/src/components/CustomSelect.tsx +89 -0
  43. package/src/components/DashboardNav.test.tsx +98 -0
  44. package/src/components/DashboardNav.tsx +281 -0
  45. package/src/components/Input.test.tsx +33 -0
  46. package/src/components/Input.tsx +61 -0
  47. package/src/components/JsonEditor.tsx +579 -0
  48. package/src/components/Navbar.test.tsx +98 -0
  49. package/src/components/Navbar.tsx +563 -0
  50. package/src/configs/forms/contactForm.config.ts +15 -0
  51. package/src/configs/forms/index.ts +29 -0
  52. package/src/configs/forms/pubForm.config.ts +11 -0
  53. package/src/configs/forms/supportForm.config.ts +14 -0
  54. package/src/configs/forms/userForm.config.ts +11 -0
  55. package/src/configs/pages/admin.config.ts +29 -0
  56. package/src/configs/pages/contact.config.ts +6 -0
  57. package/src/configs/pages/home.config.ts +18 -0
  58. package/src/configs/pages/mem.config.ts +2 -0
  59. package/src/configs/pages/menuOrders.config.ts +11 -0
  60. package/src/configs/pages/pub.config.ts +11 -0
  61. package/src/configs/pages/shared.config.ts +29 -0
  62. package/src/configs/pages/support.config.ts +7 -0
  63. package/src/configs/pages/tabOrders.config.ts +33 -0
  64. package/src/configs/pages/user.config.ts +29 -0
  65. package/src/configs/theme.config.ts +93 -0
  66. package/src/index.css +403 -0
  67. package/src/index.ts +22 -0
  68. package/src/lib/AuthContext.test.tsx +88 -0
  69. package/src/lib/AuthContext.tsx +191 -0
  70. package/src/lib/ConfigContext.tsx +45 -0
  71. package/src/lib/ThemeContext.tsx +233 -0
  72. package/src/lib/firebase.ts +91 -0
  73. package/src/main.tsx +22 -0
  74. package/src/microcomponents/AdminExampleContent.tsx +44 -0
  75. package/src/microcomponents/PrivateExampleContent.tsx +39 -0
  76. package/src/microcomponents/Public.tsx +126 -0
  77. package/src/microcomponents/SharedExampleContent.tsx +53 -0
  78. package/src/pages/Dashboard.test.tsx +98 -0
  79. package/src/pages/Dashboard.tsx +60 -0
  80. package/src/pages/DynamicPage.tsx +237 -0
  81. package/src/pages/FormsAdmin.test.tsx +98 -0
  82. package/src/pages/FormsAdmin.tsx +459 -0
  83. package/src/pages/Home.test.tsx +98 -0
  84. package/src/pages/Home.tsx +144 -0
  85. package/src/pages/Login.test.tsx +98 -0
  86. package/src/pages/Login.tsx +108 -0
  87. package/src/pages/PagesAdmin.test.tsx +98 -0
  88. package/src/pages/PagesAdmin.tsx +1022 -0
  89. package/src/pages/Profile.test.tsx +98 -0
  90. package/src/pages/Profile.tsx +319 -0
  91. package/src/pages/Register.test.tsx +98 -0
  92. package/src/pages/Register.tsx +116 -0
  93. package/src/pages/Requests.test.tsx +95 -0
  94. package/src/pages/Requests.tsx +422 -0
  95. package/src/pages/ResetPassword.test.tsx +98 -0
  96. package/src/pages/ResetPassword.tsx +92 -0
  97. package/src/pages/Settings.test.tsx +98 -0
  98. package/src/pages/Settings.tsx +393 -0
  99. package/src/pages/Setup.tsx +413 -0
  100. package/src/pages/StorageAdmin.test.tsx +150 -0
  101. package/src/pages/StorageAdmin.tsx +769 -0
  102. package/src/pages/Submissions.test.tsx +95 -0
  103. package/src/pages/Submissions.tsx +378 -0
  104. package/src/pages/Templates.test.tsx +98 -0
  105. package/src/pages/Templates.tsx +103 -0
  106. package/src/pages/ThemeAdmin.test.tsx +144 -0
  107. package/src/pages/ThemeAdmin.tsx +1000 -0
  108. package/src/pages/Users.test.tsx +95 -0
  109. package/src/pages/Users.tsx +334 -0
  110. package/src/pages/Verify.test.tsx +98 -0
  111. package/src/pages/Verify.tsx +95 -0
  112. package/src/prompts/index.ts +13 -0
  113. package/src/prompts/pages/publicPage.ts +44 -0
  114. package/src/prompts/sharedConstants.ts +12 -0
  115. package/src/prompts/tabs/board/adminboard.ts +32 -0
  116. package/src/prompts/tabs/board/privateboard.ts +36 -0
  117. package/src/prompts/tabs/board/publicboard.ts +36 -0
  118. package/src/prompts/tabs/calendar/admincalendar.ts +32 -0
  119. package/src/prompts/tabs/calendar/privatecalendar.ts +36 -0
  120. package/src/prompts/tabs/calendar/publiccalendar.ts +36 -0
  121. package/src/prompts/tabs/crud/admin.ts +54 -0
  122. package/src/prompts/tabs/crud/private.ts +55 -0
  123. package/src/prompts/tabs/crud/shared.ts +53 -0
  124. package/src/prompts/tabs/table/admintable.ts +32 -0
  125. package/src/prompts/tabs/table/privatetable.ts +36 -0
  126. package/src/prompts/tabs/table/publictable.ts +36 -0
  127. package/src/setupTests.ts +1 -0
  128. package/src/templates/AdminPageTemplate.tsx +678 -0
  129. package/src/templates/PrivatePageTemplate.tsx +594 -0
  130. package/src/templates/PublicPageTemplate.tsx +92 -0
  131. package/src/templates/SharedPageTemplate.tsx +551 -0
  132. package/src/templates/TemplateBoard.test.tsx +106 -0
  133. package/src/templates/TemplateBoard.tsx +642 -0
  134. package/src/templates/TemplateCalendar.test.tsx +106 -0
  135. package/src/templates/TemplateCalendar.tsx +848 -0
  136. package/src/templates/TemplateConfirmation.test.tsx +106 -0
  137. package/src/templates/TemplateConfirmation.tsx +145 -0
  138. package/src/templates/TemplateInlineForm.test.tsx +106 -0
  139. package/src/templates/TemplateInlineForm.tsx +129 -0
  140. package/src/templates/TemplatePopupForm.test.tsx +106 -0
  141. package/src/templates/TemplatePopupForm.tsx +174 -0
  142. package/src/templates/TemplateTable.test.tsx +106 -0
  143. package/src/templates/TemplateTable.tsx +675 -0
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "your-ai-workflow-firebase-os",
3
+ "version": "1.2.1",
4
+ "description": "A complete Firebase-powered admin OS — one React component.",
5
+ "type": "module",
6
+ "main": "dist/firebase-os.cjs.js",
7
+ "module": "dist/firebase-os.es.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/firebase-os.es.js",
12
+ "require": "./dist/firebase-os.cjs.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./styles.css": {
16
+ "default": "./dist/firebase-os.css"
17
+ },
18
+ "./dist/firebase-os.css": {
19
+ "default": "./dist/firebase-os.css"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "scripts",
25
+ "src"
26
+ ],
27
+ "scripts": {
28
+ "dev": "vite",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "build": "tsc -b && vite build",
32
+ "build:lib": "vite build",
33
+ "lint": "eslint .",
34
+ "preview": "vite preview",
35
+ "postinstall": "node scripts/postinstall.js"
36
+ },
37
+ "dependencies": {
38
+ "@eslint/js": "^9.39.4",
39
+ "@tailwindcss/vite": "^4.2.2",
40
+ "@types/node": "^24.12.0",
41
+ "@types/react": "^19.2.14",
42
+ "@types/react-dom": "^19.2.3",
43
+ "@vitejs/plugin-react": "^6.0.1",
44
+ "clsx": "^2.1.1",
45
+ "firebase": ">=10",
46
+ "framer-motion": "^12.38.0",
47
+ "fuse.js": "^7.3.0",
48
+ "iconoir": "^7.11.0",
49
+ "iconoir-react": "^7.11.0",
50
+ "lucide-react": "^1.7.0",
51
+ "react": ">=18",
52
+ "react-dom": ">=18",
53
+ "react-dropzone": "^15.0.0",
54
+ "react-international-phone": "^4.8.0",
55
+ "react-phone-number-input": "^3.4.16",
56
+ "react-router-dom": ">=6",
57
+ "tailwind-merge": "^3.5.0",
58
+ "tailwindcss": "^4.2.2",
59
+ "typescript": "~5.9.3",
60
+ "vite": "^8.0.1"
61
+ },
62
+ "devDependencies": {
63
+ "@testing-library/jest-dom": "^6.9.1",
64
+ "@testing-library/react": "^16.3.2",
65
+ "@testing-library/user-event": "^14.6.1",
66
+ "eslint": "^9.39.4",
67
+ "eslint-plugin-react-hooks": "^7.0.1",
68
+ "eslint-plugin-react-refresh": "^0.5.2",
69
+ "globals": "^17.4.0",
70
+ "jsdom": "^29.0.1",
71
+ "typescript-eslint": "^8.57.0",
72
+ "vite-plugin-dts": "^5.0.0",
73
+ "vitest": "^4.1.2"
74
+ },
75
+ "peerDependencies": {
76
+ "firebase": ">=10",
77
+ "react": ">=18",
78
+ "react-dom": ">=18",
79
+ "react-router-dom": ">=6"
80
+ }
81
+ }
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * your-ai-workflow-firebase-os postinstall script
4
+ *
5
+ * Runs automatically after `npm install your-ai-workflow-firebase-os`.
6
+ * Patches the consumer project so that <FirebaseOS /> renders correctly
7
+ * out of the box — no manual cleanup required.
8
+ *
9
+ * What it does:
10
+ * 1. Clears src/index.css and src/App.css to remove Vite default styling
11
+ * that would clash with the library's design system.
12
+ * 2. Writes a clean src/main.tsx that removes the Vite index.css import.
13
+ * 3. Writes the minimal src/App.tsx that mounts <FirebaseOS />.
14
+ */
15
+
16
+ import fs from 'fs';
17
+ import path from 'path';
18
+ import { fileURLToPath } from 'url';
19
+
20
+ // Walk up from node_modules/your-ai-workflow-firebase-os/scripts/ to find the consumer project root
21
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
22
+ // __dirname = <consumer>/node_modules/your-ai-workflow-firebase-os/scripts
23
+ const consumerRoot = path.resolve(__dirname, '..', '..', '..');
24
+
25
+ // Only run when we are truly installed inside a consumer (not during our own dev)
26
+ const consumerPkg = path.join(consumerRoot, 'package.json');
27
+ if (!fs.existsSync(consumerPkg)) {
28
+ console.log('[your-ai-workflow-firebase-os] postinstall: no package.json found up the tree, skipping.');
29
+ process.exit(0);
30
+ }
31
+
32
+ let pkgJson;
33
+ try {
34
+ pkgJson = JSON.parse(fs.readFileSync(consumerPkg, 'utf8'));
35
+ } catch {
36
+ process.exit(0);
37
+ }
38
+
39
+ // Don't self-apply when running inside our own library project
40
+ if (pkgJson.name === 'your-ai-workflow-firebase-os') {
41
+ process.exit(0);
42
+ }
43
+
44
+ const srcDir = path.join(consumerRoot, 'src');
45
+
46
+ // No src/ directory means this isn't a Vite/React project — skip silently
47
+ if (!fs.existsSync(srcDir)) {
48
+ process.exit(0);
49
+ }
50
+
51
+ console.log('\n[your-ai-workflow-firebase-os] Setting up project for zero-config usage...\n');
52
+
53
+ // ── 1. Clear Vite's default conflicting CSS files ───────────────────────────
54
+ const cssFiles = ['index.css', 'App.css'];
55
+ for (const file of cssFiles) {
56
+ const filePath = path.join(srcDir, file);
57
+ if (fs.existsSync(filePath)) {
58
+ fs.writeFileSync(filePath, '/* cleared by your-ai-workflow-firebase-os postinstall */\n');
59
+ console.log(` ✓ Cleared ${file} (was conflicting with your-ai-workflow-firebase-os styles)`);
60
+ }
61
+ }
62
+
63
+ // ── 2. Rewrite main.tsx — import library + theme CSS at the entry point ─────
64
+ const mainPath = path.join(srcDir, 'main.tsx');
65
+ if (fs.existsSync(mainPath)) {
66
+ const mainContent = fs.readFileSync(mainPath, 'utf8');
67
+ // Rewrite if it has the default Vite CSS import OR if it doesn't have our library CSS
68
+ if (mainContent.includes("import './index.css'") || mainContent.includes('import "./index.css"') || !mainContent.includes('your-ai-workflow-firebase-os')) {
69
+ const clean = `import { StrictMode } from 'react'
70
+ import { createRoot } from 'react-dom/client'
71
+
72
+ // Firebase OS — compiled library styles (Tailwind utilities, components, layouts)
73
+ import 'your-ai-workflow-firebase-os/styles.css'
74
+ // Firebase OS — local theme overrides (CSS variables, data-theme, custom styles)
75
+ import './your-ai-workflow-firebase-os/theme.css'
76
+
77
+ import App from './App.tsx'
78
+
79
+ createRoot(document.getElementById('root')!).render(
80
+ <StrictMode>
81
+ <App />
82
+ </StrictMode>,
83
+ )
84
+ `;
85
+ fs.writeFileSync(mainPath, clean);
86
+ console.log(' ✓ Patched main.tsx with Firebase OS styles');
87
+ }
88
+ }
89
+
90
+ // ── 3. Hybrid Architecture: Create local overrides directory ─────────────
91
+ const fbosDir = path.join(srcDir, 'your-ai-workflow-firebase-os');
92
+ if (!fs.existsSync(fbosDir)) fs.mkdirSync(fbosDir, { recursive: true });
93
+
94
+ // Copy raw index.css to give user full control over Tailwind and variables
95
+ const sourceCssPath = path.join(__dirname, '..', 'src', 'index.css');
96
+ if (fs.existsSync(sourceCssPath)) {
97
+ fs.copyFileSync(sourceCssPath, path.join(fbosDir, 'theme.css'));
98
+ console.log(' ✓ Copied theme.css to your src/your-ai-workflow-firebase-os directory');
99
+ }
100
+
101
+ // Copy configurations
102
+ const configsDir = path.join(fbosDir, 'configs');
103
+ if (!fs.existsSync(configsDir)) fs.mkdirSync(configsDir, { recursive: true });
104
+
105
+ const copyConfig = (srcPath, destName) => {
106
+ const fullSrc = path.join(__dirname, '..', 'src', 'configs', srcPath);
107
+ if (fs.existsSync(fullSrc)) {
108
+ fs.copyFileSync(fullSrc, path.join(configsDir, destName));
109
+ }
110
+ };
111
+ copyConfig('theme.config.ts', 'theme.config.ts');
112
+ copyConfig('pages/home.config.ts', 'home.config.ts');
113
+ copyConfig('forms/contactForm.config.ts', 'contactForm.config.ts');
114
+ copyConfig('forms/supportForm.config.ts', 'supportForm.config.ts');
115
+ console.log(' ✓ Copied configuration files to your src/your-ai-workflow-firebase-os/configs directory');
116
+
117
+ // Read and rewrite Home.tsx
118
+ const sourceHomePath = path.join(__dirname, '..', 'src', 'pages', 'Home.tsx');
119
+ if (fs.existsSync(sourceHomePath)) {
120
+ let homeContent = fs.readFileSync(sourceHomePath, 'utf8');
121
+ homeContent = homeContent.replace(/from '\.\.\/components\/ContactPopup'/g, "from 'your-ai-workflow-firebase-os'");
122
+ homeContent = homeContent.replace(/from '\.\.\/lib\/firebase'/g, "from 'your-ai-workflow-firebase-os'");
123
+ homeContent = homeContent.replace(/from '\.\.\/configs\/pages\/home\.config'/g, "from './configs/home.config'");
124
+ fs.writeFileSync(path.join(fbosDir, 'Home.tsx'), homeContent);
125
+ console.log(' ✓ Created local Home.tsx template override');
126
+ }
127
+
128
+ // ── 4. Write App.tsx with Hybrid Overrides Wired Up ───────────────────────
129
+ // Note: CSS imports are in main.tsx (entry point) for correct load ordering.
130
+ const appPath = path.join(srcDir, 'App.tsx');
131
+ const appContent = `import { FirebaseOS } from 'your-ai-workflow-firebase-os';
132
+
133
+ // Local Hybrid Overrides
134
+ import { Home } from './your-ai-workflow-firebase-os/Home';
135
+ import { themeConfig } from './your-ai-workflow-firebase-os/configs/theme.config';
136
+
137
+ // Vite injects these from your .env file at dev/build time.
138
+ const firebaseConfig = {
139
+ apiKey: import.meta.env.VITE_FIREBASE_API_KEY || '',
140
+ authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || '',
141
+ projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || '',
142
+ storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET || '',
143
+ messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID || '',
144
+ appId: import.meta.env.VITE_FIREBASE_APP_ID || '',
145
+ };
146
+
147
+ const adminEmails = (import.meta.env.VITE_ADMIN_EMAILS || '')
148
+ .split(',')
149
+ .map((e: string) => e.trim())
150
+ .filter(Boolean);
151
+
152
+ export default function App() {
153
+ return (
154
+ <FirebaseOS
155
+ firebaseConfig={firebaseConfig}
156
+ adminEmails={adminEmails}
157
+ themeConfig={themeConfig}
158
+ components={{
159
+ Home: Home
160
+ }}
161
+ />
162
+ );
163
+ }
164
+ `;
165
+
166
+ const existingApp = fs.existsSync(appPath) ? fs.readFileSync(appPath, 'utf8') : '';
167
+ if (!existingApp.includes('your-ai-workflow-firebase-os')) {
168
+ fs.writeFileSync(appPath, appContent);
169
+ console.log(' ✓ Wrote App.tsx with <FirebaseOS /> hybrid architecture ready to go');
170
+ } else {
171
+ console.log(' ℹ App.tsx already uses your-ai-workflow-firebase-os — skipped');
172
+ }
173
+
174
+ // ── 5. Setup Tailwind V4 in host app ───────────────────────────────────────
175
+ // We'll update the user's package.json to include tailwindcss dependencies
176
+ const pkgPath = path.join(consumerRoot, 'package.json');
177
+ if (fs.existsSync(pkgPath)) {
178
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
179
+ let pkgModified = false;
180
+ pkg.devDependencies = pkg.devDependencies || {};
181
+
182
+ if (!pkg.devDependencies['tailwindcss']) {
183
+ pkg.devDependencies['tailwindcss'] = '^4.0.0';
184
+ pkgModified = true;
185
+ }
186
+ if (!pkg.devDependencies['@tailwindcss/vite']) {
187
+ pkg.devDependencies['@tailwindcss/vite'] = '^4.0.0';
188
+ pkgModified = true;
189
+ }
190
+ if (pkgModified) {
191
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
192
+ console.log(' ✓ Added tailwindcss and @tailwindcss/vite to your package.json');
193
+ }
194
+ }
195
+
196
+ const viteConfigPath = path.join(consumerRoot, 'vite.config.ts');
197
+ if (fs.existsSync(viteConfigPath)) {
198
+ let viteConfig = fs.readFileSync(viteConfigPath, 'utf8');
199
+ if (!viteConfig.includes('@tailwindcss/vite')) {
200
+ // Build the patched file with real newlines (not escaped \n literals)
201
+ const importLine = "import tailwindcss from '@tailwindcss/vite';";
202
+ viteConfig = importLine + '\n' + viteConfig;
203
+ viteConfig = viteConfig.replace(
204
+ 'plugins: [',
205
+ 'plugins: [\n tailwindcss(),'
206
+ );
207
+ fs.writeFileSync(viteConfigPath, viteConfig);
208
+ console.log(' ✓ Patched vite.config.ts to enable Tailwind CSS v4');
209
+ }
210
+ }
211
+
212
+ // ── 6. Create .env file with empty placeholders ────────────────────────────
213
+ const envPath = path.join(consumerRoot, '.env');
214
+ if (!fs.existsSync(envPath)) {
215
+ const envContent = `# 🔥 Firebase OS Configuration
216
+ # Fill in each value below with your Firebase Web App credentials.
217
+ # Find them in Firebase Console -> Project Settings -> General -> Your Apps
218
+ # Leave values empty until you are ready — the app will show a Setup page.
219
+ # After filling them in, restart the dev server (npm run dev).
220
+
221
+ # Your Firebase API Key (e.g. AIzaSyD...)
222
+ VITE_FIREBASE_API_KEY=
223
+ # Your Firebase Auth Domain (e.g. myproject.firebaseapp.com)
224
+ VITE_FIREBASE_AUTH_DOMAIN=
225
+ # Your Firebase Project ID (e.g. myproject)
226
+ VITE_FIREBASE_PROJECT_ID=
227
+ # Your Firebase Storage Bucket (e.g. myproject.firebasestorage.app)
228
+ VITE_FIREBASE_STORAGE_BUCKET=
229
+ # Your Firebase Messaging Sender ID (e.g. 123456789012)
230
+ VITE_FIREBASE_MESSAGING_SENDER_ID=
231
+ # Your Firebase App ID (e.g. 1:123456789012:web:abcdef123456)
232
+ VITE_FIREBASE_APP_ID=
233
+
234
+ # Comma-separated list of admin email addresses (these users get admin role on first registration)
235
+ # Example: you@email.com,colleague@email.com
236
+ VITE_ADMIN_EMAILS=
237
+ `;
238
+ fs.writeFileSync(envPath, envContent);
239
+ console.log(' ✓ Created .env template (fill in your Firebase credentials)');
240
+ }
241
+
242
+ console.log('\n[your-ai-workflow-firebase-os] 🎉 Hybrid Setup complete! You now have full control over styling and configs.\n');
243
+ console.log('🚨 IMPORTANT NEXT STEPS:');
244
+ console.log('1. Run `npm install` again to install the required Tailwind CSS dependencies.');
245
+ console.log('2. Run `npm run dev` to start your app.\n');
package/src/App.css ADDED
@@ -0,0 +1,184 @@
1
+ .counter {
2
+ font-size: 16px;
3
+ padding: 5px 10px;
4
+ border-radius: 5px;
5
+ color: var(--accent);
6
+ background: var(--accent-bg);
7
+ border: 2px solid transparent;
8
+ transition: border-color 0.3s;
9
+ margin-bottom: 24px;
10
+
11
+ &:hover {
12
+ border-color: var(--accent-border);
13
+ }
14
+ &:focus-visible {
15
+ outline: 2px solid var(--accent);
16
+ outline-offset: 2px;
17
+ }
18
+ }
19
+
20
+ .hero {
21
+ position: relative;
22
+
23
+ .base,
24
+ .framework,
25
+ .vite {
26
+ inset-inline: 0;
27
+ margin: 0 auto;
28
+ }
29
+
30
+ .base {
31
+ width: 170px;
32
+ position: relative;
33
+ z-index: 0;
34
+ }
35
+
36
+ .framework,
37
+ .vite {
38
+ position: absolute;
39
+ }
40
+
41
+ .framework {
42
+ z-index: 1;
43
+ top: 34px;
44
+ height: 28px;
45
+ transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
46
+ scale(1.4);
47
+ }
48
+
49
+ .vite {
50
+ z-index: 0;
51
+ top: 107px;
52
+ height: 26px;
53
+ width: auto;
54
+ transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
55
+ scale(0.8);
56
+ }
57
+ }
58
+
59
+ #center {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: 25px;
63
+ place-content: center;
64
+ place-items: center;
65
+ flex-grow: 1;
66
+
67
+ @media (max-width: 1024px) {
68
+ padding: 32px 20px 24px;
69
+ gap: 18px;
70
+ }
71
+ }
72
+
73
+ #next-steps {
74
+ display: flex;
75
+ border-top: 1px solid var(--border);
76
+ text-align: left;
77
+
78
+ & > div {
79
+ flex: 1 1 0;
80
+ padding: 32px;
81
+ @media (max-width: 1024px) {
82
+ padding: 24px 20px;
83
+ }
84
+ }
85
+
86
+ .icon {
87
+ margin-bottom: 16px;
88
+ width: 22px;
89
+ height: 22px;
90
+ }
91
+
92
+ @media (max-width: 1024px) {
93
+ flex-direction: column;
94
+ text-align: center;
95
+ }
96
+ }
97
+
98
+ #docs {
99
+ border-right: 1px solid var(--border);
100
+
101
+ @media (max-width: 1024px) {
102
+ border-right: none;
103
+ border-bottom: 1px solid var(--border);
104
+ }
105
+ }
106
+
107
+ #next-steps ul {
108
+ list-style: none;
109
+ padding: 0;
110
+ display: flex;
111
+ gap: 8px;
112
+ margin: 32px 0 0;
113
+
114
+ .logo {
115
+ height: 18px;
116
+ }
117
+
118
+ a {
119
+ color: var(--text-h);
120
+ font-size: 16px;
121
+ border-radius: 6px;
122
+ background: var(--social-bg);
123
+ display: flex;
124
+ padding: 6px 12px;
125
+ align-items: center;
126
+ gap: 8px;
127
+ text-decoration: none;
128
+ transition: box-shadow 0.3s;
129
+
130
+ &:hover {
131
+ box-shadow: var(--shadow);
132
+ }
133
+ .button-icon {
134
+ height: 18px;
135
+ width: 18px;
136
+ }
137
+ }
138
+
139
+ @media (max-width: 1024px) {
140
+ margin-top: 20px;
141
+ flex-wrap: wrap;
142
+ justify-content: center;
143
+
144
+ li {
145
+ flex: 1 1 calc(50% - 8px);
146
+ }
147
+
148
+ a {
149
+ width: 100%;
150
+ justify-content: center;
151
+ box-sizing: border-box;
152
+ }
153
+ }
154
+ }
155
+
156
+ #spacer {
157
+ height: 88px;
158
+ border-top: 1px solid var(--border);
159
+ @media (max-width: 1024px) {
160
+ height: 48px;
161
+ }
162
+ }
163
+
164
+ .ticks {
165
+ position: relative;
166
+ width: 100%;
167
+
168
+ &::before,
169
+ &::after {
170
+ content: '';
171
+ position: absolute;
172
+ top: -4.5px;
173
+ border: 5px solid transparent;
174
+ }
175
+
176
+ &::before {
177
+ left: 0;
178
+ border-left-color: var(--border);
179
+ }
180
+ &::after {
181
+ right: 0;
182
+ border-right-color: var(--border);
183
+ }
184
+ }