System Architecture
ForgeX is built on a modern microservices architecture with subdomain-based routing, providing true service isolation, independent scaling, and seamless single sign-on across all apps.
High-Level Architecture
Legend: 🟢 Green = Live/Operational | 🟠 Orange = Planned for future phases
Service Overview
ForgeX consists of 4 core services, each with its own frontend, backend, and database:
- Portal Service
- Bids Service
- Projects Service
- Field Service
Purpose: Authentication & App Launcher
| Aspect | Details |
|---|---|
| URL | https://forge.precisionsiteservices.com |
| Port (Dev) | 3000 |
| Status | ✅ Operational |
| Tech | React, Firebase Hosting |
Features:
- Centralized Google OAuth entry point via SuperTokens
- App tile selection interface
- Role-based app visibility (users only see apps they have access to)
- User profile display
- Session management via HTTP-only cookies
Why it exists:
- Single Sign-On (SSO): Sign in once, access all services
- Security: Centralized auth reduces attack surface, SuperTokens handles session security
- User Experience: Unified entry point for the entire platform
Purpose: Bid Management & Estimation
| Aspect | Details |
|---|---|
| URL | https://bids.precisionsiteservices.com |
| Ports (Dev) | Frontend: 3001, Backend: 5001 |
| Database | bids_db (PostgreSQL, 27 models) |
| Status | ✅ Fully Operational (Phase 1) |
| Tech | React, Node.js, Prisma, Express |
Features:
- Client & bid CRUD operations
- 6 estimation modules (Concrete, Labor, Equipment, Materials, Subcontractor, Misc)
- Automatic cost rollup (items → scopes → bids)
- Pricing catalog management
- Global variables configuration
- PDF generation for proposals
- File attachments (plans, specs, photos)
- Bid duplication and templating
- Scope linking (parent-child relationships)
- Tax exemption support
Database Models:
- User, Client, Bid, Scope
- ConcreteItem, LaborItem, EquipmentItem, MaterialItem, SubcontractorItem, MiscItem
- PricingItem, BidPricingItem, GlobalVariable, BidGlobalVariable
- RebarRate, EquipmentRate, MaterialRate, Employee
- ScopeType, ScopeTypeMaterialCategory, AuditLog
Purpose: Purchase Orders & Cost Tracking
| Aspect | Details |
|---|---|
| URL | https://projects.precisionsiteservices.com |
| Ports (Dev) | Frontend: 3002, Backend: 5002 |
| Database | projects_db (PostgreSQL, 6 models) |
| Status | ⏳ Phase 2 (Planned) |
| Tech | React, Node.js, Prisma, Express |
Planned Features:
- Auto-create projects from awarded bids (via Pub/Sub event)
- Purchase order workflow management
- Type-specific PO forms (materials, equipment, subcontractors)
- Receipt upload and tracking
- Cost tracking vs. bid estimates
- PM approval workflow
- Accounting reconciliation
- Vendor management
Database Models (Planned):
- Project, PurchaseOrder, Receipt, Vendor, Approval, CostTracking
Integration:
- Listens to
BID_AWARDEDevents from Bids Service - Publishes
PROJECT_CREATED,PO_APPROVEDevents
Purpose: Timesheets & GPS Tracking
| Aspect | Details |
|---|---|
| URL | https://field.precisionsiteservices.com |
| Ports (Dev) | Frontend: 3003, Backend: 5003 |
| Database | field_db (PostgreSQL, 10 models) |
| Status | ⏳ Phase 3 (Planned) |
| Tech | React, Node.js, Prisma, Express |
Planned Features:
- PIN-based worker authentication (no Google accounts needed)
- GPS clock-in/out with geofencing
- Timesheet management and approval
- Foreman dashboard
- Daily job logs
- Crew management
- Equipment usage tracking
Database Models (Planned):
- Worker, Timesheet, GPSLog, JobLog, Crew, Equipment, Approval
Integration:
- Links to Projects Service for job assignments
- Timesheets feed into cost tracking
Database Isolation
Each service has its own dedicated PostgreSQL database, ensuring data isolation and independent scaling.
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ bids_db │ │ projects_db │ │ field_db │
│ │ │ │ │ │
│ • 27 models │ │ • 6 models │ │ • 10 models │
│ • Bids, Scopes │ │ • Projects │ │ • Workers │
│ • 6 Item types │ │ • POs, Receipts │ │ • Timesheets │
│ • Pricing, Vars │ │ • Vendors │ │ • GPS logs │
│ • Audit logs │ │ • Approvals │ │ • Job logs │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
Why Separate Databases?
| Benefit | Description |
|---|---|
| Data Isolation | Service failures don't cascade across the platform |
| Independent Scaling | Scale databases based on service-specific load |
| Security | Limit data access per service (least privilege) |
| Schema Evolution | Change schemas without affecting other services |
| Backup/Recovery | Restore services independently |
No direct database connections between services. All communication happens via REST APIs or Pub/Sub events.
Authentication Flow
ForgeX uses SuperTokens with Google Workspace OAuth for enterprise authentication and session management.
Key Points
User navigates to https://forge.precisionsiteservices.com
SuperTokens handles OAuth flow with Google:
- Only @precisionsiteservices.com emails allowed
- Google handles password, 2FA, etc.
- SuperTokens manages the entire authentication flow
SuperTokens creates a secure session containing:
- User ID, email, name, role
- Session expiration (configurable, typically 24 hours)
- Refresh token for seamless re-authentication
Session is stored as HTTP-only cookies on .precisionsiteservices.com
User sees available apps based on their role:
- ADMIN: All apps
- ESTIMATOR: Bids
- PM: Bids (read-only), Projects
- OPS: Projects, Field
- ACCOUNTING: Projects
- FOREMAN: Field only
SuperTokens session cookies are shared across all subdomains:
forge.precisionsiteservices.com✅bids.precisionsiteservices.com✅projects.precisionsiteservices.com✅field.precisionsiteservices.com✅
No re-authentication needed! Seamless SSO via shared session cookies.
Security Features
- SuperTokens Session Management: Self-hosted authentication core with secure session handling and automatic token rotation
- HTTP-Only Cookies: Prevents XSS attacks (JavaScript can't access session tokens -
sAccessToken,sRefreshToken) - SameSite Cookie Policy: CSRF protection built-in
- Session Expiration: Sessions expire after 24 hours with automatic refresh token rotation
- Domain Restriction: Only
@precisionsiteservices.comemails allowed via Google Workspace OAuth - Self-Hosted: Full control over authentication infrastructure (no third-party access to session data)
- No JWT in Frontend: All authentication handled via secure HTTP-only cookies, not localStorage or sessionStorage
Subdomain Routing
ForgeX uses subdomain-based routing, an industry-standard pattern used by companies like Stripe, GitHub, and Netlify.
Production URLs
| Subdomain | Service | Purpose |
|---|---|---|
forge.* | Portal | Authentication & app launcher |
bids.* | Bids | Bid management |
projects.* | Projects | Project management (Phase 2) |
field.* | Field | Field operations (Phase 3) |
Why Subdomains?
True Service Isolation
Each service has its own URL, frontend bundle, and backend. No shared code at runtime (only build-time via packages/shared).
Independent Deployment
Deploy services independently without affecting others. Update Bids Service without touching Projects or Field.
Shared Authentication
SuperTokens session cookies work across subdomains on the same parent domain (.precisionsiteservices.com).
Security (XSS Isolation)
XSS vulnerability in one service doesn't compromise others (different origins).
Scalability
Scale services independently based on load:
- Bids Service: 5 Cloud Run instances
- Projects Service: 2 instances
- Field Service: 3 instances (mobile-heavy)
Future-Proof
Easy to add new services:
reporting.precisionsiteservices.com- Analytics dashboardadmin.precisionsiteservices.com- Admin panelapi.precisionsiteservices.com- Public API gateway
Local Development
Docker Compose orchestrates all services locally, simulating the production environment:
services:
# Databases
bids-db: # PostgreSQL for Bids Service
projects-db: # PostgreSQL for Projects Service
field-db: # PostgreSQL for Field Service
# Frontends (React)
portal: # Port 3000
bids-frontend: # Port 3001
projects-frontend: # Port 3002
field-frontend: # Port 3003
# Backends (Node.js/Express)
bids-backend: # Port 5001
projects-backend: # Port 5002
field-backend: # Port 5003
Local URLs
| Service | URL |
|---|---|
| Portal | http://localhost:3000 |
| Bids (Frontend) | http://localhost:3001 |
| Bids (API) | http://localhost:5001/api |
| Projects (Frontend) | http://localhost:3002 |
| Field (Frontend) | http://localhost:3003 |
Local vs. Production: Local uses localhost ports instead of subdomains. SuperTokens session cookies are set on localhost for local development.
Production Deployment
ForgeX is deployed on Google Cloud Platform (GCP) with a fully managed infrastructure.
- Frontend (Firebase Hosting)
- Backend (Cloud Run)
- Database (Cloud SQL)
- Storage (Cloud Storage)
- Event Bus (Pub/Sub)
Platform: Firebase Hosting (Google CDN)
Workflow:
# Build production bundle
npm run build
# Deploy to Firebase
firebase deploy --only hosting:bids
Features:
- Global CDN distribution (low latency worldwide)
- Automatic SSL certificates
- HTTP/2 and Brotli compression
- Atomic deployments (zero downtime)
- Rollback to previous versions
Static Assets:
- HTML, CSS, JS bundles
- Images, fonts, icons
- Service worker (for PWA features)
Platform: Google Cloud Run (serverless containers)
Workflow:
# Build Docker image
docker build -t gcr.io/PROJECT/bids-backend .
# Push to Google Container Registry
docker push gcr.io/PROJECT/bids-backend
# Deploy to Cloud Run
gcloud run deploy bids-backend \
--image gcr.io/PROJECT/bids-backend \
--platform managed \
--region us-central1
Features:
- Auto-scaling: 0 to N instances based on load
- Pay-per-request: No cost when idle
- Automatic HTTPS: Managed SSL certificates
- Container-based: Run any language/framework
- Health checks: Auto-restart unhealthy instances
Configuration:
- Min instances: 1 (prevent cold starts)
- Max instances: 10 (cost control)
- Memory: 512 MB per instance
- Timeout: 60 seconds per request
Platform: Cloud SQL for PostgreSQL (managed database)
Configuration:
Instance: pss-bidmanager-db
Version: PostgreSQL 14
Machine type: db-n1-standard-1 (1 vCPU, 3.75 GB RAM)
Storage: 10 GB SSD (auto-scaling enabled)
Backups: Daily at 3:00 AM UTC (7-day retention)
High availability: Disabled (Phase 1)
Features:
- Automatic backups: Daily snapshots (7-day retention)
- Point-in-time recovery: Restore to any second in the last 7 days
- Connection pooling: PgBouncer for efficient connections
- SSL/TLS encryption: Encrypted connections from backends
- Private IP: Not exposed to public internet
Access:
- Backends connect via private VPC peering
- Developers connect via Cloud SQL Proxy (local tunnel)
Platform: Google Cloud Storage (object storage)
Buckets:
pss-bidmanager-attachments- Bid attachments (plans, specs)pss-bidmanager-receipts- PO receipts (Phase 2)pss-bidmanager-photos- Field photos (Phase 3)
Features:
- Signed URLs: Time-limited access to private files
- Lifecycle policies: Auto-delete temp files after 30 days
- CORS configuration: Frontend can upload directly
- Versioning: Keep old versions of files (optional)
Upload Flow:
// Backend generates signed URL
const signedUrl = await storage.bucket(bucket).file(filename).getSignedUrl({
action: 'write',
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
})
// Frontend uploads directly to GCS
await fetch(signedUrl, {
method: 'PUT',
body: file,
headers: { 'Content-Type': file.type },
})
Platform: Google Cloud Pub/Sub (event streaming)
Status: ⏳ Phase 2 (planned for inter-service communication)
Topics:
bid-events- Bid lifecycle events (created, awarded, lost)project-events- Project events (created, completed)field-events- Field events (timesheet submitted, approved)
Subscriptions:
projects-service-sub- Projects Service listens tobid-eventsfield-service-sub- Field Service listens toproject-events
Event Flow:
Bids Service → Pub/Sub → Projects Service
BID_AWARDED event → Auto-create Project
Why Pub/Sub?
- Decoupling: Services don't need to know about each other
- Reliability: Events are retried on failure
- Asynchronous: Non-blocking, no timeouts
- Scalability: Handles millions of events per second
Role-Based Access Control (RBAC)
ForgeX implements fine-grained role-based access control at both the service and resource levels.
Roles
| Role | Bids Service | Projects Service | Field Service |
|---|---|---|---|
| ADMIN | Full access | Full access | Full access |
| ESTIMATOR | Full access (no delete bids) | Read-only | - |
| PM | Read-only | Approve POs, view costs | Approve timesheets |
| OPS | - | Create/manage POs | - |
| ACCOUNTING | - | Reconcile, view costs | - |
| FOREMAN | - | - | Clock in/out, view crew |
Permission Model
// Middleware checks role before allowing actions
if (action === "DELETE_BID" && user.role !== "ADMIN") {
return res.status(403).json({ error: "Forbidden: Admin only" });
}
if (action === "APPROVE_PO" && !["ADMIN", "PM"].includes(user.role)) {
return res.status(403).json({ error: "Forbidden: PM or Admin required" });
}
Audit Logging
All actions are logged to the AuditLog table:
{
userId: "user-123",
action: "UPDATE_BID",
resourceType: "Bid",
resourceId: "bid-456",
changes: { status: "DRAFT" → "SUBMITTED" },
timestamp: "2025-01-29T12:34:56Z"
}
Tech Stack Summary
- Frontend
- Backend
- Database
- Infrastructure
- Development
- Framework: React 18 with TypeScript
- Styling: Tailwind CSS
- UI Library: shadcn/ui (Radix UI primitives)
- State Management: Zustand (global state), React Query (server state)
- Routing: React Router v6
- Forms: React Hook Form + Zod validation
- HTTP Client: Axios
- Build Tool: Vite
- Runtime: Node.js v20+
- Framework: Express.js
- ORM: Prisma (type-safe database client)
- Validation: Zod schemas
- Authentication: SuperTokens Core (self-hosted) with Google OAuth
- Session Management: SuperTokens SDK (HTTP-only cookies, no JWT)
- Email: Resend API for transactional emails
- File Upload: Multer + Google Cloud Storage
- PDF Generation: jsPDF (client-side)
- RDBMS: PostgreSQL 14
- Migrations: Prisma Migrate
- Query Builder: Prisma Client
- Connection Pooling: PgBouncer (production)
- Hosting (Frontend): Firebase Hosting
- Hosting (Backend): Google Cloud Run
- Database: Cloud SQL for PostgreSQL
- Storage: Google Cloud Storage
- Event Bus: Cloud Pub/Sub (Phase 2+)
- DNS/SSL: Cloudflare
- CI/CD: GitHub Actions
- Containerization: Docker + Docker Compose
- Monorepo: Lerna (shared packages)
- Code Quality: ESLint, Prettier
- Version Control: Git (GitHub)
- Database GUI: Prisma Studio
Next Steps
Quickstart
Set up your local development environment
Core Concepts
Understand the ForgeX data model
API Reference
Explore the REST API
Deployment Guide
Deploy ForgeX to production
This architecture supports Phase 1 (Bids Service). Phase 2/3 features are planned and subject to change.