feat: add firebase configuration and deployment scripts

This commit introduces Firebase configuration files (.firebaserc,
firebase.json) and updates the Makefile to include deployment
commands for different environments (dev, staging).

The .firebaserc file defines Firebase projects for development and
staging, along with hosting targets.

The firebase.json file configures hosting settings, including
rewrites and ignores. It defines hosting targets for the main app
in dev and staging, and a separate target for an internal launchpad.

The Makefile is updated to include:
- GCP project IDs for dev and staging.
- Environment detection (ENV variable).
- Conditional variables based on the environment (GCP_PROJECT_ID,
 FIREBASE_ALIAS, HOSTING_TARGET).
- Deployment commands for the launchpad and the main app.
- The build command now passes the environment variable to the
 frontend build process.

The internal launchpad is added to firebase/internal-launchpad/index.html
to provide quick access to application URLs and Firebase/GCP
consoles for different environments.

A patch script is added to inject the environment label into the
Dashboard page.

The index.html title is changed to KROW.

These changes enable streamlined deployment and environment
management for the KROW application.
This commit is contained in:
bwnyasse
2025-11-14 08:53:00 -05:00
parent a4f1153d57
commit 9bdb250714
7 changed files with 171 additions and 52 deletions

30
.firebaserc Normal file
View File

@@ -0,0 +1,30 @@
{
"projects": {
"default": "krow-workforce-dev",
"dev": "krow-workforce-dev",
"staging": "krow-workforce-staging"
},
"targets": {
"krow-workforce-dev": {
"hosting": {
"launchpad": [
"krow-workforce-dev-launchpad"
],
"app-dev": [
"krow-workforce-dev"
],
"app-staging": [
"krow-workforce-staging"
]
}
},
"krow-workforce-staging": {
"hosting": {
"app-staging": [
"krow-workforce-staging"
]
}
}
},
"etags": {}
}

View File

@@ -4,11 +4,29 @@
# It is designed to be the main entry point for developers. # It is designed to be the main entry point for developers.
# Use .PHONY to declare targets that are not files, to avoid conflicts. # Use .PHONY to declare targets that are not files, to avoid conflicts.
.PHONY: install dev build prepare-export help .PHONY: install dev build prepare-export help deploy-launchpad deploy-app
# The default command to run if no target is specified (e.g., just 'make'). # The default command to run if no target is specified (e.g., just 'make').
.DEFAULT_GOAL := help .DEFAULT_GOAL := help
# --- Firebase & GCP Configuration ---
GCP_DEV_PROJECT_ID := krow-workforce-dev
GCP_STAGING_PROJECT_ID := krow-workforce-staging
# --- Environment Detection ---
ENV ?= dev
# --- Conditional Variables by Environment ---
ifeq ($(ENV),staging)
GCP_PROJECT_ID := $(GCP_STAGING_PROJECT_ID)
FIREBASE_ALIAS := staging
HOSTING_TARGET := app-staging
else
GCP_PROJECT_ID := $(GCP_DEV_PROJECT_ID)
FIREBASE_ALIAS := dev
HOSTING_TARGET := app-dev
endif
# Installs all project dependencies using npm. # Installs all project dependencies using npm.
install: install:
@echo "--> Installing web frontend dependencies..." @echo "--> Installing web frontend dependencies..."
@@ -24,7 +42,7 @@ dev:
# Builds the application for production. # Builds the application for production.
build: build:
@echo "--> Building web frontend for production..." @echo "--> Building web frontend for production..."
@cd frontend-web && npm run build @cd frontend-web && VITE_APP_ENV=$(ENV) npm run build
# Integrates a new Base44 export into the current project. # Integrates a new Base44 export into the current project.
# It replaces the src directory and the index.html file in the frontend-web directory. # It replaces the src directory and the index.html file in the frontend-web directory.
@@ -45,6 +63,8 @@ integrate-export:
@node scripts/patch-base44-client.js @node scripts/patch-base44-client.js
@echo " - Patching queryKey in Layout.jsx for local development..." @echo " - Patching queryKey in Layout.jsx for local development..."
@node scripts/patch-layout-query-key.js @node scripts/patch-layout-query-key.js
@echo " - Patching Dashboard.jsx for environment label..."
@node scripts/patch-dashboard-for-env-label.js
@echo "--> Integration complete. Next step: 'make prepare-export'." @echo "--> Integration complete. Next step: 'make prepare-export'."
# Applies all necessary patches to a fresh Base44 export to run it locally. # Applies all necessary patches to a fresh Base44 export to run it locally.
@@ -54,6 +74,15 @@ prepare-export:
@node scripts/prepare-export.js @node scripts/prepare-export.js
@echo "--> Preparation complete. You can now run 'make dev'." @echo "--> Preparation complete. You can now run 'make dev'."
# --- Firebase Deployment ---
deploy-launchpad:
@echo "--> Deploying Internal Launchpad to DEV project..."
@firebase deploy --only hosting:launchpad --project=dev
deploy-app: build
@echo "--> Deploying Frontend Web App to [$(ENV)] environment..."
@firebase deploy --only hosting:$(HOSTING_TARGET) --project=$(FIREBASE_ALIAS)
# Shows this help message. # Shows this help message.
help: help:
@echo "--------------------------------------------------" @echo "--------------------------------------------------"
@@ -64,6 +93,11 @@ help:
@echo " make build - Builds the web frontend for production." @echo " make build - Builds the web frontend for production."
@echo " make integrate-export - Integrates a new Base44 export from '../krow-workforce-export-latest'." @echo " make integrate-export - Integrates a new Base44 export from '../krow-workforce-export-latest'."
@echo " make prepare-export - Prepares a fresh Base44 export for local use." @echo " make prepare-export - Prepares a fresh Base44 export for local use."
@echo ""
@echo " --- DEPLOYMENT ---"
@echo " make deploy-launchpad - Deploys the internal launchpad (always to dev)."
@echo " make deploy-app [ENV=staging] - Builds and deploys the main web app (default: dev)."
@echo ""
@echo " make help - Shows this help message." @echo " make help - Shows this help message."
@echo "--------------------------------------------------" @echo "--------------------------------------------------"

View File

@@ -1,58 +1,49 @@
{ {
"firestore": {
"rules": "firebase/firestore.rules"
},
"storage": {
"rules": "firebase/storage.rules"
},
"hosting": [ "hosting": [
{ {
"target": "dev", "target": "launchpad",
"public": "frontend-web/dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
{
"target": "staging",
"public": "frontend-web/dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
{
"target": "prod",
"public": "frontend-web/dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
{
"target": "internal-launchpad",
"public": "firebase/internal-launchpad", "public": "firebase/internal-launchpad",
"ignore": [ "ignore": [
"firebase.json", "firebase.json",
"**/.*", "**/.*",
"**/node_modules/**" "**/node_modules/**"
] ]
},
{
"target": "app-dev",
"public": "frontend-web/dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
{
"target": "app-staging",
"public": "frontend-web/dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
} }
] ]
} }

View File

@@ -165,7 +165,7 @@
<div class="row"> <div class="row">
<div class="col-lg-6"> <div class="col-lg-6">
<div class="card shadow-sm mb-4"> <div class="card shadow-sm mb-4">
<div class="card-header"><h3>Applications</h3></div> <div class="card-header"><h3>Applications (Hosting URLs)</h3></div>
<div class="card-body"> <div class="card-body">
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-center"> <li class="list-group-item d-flex justify-content-between align-items-center">
@@ -196,6 +196,29 @@
</div> </div>
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<div class="card shadow-sm mb-4">
<div class="card-header"><h3>Google Cloud & Firebase Consoles</h3></div>
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-center">
<a target="_blank" href="https://console.firebase.google.com/project/krow-workforce-dev/overview">Firebase Console (Dev)</a>
<span class="badge bg-primary rounded-pill">Dev</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
<a target="_blank" href="https://console.firebase.google.com/project/krow-workforce-staging/overview">Firebase Console (Staging)</a>
<span class="badge bg-warning text-dark rounded-pill">Staging</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
<a target="_blank" href="https://console.cloud.google.com/welcome/new?project=krow-workforce-dev">Google Cloud Console (Dev)</a>
<span class="badge bg-primary rounded-pill">Dev</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
<a target="_blank" href="https://console.cloud.google.com/welcome/new?project=krow-workforce-staging">Google Cloud Console (Staging)</a>
<span class="badge bg-warning text-dark rounded-pill">Staging</span>
</li>
</ul>
</div>
</div>
<div class="card shadow-sm mb-4"> <div class="card shadow-sm mb-4">
<div class="card-header"><h3>Access & Resources</h3></div> <div class="card-header"><h3>Access & Resources</h3></div>
<div class="card-body"> <div class="card-body">

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="https://base44.com/logo_v2.svg" /> <link rel="icon" type="image/svg+xml" href="https://base44.com/logo_v2.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Base44 APP</title> <title>KROW</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@@ -88,7 +88,13 @@ export default function Dashboard() {
<div className="p-4 md:p-8 bg-gradient-to-br from-slate-50 to-slate-100 min-h-screen"> <div className="p-4 md:p-8 bg-gradient-to-br from-slate-50 to-slate-100 min-h-screen">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<PageHeader <PageHeader
title="Welcome to KROW" title={
<div className="flex items-center gap-2">
<span>Welcome to KROW</span>
{import.meta.env.VITE_APP_ENV === 'staging' && <Badge className="bg-yellow-100 text-yellow-800">Staging</Badge>}
{import.meta.env.VITE_APP_ENV === 'dev' && <Badge className="bg-slate-100 text-slate-800">Dev</Badge>}
</div>
}
subtitle="Your Complete Workforce Management Ecosystem" subtitle="Your Complete Workforce Management Ecosystem"
actions={ actions={
<> <>

View File

@@ -0,0 +1,35 @@
const fs = require('fs');
const path = require('path');
const projectRoot = path.resolve(__dirname, '..');
const dashboardFilePath = path.join(projectRoot, 'frontend-web', 'src', 'pages', 'Dashboard.jsx');
const oldString = ` <PageHeader
title="Welcome to KROW"`;
const newString = ` <PageHeader
title={
<div className="flex items-center gap-2">
<span>Welcome to KROW</span>
{import.meta.env.VITE_APP_ENV === 'staging' && <Badge className="bg-yellow-100 text-yellow-800">Staging</Badge>}
{import.meta.env.VITE_APP_ENV === 'dev' && <Badge className="bg-slate-100 text-slate-800">Dev</Badge>}
</div>
}`;
try {
const content = fs.readFileSync(dashboardFilePath, 'utf8');
if (content.includes(oldString)) {
const newContent = content.replace(oldString, newString);
fs.writeFileSync(dashboardFilePath, newContent, 'utf8');
console.log('✅ Successfully patched Dashboard.jsx to include environment label.');
} else if (content.includes('VITE_APP_ENV')) {
console.log(' Dashboard.jsx is already patched for environment labels. Skipping.');
} else {
console.error('❌ Patching Dashboard.jsx failed: Could not find the PageHeader title.');
process.exit(1);
}
} catch (error) {
console.error('❌ An error occurred during patching Dashboard.jsx:', error);
process.exit(1);
}