Routing problems with Volto Loopback port

The problem:
We are having issues with the Volto Loopback port starting on pod port + 1. As you can see in the error messages from the Chrome console below:

First solution attempt: 404 error when setting CLIENT_PUBLIC_PATH for the same domain thats listening on port 3000:

       GET http://siteplone.frontend.apps-crc.testing/static/js/runtime~client.js 404 (Not Found)
siteplone.frontend.apps-crc.testing/:2 
       GET http://siteplone.frontend.apps-crc.testing/static/media/Logo.16e25cdf.svg 404 (Not Found)
siteplone.frontend.apps-crc.testing/:2 
       GET http://siteplone.frontend.apps-crc.testing/static/js/client.js net::ERR_ABORTED 404 (Not Found)

Second solution attempt: CORS error when using different domains. The Loopback domain is listening on port 3001 (ChatGPT suggested this approach as a solution):

       Access to script at 'http://siteplone.loopback.frontend.apps-crc.testing/static/js/client.js' from origin 'http://siteplone.frontend.apps-crc.testing' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
siteplone.frontend.apps-crc.testing/:2 
       Access to script at 'http://siteplone.loopback.frontend.apps-crc.testing/static/js/runtime~client.js' from origin 'http://siteplone.frontend.apps-crc.testing' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Calling localhost domain when not setting CLIENT_PUBLIC_PATH (application is not running on local environment):

       GET http://localhost:3001/static/media/Logo.16e25cdf.svg net::ERR_CONNECTION_REFUSED
siteplone.frontend.apps-crc.testing/:2 
       GET http://localhost:3001/static/js/runtime~client.js net::ERR_CONNECTION_REFUSED
siteplone.frontend.apps-crc.testing/:2 
       GET http://localhost:3001/static/js/client.js net::ERR_CONNECTION_REFUSED

Log from the make start command inside the pod showing the Loopback configuration:

> @plone/volto@18.0.0-alpha.43 start /opt/app-root/src/core/packages/volto
> make build-deps && razzle start
Using volto.config.js in: /opt/app-root/src/volto.config.js
WAIT Compiling...
ℹ Compiling Client
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:3001/, http://[::1]:3001/
<i> [webpack-dev-server] Content not from webpack is served from '/opt/app-root/src/core/packages/volto/public' directory
<i> [webpack-dev-server] 404s will fallback to '/index.html'
✔ Client: Compiled successfully in 52.28s

Explaining our environment:
We are using Plone 6 (backend folder) and Volto (frontend folder) running with pnpm generated with cookieplone with default ports (8080, 3000 and 3001). The deployment is separated into 2 pods, a Python image and a Node image using S2I (Source-to-Image) inside a Single Node Openshift installation for development purposes. We are not using Production yet.

More details about the situation:
Our builds are working fine and the backend is working with CORS configured correctly. The Volto frontend build is also working with a custom S2I script that calls make start and make install commands, but we couldn't find a solution for this call to port 3001 on our frontend. As you can see from the messages above, we tried 2 different approaches to solve the problem, but none of them worked.
One of the solutions was a response from ChatGPT saying that we need to split into two domains and this gave us a CORS error on the frontend. I find it a bit strange to put CORS rules on the Node frontend, since it's not a common scenario, so we're discarding that solution for now. GPT recommended this approach because automatic deployments with OpenShift use Routes by default that do not use a YAML Ingress and in Routes you cannot expose to the internet by default a port other than 80 (http) and 443 (https) or explaining in other words: The Route has a mandatory parameter requesting a targetPort to forward to a specific domain that is responding on port 80 or 443 (1:1).
Another solution we tried is to use the same domain that is consuming port 3000, but it says it cannot find some js files returning 404, so it seems that Volto serves specific files that are only found on port 3001.
In all situations, we change the domain for port 3001 calls using the CLIENT_PUBLIC_PATH environment variable. If we do not set this variable, the browser sends a request to localhost:3001, as shown in the message errors above.

The question:
Is there a way to disable Loopback port 3001 and deliver everything to the same port 3000 so that the browser always calls the same domain?

I've seen in other posts someone talking about enabling Production mode, but I don't know if that relates to this issue (and I currently don't know how to change the frontend to that mode). We've already searched the official documentation and didn't find anything specific to the Loopback port.

About this post: I got an error saying "Desculpe, não é possível incorporar itens de mídia nesta postagem." when I tried to upload jpg screenshots, so I was forced to post just the error messages.

Openshift and pods is a bit non-standard but it sounds like you're making progress.
I would point you towards seamless mode.
The example below is based on nginx on a basic server but hopefully should give you some ideas.

Thanks for the quick response @pigeonflight. I had to accompany my son to the hospital and was away for some time.

I can't find a way to properly enable Seamless mode on our project built with cookieplone. We are using PNPM and not YARN.

Our goal is to enable hot reloading in an Openshift development environment. We will use Openshift client commands to enable "remote development" for some users so they can make changes and test them without the need of a local environment. Our priority now is to have this development environment available and later we will work on our Production build process.

I tried the solution below but it didn't work (another solution from ChatGPT). We tried changing the port and enabling access with CORS header:

volto.config.js

const addons = ['volto-procergs-siteplone'];
const theme = '';

// Extend Webpack configuration
module.exports = (config) => {
  // Keep your existing addons and theme
  config.addons = addons;
  config.theme = theme;

  // Extend Webpack dev server configuration
  config.devServer = {
    port: 3000, // Force it to only use port 3000
    host: '0.0.0.0', // Allow access from any IP
    hot: true, // Enable hot reloading
    historyApiFallback: true, // Fallback for SPA routing
    client: {
      overlay: {
        warnings: false,
        errors: true,
      },
    },
    headers: {
      'Access-Control-Allow-Origin': '*', // Optional: Add CORS header if needed
    },
  };

  return config;
};

We have 2 options to solve this issue:

  1. Best solution - Make the project run on a single port with hot reload enabled (maybe using Seamless will help)

  2. Alternative solution - Adding Access-Control-Allow-Origin in the devServer configuration like in the code I showed above.

Can you help us understand what we need to do to make one of the above options work?

Here is the link to our public repository and the branch with this specific configuration file:

If you are curious about how we got the project working on OpenShift, the .s2i folder inside the backend and frontend folders contains our assemble process (Source-to-Image scripts) and is currently not finished as we will introduce production variables later and refine it with more features. Much of the code comes from the default S2I script inside the RedHat Images and we will change it once we are ready for Production. For Volto, we are using the Node Images from the RedHat catalog like this one:
https://catalog.redhat.com/software/containers/ubi9/nodejs-20/64770ac7a835530172eee6a9