<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Hesham Ashraf</title>
    <description>The latest articles on Forem by Hesham Ashraf (@hesham_ash).</description>
    <link>https://forem.com/hesham_ash</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3604637%2Fc3d012b4-3547-4887-a258-e41cf5d4176f.png</url>
      <title>Forem: Hesham Ashraf</title>
      <link>https://forem.com/hesham_ash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hesham_ash"/>
    <language>en</language>
    <item>
      <title>From Localhost to Global Scale: Deploying a Multi-Agent AI Interior Designer with Google Cloud Run</title>
      <dc:creator>Hesham Ashraf</dc:creator>
      <pubDate>Mon, 10 Nov 2025 23:18:14 +0000</pubDate>
      <link>https://forem.com/hesham_ash/from-localhost-to-global-scale-deploying-a-multi-agent-ai-interior-designer-with-google-cloud-run-2mp4</link>
      <guid>https://forem.com/hesham_ash/from-localhost-to-global-scale-deploying-a-multi-agent-ai-interior-designer-with-google-cloud-run-2mp4</guid>
      <description>&lt;p&gt;This article details the technical architecture and deployment process for Multivra, an advanced AI interior design suite. &lt;strong&gt;This project and write-up were created as a submission for the Google AI Hackathon.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/rFIkEzviWOI"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h4&gt;
  
  
  Introduction: The Idea and the Challenge
&lt;/h4&gt;

&lt;p&gt;At its core, Multivra is more than just a text-to-image generator. It's a design co-pilot that employs a team of specialized AI agents—powered by the Google Gemini API—to transform a user's vision into a polished, professional mood board, complete with a photorealistic image and a detailed design rationale.&lt;/p&gt;

&lt;p&gt;Building this on my local machine was one thing, but making it available, reliable, and scalable for the world to use presented a classic developer challenge: how do you deploy a modern web application that might experience unpredictable, spiky traffic without over-provisioning resources or getting bogged down in server management?&lt;/p&gt;

&lt;p&gt;The answer was &lt;strong&gt;Google Cloud Run&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Cloud Run is the Perfect Fit for a GenAI App
&lt;/h4&gt;

&lt;p&gt;Cloud Run is a fully managed serverless platform that allows you to run containers without worrying about the underlying infrastructure. For a project like Multivra, it was the ideal choice for several key reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Serverless Simplicity:&lt;/strong&gt; My focus should be on building great features and perfecting AI prompts, not patching servers or configuring load balancers. Cloud Run abstracts all of that away.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Scale to Zero (and to Infinity):&lt;/strong&gt; A hackathon project might get a surge of traffic one day and none the next. Cloud Run automatically scales the number of running containers based on incoming requests. Crucially, if there are no requests, it scales down to zero, meaning &lt;strong&gt;I pay nothing for idle time&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Container-First Workflow:&lt;/strong&gt; The entire application—a React frontend built with Vite—can be neatly packaged into a container image. This creates a portable, consistent, and reproducible environment that runs the same on my machine as it does in the cloud.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  The Deployment Blueprint: A Step-by-Step Guide
&lt;/h4&gt;

&lt;p&gt;Here’s the exact process I followed to take Multivra from a local project folder to a publicly accessible URL.&lt;/p&gt;

&lt;h5&gt;
  
  
  Step 1: Containerizing the React App with a Multi-Stage Dockerfile
&lt;/h5&gt;

&lt;p&gt;The first step is to create a blueprint for our application's environment. Since we're building a static-site React app, a multi-stage &lt;code&gt;Dockerfile&lt;/code&gt; is the most efficient approach. This creates a temporary "builder" environment to compile our code, then copies only the essential, optimized static files into a final, lightweight production container.&lt;/p&gt;

&lt;p&gt;This keeps our final image small, secure, and fast.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dockerfile&lt;/span&gt;

&lt;span class="c"&gt;# ---- Stage 1: Build the React Application ----&lt;/span&gt;
&lt;span class="c"&gt;# Use an official Node.js image as the builder environment.&lt;/span&gt;
&lt;span class="c"&gt;# 'alpine' is a lightweight version.&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:20-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;

&lt;span class="c"&gt;# Set the working directory inside the container.&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy package.json and package-lock.json to leverage Docker layer caching.&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Install project dependencies.&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Copy the rest of the application source code.&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Build the application for production, creating an optimized 'dist' folder.&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build


&lt;span class="c"&gt;# ---- Stage 2: Serve the Static Files with a Web Server ----&lt;/span&gt;
&lt;span class="c"&gt;# Use a lightweight and secure web server image. Caddy is a great modern choice.&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; caddy:2-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Copy the build output from the 'builder' stage into Caddy's public directory.&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/dist /usr/share/caddy&lt;/span&gt;

&lt;span class="c"&gt;# Caddy will automatically serve the 'index.html' file from this directory.&lt;/span&gt;
&lt;span class="c"&gt;# No extra configuration is needed for this simple case.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Step 2: Build the Image and Push to Artifact Registry
&lt;/h5&gt;

&lt;p&gt;With our &lt;code&gt;Dockerfile&lt;/code&gt; ready, we need to build the container image and store it in a place Cloud Run can access. Google Artifact Registry is the perfect, secure place for this.&lt;/p&gt;

&lt;p&gt;I used Google Cloud Build to handle this process with a single command. Cloud Build automatically builds the image from my source code and pushes it to the registry.&lt;/p&gt;

&lt;p&gt;In my project's root directory, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First, ensure gcloud is configured to use your project&lt;/span&gt;
gcloud config &lt;span class="nb"&gt;set &lt;/span&gt;project &lt;span class="o"&gt;[&lt;/span&gt;YOUR_PROJECT_ID]

&lt;span class="c"&gt;# Submit the build to Cloud Build&lt;/span&gt;
gcloud builds submit &lt;span class="nt"&gt;--tag&lt;/span&gt; gcr.io/[YOUR_PROJECT_ID]/multivra:latest &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tells Cloud Build to take the code in the current directory (&lt;code&gt;.&lt;/code&gt;), find the &lt;code&gt;Dockerfile&lt;/code&gt;, build an image, tag it as &lt;code&gt;multivra:latest&lt;/code&gt;, and push it to my project's Google Container Registry (gcr.io).&lt;/p&gt;

&lt;h5&gt;
  
  
  Step 3: Deploying the Container to Cloud Run
&lt;/h5&gt;

&lt;p&gt;This is the magic moment. With our container image stored in the registry, we can deploy it to Cloud Run with another single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud run deploy multivra &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; gcr.io/[YOUR_PROJECT_ID]/multivra:latest &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--platform&lt;/span&gt; managed &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-central1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down these flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;--image&lt;/code&gt;: Points to the container we just pushed to the registry.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--platform managed&lt;/code&gt;: Tells Google to handle all the infrastructure.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--region&lt;/code&gt;: Specifies the physical location to run the service.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--allow-unauthenticated&lt;/code&gt;: Makes the service public so anyone can access the website.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a minute or so, the command line returned a public URL. And just like that, Multivra was live on the internet, backed by Google's scalable infrastructure.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Elephant in the Room: The API Key
&lt;/h4&gt;

&lt;p&gt;In a frontend-only application, the Gemini API key must be available to the browser. For this hackathon, the key was embedded during the build process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is not a secure, production-ready practice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a real-world application, exposing an API key on the client-side is a major security risk. The correct architecture is to introduce a simple backend service that acts as a proxy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Production-Ready Architecture:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Create a Backend:&lt;/strong&gt; A lightweight Node.js Express server (also running on Cloud Run) with a single endpoint, e.g., &lt;code&gt;/api/generate&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Secure the Key:&lt;/strong&gt; Store the Gemini API Key in Google Secret Manager. The backend Cloud Run service would be granted specific IAM permissions to access this secret at runtime.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Proxy the Request:&lt;/strong&gt; The React frontend would call &lt;code&gt;/api/generate&lt;/code&gt; on our backend. The backend service would then securely retrieve the API key from Secret Manager, make the call to the Gemini API, and return the response to the frontend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This way, the API key &lt;strong&gt;never&lt;/strong&gt; leaves the secure Google Cloud environment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;Deploying Multivra with Google Cloud Run was a fast, straightforward, and powerful experience. It allowed me to move from a local prototype to a globally scalable application in a matter of minutes, letting me focus on the core AI functionality rather than infrastructure.&lt;/p&gt;

&lt;p&gt;For developers working on AI-powered web apps, especially in fast-paced environments like hackathons or startups, the combination of a containerized workflow and a serverless platform like Cloud Run is, without a doubt, a game-changer.&lt;/p&gt;

&lt;p&gt;You can try out the Multivra application here: &lt;a href="https://multivra-327180202327.us-west1.run.app/" rel="noopener noreferrer"&gt;https://multivra-327180202327.us-west1.run.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>google</category>
      <category>serverless</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
