← Back to list

How We Served Multiple React Apps from a Single Domain Using GCP Load Balancer, Cloud Storage, and…

Most React deployment tutorials stop at:

Sashankbhardwaj · 2026-06-21 18:49 · 57 claps · 4.5 min read
#react #devops #google-cloud-platform #load-balancing #deployment
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval 🌐 · Web Development ☁️ · DevOps & Cloud

How We Served Multiple React Apps from a Single Domain Using GCP Load Balancer, Cloud Storage, and Cloud Run

Most React deployment tutorials stop at:

  • Build your React app
  • Upload it to a Cloud Storage bucket
  • Connect a domain

That works for simple websites, but production applications often need much more:

  • Multiple frontend applications under the same domain
  • SPA routing support
  • Deep links that don’t return 404s
  • Social media previews for dynamic pages
  • Bot-specific rendering for WhatsApp, Twitter, LinkedIn, Slack, and Facebook

In this article, I’ll show how we built a scalable frontend architecture on Google Cloud Platform that serves multiple React applications behind a single domain while supporting dynamic metadata generation for social sharing.

Architecture Overview

We use:

  • Google Cloud Storage for static frontend hosting
  • Global HTTP(S) Load Balancer for routing
  • Cloud Run for metadata generation
  • Custom route rules for SPA support
  • Custom error response for over writing 404 response on every dynamic route to 200

Traffic enters through a single load balancer:

User Request ↓ Global Load Balancer ├── Project 1 Bucket ├── Project 2 Bucket └── Cloud Run Metadata Service

The Problem

Deploying 2 or more frontend applications:

Example: we have two projects one as website and other as store front where users purchase products

Landing Website

Used for:

  • Marketing pages
  • Landing pages
  • Documentation
  • Public content
  • Blogs

Store Application

Used for:

  • Analytics
  • Product Collection
  • User profiles
  • Posts
  • product recommendations

Both applications needed to live under the same domain.

Why Cloud Storage?

React builds are static assets.

Instead of running Nginx or a VM, we host them in Cloud Storage buckets:

Bucket 1:

website-bucket

Bucket 2:

store-bucket

Benefits:

  • Near-zero maintenance
  • Automatic scalability
  • Extremely low cost
  • No server patching
  • No container management

Steps to setup a multi-project React frontend under single domain

This guide explains how to create an external HTTP(S) Load Balancer on a reserved global static IP, enable HTTP → HTTPS redirection, Cloud CDN caching, and path‑based routing to multiple Cloud Storage backend buckets.

It is split into two complete approaches:

  1. Using GCP Console (UI)
  2. Using CLI (gcloud + gsutil) (coming soon)

Architecture Overview

  • Load Balancer: External HTTP(S)
  • IP Address: Reserved global static IP
  • Protocols: HTTP (80), HTTPS (443)
  • Redirect: HTTP → HTTPS (301)
  • Backends (GCS):
  • bucket-website/
  • bucket-store/<stotre-routes>/*
  • Caching: Cloud CDN enabled

Using GCP Console (UI)

Step 1: Create Cloud Storage Buckets

Navigate to:

Cloud Storage → Buckets

Create two buckets:

BucketPurposewebsite-bucketMarketing website, landing pages, blogs, documentationstore-bucketStore application, products, collections, user profiles, posts

Upload your React production build files into the corresponding buckets.

For both buckets:

  • Enable public access to objects
  • Grant Storage Object Viewer access to allUsers

This allows the load balancer to serve static assets directly from Cloud Storage.

Step 2: Create Backend Buckets

Navigate to:

Network Services → Load Balancing

Create a new:

External HTTP(S) Load Balancer

Under backend configuration create:

Website Backend

Name

website-backend

Bucket

website-bucket

Optional:

Enable Cloud CDN

Store Backend

Name

store-backend

Bucket

store-bucket

Optional:

Enable Cloud CDN

At this stage both frontend applications are available as independent backend buckets.

Step 3: Configure URL Routing

The load balancer determines which application should receive incoming requests.

Set:

defaultService: website-backend

This means every request is routed to the website by default.

Next, create routing rules for store-related paths:

- prefixMatch: /route1
- prefixMatch: /route2
- prefixMatch: /route3
- prefixMatch: /route4
- prefixMatch: /docs

Route these paths to:

service: store-backend

Now both React applications can share the same domain while remaining independently deployable.

Example

example.com/
            → website-bucket
example.com/blog
            → website-bucket
example.com/product/123
            → store-bucket
example.com/profile/john
            → store-bucket

Step 4: Configure SPA Route Handling

One of the biggest challenges with React applications hosted on Cloud Storage is browser refresh behavior.

Consider:

https://example.com/product/123

When a user refreshes the page:

  1. Browser requests /product/123
  2. Cloud Storage looks for a file named /product/123
  3. File doesn’t exist
  4. Cloud Storage returns 404

To solve this, configure a custom error response policy.

For the website bucket:

customErrorResponsePolicy:
  errorResponseRules:
    - matchResponseCodes:
        - "404"
      overrideResponseCode: 200
      path: /index.html

Repeat the same configuration for the store bucket.

Now every unknown route loads:

index.html

allowing React Router to handle routing on the client side.

Benefits

  • Deep linking
  • Browser refresh support
  • Shareable URLs
  • Better user experience

Step 5: Configure Bot-Aware Metadata Routing

Single Page Applications introduce another challenge.

When a product URL is shared on:

  • WhatsApp
  • Twitter / X
  • LinkedIn
  • Slack
  • Facebook
  • Telegram

these platforms don’t execute React.

Instead they fetch the raw HTML response and look for Open Graph tags:

<meta property="og:title">
<meta property="og:image">
<meta property="og:description">

Since React generates these values client-side, social platforms often display empty or incomplete previews.

To solve this problem, create a Cloud Run service that generates metadata dynamically.

The load balancer can inspect the User-Agent header and route crawler traffic differently.

Example:

- matchRules:
    - headerMatches:
        - headerName: user-agent
          prefixMatch: WhatsApp
      prefixMatch: /product/
  service: metadata-service

Create similar rules for:

Twitterbot
Slackbot
TelegramBot
LinkedInBot
facebookexternalhit
Facebot

Request Flow

Normal User:

User
  ↓
Load Balancer
  ↓
store-bucket
  ↓
React Application

Social Bot:

WhatsApp / Twitter / Facebook Bot
  ↓
Load Balancer
  ↓
Cloud Run Metadata Service
  ↓
Dynamic Open Graph Response

This allows rich previews to appear automatically when links are shared.

Step 6: Configure HTTPS

Reserve a Global Static IP:

VPC Network → IP Addresses

Create a Google-managed SSL certificate and attach your domain.

Example:

example.com
www.example.com

Enable:

HTTP → HTTPS Redirect

Response Code:

301 Permanent Redirect

This ensures all traffic uses HTTPS.

Step 7: Update DNS

Point your domain’s A record to the reserved Global Static IP address.

After DNS propagation and SSL certificate provisioning complete, your architecture will look like:

Internet
                             │
                             ▼
                Global HTTP(S) Load Balancer
                             │
         ┌───────────────────┼───────────────────┐
         │                   │                   │
         ▼                   ▼                   ▼
   website-bucket      store-bucket       Cloud Run
                                           Metadata
                                           Service

Final Result

✅ Multiple React applications on a single domain

✅ Static hosting using Cloud Storage

✅ Global HTTPS Load Balancer

✅ SPA routing without 404 errors

✅ Independent frontend deployments

✅ Dynamic social media previews

✅ Optional Cloud CDN support

✅ No VMs or Nginx servers to manage

In the next section, we’ll configure the same architecture using gcloud and gsutil, making the entire infrastructure reproducible and automation-friendly.


메타데이터
post_id
273ea1657fa5
slug
how-we-served-multiple-react-apps-from-a-single-domain-using-gcp-load-balancer-cloud-storage-and-273ea1657fa5
url
https://medium.com/@sashankbhardwaj99/how-we-served-multiple-react-apps-from-a-single-domain-using-gcp-load-balancer-cloud-storage-and-273ea1657fa5
canonical_url
https://medium.com/@sashankbhardwaj99/how-we-served-multiple-react-apps-from-a-single-domain-using-gcp-load-balancer-cloud-storage-and-273ea1657fa5
author_url
https://medium.com/@sashankbhardwaj99
status
ok
fetched_at
2026-06-26 03:39:16