A web application to visualize organizational teams and members from JSON data files. This tool provides an interactive view of pods, teams, and team members with their roles, skillsets, and contract information.
- Google Workspace OAuth Authentication: Secure access restricted to authorized Google Workspace users
- Version Support: Switch between v1 and v2 pod data models using the version selector
- Pod Overview: View all pods with team counts, individual counts, vacancy counts, and leadership information
- Collapsible Sections: Expandable pods, teams, and solutions sections for easy navigation
- Team Members & Supporting Members: Teams display both regular members and supporting members separately
- Member Information: View comprehensive details including:
- Name and email
- Role and roleGroup
- Contract type (Permanent, 3rd Party Partner, Vacancy)
- Skillsets grouped by type: careerSkillset, teamSkillset, dailySkillset, generalCompetencies
- Supplier information (for 3rd Party Partners)
- Leave status
- Solutions Display: View solutions for each pod with collapsible sections
- Responsive Design: Works seamlessly on desktop and mobile devices
- API Protection: All API endpoints are protected with authentication middleware
This application uses Express.js as the backend server. To run it locally:
- Node.js (v14 or higher)
- npm (comes with Node.js)
- Install dependencies:
npm install-
Set up Google OAuth credentials:
- Go to the Google Cloud Console
- Create a new project or select an existing one
- Enable the Google+ API
- Go to "Credentials" → "Create Credentials" → "OAuth client ID"
- Choose "Web application"
- Add authorized redirect URIs:
http://localhost:3000/auth/google/callback(for local development)- Your production URL +
/auth/google/callback(for production)
- Copy the Client ID and Client Secret
-
Create a
.envfile in the root directory:
# Google OAuth Configuration
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
# Allowed domain for authentication (default: ovo.com)
ALLOWED_DOMAIN=ovo.com
# OAuth Callback URL (default: http://localhost:3000/auth/google/callback)
# For production, set this to your production URL
CALLBACK_URL=http://localhost:3000/auth/google/callback
# Session Secret (change this to a random string in production)
SESSION_SECRET=your-random-session-secret-key-change-in-production
# Server Port (default: 3000)
PORT=3000
# Node Environment
NODE_ENV=developmentDevelopment mode (with auto-reload):
npm run devProduction mode:
npm startThe server will start on http://localhost:3000 (or the port specified in the PORT environment variable).
Public Endpoints:
GET /auth/google- Initiate Google OAuth loginGET /auth/google/callback- OAuth callback handlerGET /auth/logout- Logout userGET /auth/status- Check authentication status
Protected Endpoints (require authentication):
GET /api/pods/:version- Get all pods for a specific version (e.g.,/api/pods/v1)
The application includes a Dockerfile for containerized deployment.
docker build -t ovo-product-tech-visualization .docker run -d \
-p 3000:3000 \
-e GOOGLE_CLIENT_ID=your-client-id \
-e GOOGLE_CLIENT_SECRET=your-client-secret \
-e ALLOWED_DOMAIN=ovo.com \
-e CALLBACK_URL=http://localhost:3000/auth/google/callback \
-e SESSION_SECRET=your-session-secret \
--name ovo-app \
ovo-product-tech-visualizationCreate a docker-compose.yml file:
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
- ALLOWED_DOMAIN=${ALLOWED_DOMAIN:-ovo.com}
- CALLBACK_URL=${CALLBACK_URL:-http://localhost:3000/auth/google/callback}
- SESSION_SECRET=${SESSION_SECRET}
- NODE_ENV=production
- PORT=3000
restart: unless-stoppedThen run:
docker-compose up -dThe repository includes a GitHub Actions workflow that automatically deploys to Google Cloud Run on pushes to main.
-
Create a Google Cloud Project:
gcloud projects create YOUR_PROJECT_ID gcloud config set project YOUR_PROJECT_ID -
Enable required APIs:
gcloud services enable cloudbuild.googleapis.com gcloud services enable run.googleapis.com gcloud services enable artifactregistry.googleapis.com
-
Create a Service Account:
gcloud iam service-accounts create github-actions \ --display-name="GitHub Actions Service Account" gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="serviceAccount:github-actions@YOUR_PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/run.admin" gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="serviceAccount:github-actions@YOUR_PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/artifactregistry.writer" gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="serviceAccount:github-actions@YOUR_PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/iam.serviceAccountUser"
-
Create and download Service Account key:
gcloud iam service-accounts keys create key.json \ --iam-account=github-actions@YOUR_PROJECT_ID.iam.gserviceaccount.com
-
Configure GitHub Secrets: Go to your GitHub repository → Settings → Secrets and variables → Actions, and add:
GCP_PROJECT_ID: Your Google Cloud project IDGCP_REGION: Your preferred region (e.g.,us-central1,europe-west1)GCP_SA_KEY: Contents of thekey.jsonfile (the entire JSON)GOOGLE_CLIENT_ID: Your Google OAuth client IDGOOGLE_CLIENT_SECRET: Your Google OAuth client secretALLOWED_DOMAIN: Domain restriction (e.g.,ovo.com)CALLBACK_URL: Your Cloud Run service URL +/auth/google/callback(update after first deployment)SESSION_SECRET: A strong random string for session encryption
-
Deploy:
- Push to
mainbranch to trigger automatic deployment - Or manually trigger via GitHub Actions → "Deploy to Google Cloud Run" → Run workflow
- Push to
# Build and push image
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/ovo-product-tech-visualization
# Deploy to Cloud Run
gcloud run deploy ovo-product-tech-visualization \
--image gcr.io/YOUR_PROJECT_ID/ovo-product-tech-visualization \
--platform managed \
--region us-central1 \
--allow-unauthenticated=false \
--set-env-vars="GOOGLE_CLIENT_ID=your-client-id,GOOGLE_CLIENT_SECRET=your-secret,ALLOWED_DOMAIN=ovo.com,CALLBACK_URL=https://your-service-url.run.app/auth/google/callback,SESSION_SECRET=your-session-secret,NODE_ENV=production"Docker-based platforms:
- Docker Hub / AWS ECS / Kubernetes: Use the provided Dockerfile
Heroku:
heroku create your-app-name
git push heroku mainRailway:
- Connect your GitHub repository
- Railway will auto-detect Node.js and deploy
Render:
- Connect your GitHub repository
- Set build command:
npm install - Set start command:
npm start
Vercel/Netlify:
- These platforms support Express.js serverless functions
- Configure as a Node.js application
Required environment variables (see .env.example for template):
GOOGLE_CLIENT_ID- Your Google OAuth Client IDGOOGLE_CLIENT_SECRET- Your Google OAuth Client SecretALLOWED_DOMAIN- Domain restriction for authentication (default:ovo.com)CALLBACK_URL- OAuth callback URL (default:http://localhost:3000/auth/google/callback)SESSION_SECRET- Secret key for session encryption (use a strong random string in production)PORT- Server port (default:3000)NODE_ENV- Node environment (developmentorproduction)
Important: Never commit your .env file to version control. It's already in .gitignore.
.
├── public/ # Public static files
│ ├── index.html # Main HTML structure
│ ├── styles.css # Styling and layout
│ └── app.js # Client-side application logic
├── server/ # Server-side code
│ ├── index.js # Express server entry point
│ ├── config/ # Configuration files
│ │ ├── auth.js # Passport.js Google OAuth configuration
│ │ └── session.js # Express session configuration
│ ├── middleware/ # Express middleware
│ │ └── auth.js # Authentication middleware
│ ├── routes/ # API routes
│ │ ├── index.js # Main router
│ │ ├── auth.js # Authentication routes
│ │ └── pods.js # Pod data routes
│ └── lib/ # Utility functions
│ ├── getPodFiles.js # Get pod file list
│ ├── loadPodFile.js # Load pod JSON file
│ └── sortPodsByName.js # Sort pods alphabetically
├── pods/ # Pod data files directory
│ ├── schema.json # JSON schema for pod validation
│ ├── v1/ # Version 1 pod data files
│ │ └── *.json # Individual pod data files
│ └── v2/ # Version 2 pod data files
│ └── *.json # Individual pod data files (when available)
├── scripts/ # Utility scripts
│ └── validate-all-schema.js # Schema validation script
├── data/ # Source data files (CSV files)
├── .env # Environment variables (not committed)
├── .env.example # Environment variables template
├── package.json # Node.js dependencies and scripts
└── README.md # This file
Each pod JSON file follows the schema defined in pods/schema.json and includes:
- name: Pod name
- leadership: Array of leadership names
- solutions: Array of solutions, each with:
- name: Solution name
- description: Solution description
- teams: Array of teams, each containing:
- name: Team name
- members: Array of team members with:
- Basic info: name, email, role, roleGroup, contractType
- Skillsets: careerSkillset, teamSkillset, dailySkillset, generalCompetencies
- Additional: supplier (for 3rd Party Partners), onLeave status
- supporting: Array of supporting members (pod-members who support the team but are not present within it) with:
- Basic info: name, email, role, roleGroup
- Optional: contractType, skillsets, supplier, onLeave
Validate all pod JSON files against the schema:
node scripts/validate-all-schema.jsThis ensures all pod data files conform to the expected structure.
- Login: When you first access the application, you'll be prompted to log in with your Google Workspace account
- Authentication: Only users with email addresses from the configured domain (default:
@ovo.com) can access the application - Select Version: Use the version selector at the top to switch between v1 and v2 pod data
- Browse Pods: The main view shows all pods as collapsible cards, sorted alphabetically
- Expand Pods: Click on a pod header to expand and see its content (leadership, solutions, teams)
- View Solutions: Click on the solutions header to expand and view all solutions for a pod
- View Teams: Each pod shows its teams with member counts and supporting member counts
- Expand Teams: Click on a team header to see all team members and supporting members
- View Member Details: Each member card displays:
- Role, roleGroup, and contract type
- Skillsets grouped by type (career, team, daily, general competencies)
- Supplier information (for 3rd Party Partners)
- Leave status (if applicable)
- Supporting Members: Supporting members are displayed separately from regular team members with distinct styling
- Logout: Click the logout button in the header to end your session
Data files in the data/ directory are gitignored and not committed to the repository. These typically contain source data used to generate or update the pod JSON files.
- All API endpoints are protected with authentication middleware
- Only users with email addresses from the configured domain can access the application
- Sessions are encrypted using the
SESSION_SECRETenvironment variable - In production, ensure
NODE_ENV=productionis set to enable secure cookies (HTTPS required)
When adding or updating pod data:
- Ensure the JSON file follows the schema in
pods/schema.json - Validate your changes using the validation script
- Test locally before pushing changes
- Ensure all environment variables are properly configured for your deployment environment