CEF (Chromium Embedded Framework) in Application loses keyboard focus after mouse clicks on Ubuntu 22.04

I’m experiencing a critical keyboard focus issue with CEF (Chromium Embedded Framework) running on Ubuntu 22.04. After any mouse click within the CEF window, all keyboard events stop being captured, making keyboard shortcuts like Ctrl++ completely non-functional.

System Information:

  • OS: Ubuntu 22.04 LTS
  • CEF Version: Chrome/104.0.5112.102 (based on user agent)
  • Hardware: 12-core CPU, 8GB RAM, Linux x86_64
  • Browser Engine: WebKit/537.36 (KHTML, like Gecko)

Initial State (Working):

  • The page loads correctly with keyboard focus.
  • Keyboard shortcuts (Ctrl++, Space, etc.) work as expected.
  • All key events are captured and processed.

After Mouse Click (Broken):

  • Any mouse click within the CEF window causes a complete loss of keyboard focus.
  • No keyboard events (keydown/keyup) are received.
  • Keyboard shortcuts stop working entirely.
  • The focus indicator shows the page as “not focused.”

Focus Recovery Observations:

  • ✅ WORKS: Minimizing or maximizing the window restores keyboard focus.
  • ✅ WORKS: Switching windows with Alt+Tab restores keyboard focus.
  • ❌ FAILS: Using JavaScript methods like document.body.focus(), document.documentElement.focus(), or window.focus().
  • ❌ FAILS: Setting tabIndex=-1 on body/html elements.
  • ❌ FAILS: All standard DOM focus management techniques.

Technical Details from Event Logs:

System Info: {
  "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36",
  "platform": "Linux x86_64",
  "language": "en",
  "cookieEnabled": true,
  "onLine": true,
  "hardwareConcurrency": 12,
  "deviceMemory": 8
}

Typical event sequence:
[1] Page loaded - keyboard events working
[2] Click on DIV - focus lost immediately
[3] Ctrl++ pressed - no keyboard event received
[4] document.hasFocus() returns false
[5] Alt+Tab away and back - focus restored
[6] Ctrl++ pressed - keyboard event received and working

Questions:

  • Has anyone encountered similar CEF keyboard focus issues on Ubuntu?
  • Are there Ubuntu-specific window manager settings that could help?
  • Could this be related to X11 vs Wayland display server differences?

What I’m Looking For:

  • Ubuntu/Linux-specific workarounds for CEF focus management.
  • Any insights into the root cause of this focus loss behavior.
  • Alternative approaches to maintain keyboard event capture in CEF on Linux using JS.

Any help or suggestions would be greatly appreciated!

How can I place the carousel arrows and navigation dots inside each slide on the right?

I’m building a carousel using USWDS and custom JavaScript. I want each slide to have arrows and navigation dots on the right sides. The dots and arrows show on the first slide only, but the dots do not show on rest of the slides. How can I make this work such that dots and arrows show on all the slides?

Here is my code

document.addEventListener("DOMContentLoaded", function() {
  const root = document.getElementById('ABCCarousel');
  if (!root) return;

  const LOOP = false;

  const track = root.querySelector('.ABC-carousel__viewport');
  const slides = Array.from(root.querySelectorAll('.ABC-slide'));

  // Get *all* controls
  const prevButtons = root.querySelectorAll('.carousel-button.prev');
  const nextButtons = root.querySelectorAll('.carousel-button.next');
  const nav = root.querySelector('.carousel-nav');

  // Ensure no slide has "hidden" attribute
  slides.forEach(s => s.removeAttribute('hidden'));

  // Build dots
  nav.innerHTML = '';
  const indicators = slides.map((_, i) => {
    const dot = document.createElement('span');
    dot.className = 'carousel-indicator';
    dot.addEventListener('click', () => goTo(i));
    nav.appendChild(dot);
    return dot;
  });

  let index = 0;

  function clamp(i) {
    const n = slides.length;
    return (i % n + n) % n;
  }

  function goTo(i) {
    index = LOOP ? clamp(i) : Math.max(0, Math.min(slides.length - 1, i));
    const offsetPct = -index * 100;
    track.style.transform = `translateX(${offsetPct}%)`;

    // Update dots
    indicators.forEach((dot, j) => dot.classList.toggle('active', j === index));

    // Enable/disable arrows
    if (!LOOP) {
      prevButtons.forEach(btn => btn.disabled = index === 0);
      nextButtons.forEach(btn => btn.disabled = index === slides.length - 1);
    } else {
      prevButtons.forEach(btn => btn.disabled = false);
      nextButtons.forEach(btn => btn.disabled = false);
    }

    // a11y
    slides.forEach((s, j) => s.setAttribute('aria-hidden', j === index ? 'false' : 'true'));
  }

  // Attach listeners to *all* controls
  prevButtons.forEach(btn => btn.addEventListener('click', () => goTo(index - 1)));
  nextButtons.forEach(btn => btn.addEventListener('click', () => goTo(index + 1)));

  // Keyboard nav
  root.addEventListener('keydown', (e) => {
    if (e.key === 'ArrowLeft') {
      e.preventDefault();
      goTo(index - 1);
    }
    if (e.key === 'ArrowRight') {
      e.preventDefault();
      goTo(index + 1);
    }
  });

  // Resize handling
  window.addEventListener('resize', () => {
    track.style.transform = `translateX(${-index * 100}%)`;
  });

  // Init
  goTo(0);
});
.carousel-controls {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 10px 0;
  background: #fff;
  width: 50%;
  max-width: 500px;
  margin: 0 auto;
}

.carousel-button {
  font-size: 54px;
  color: #1a4480;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 10px;
}

.carousel-button:disabled {
  color: #919191;
  pointer-events: none;
}

.carousel-nav {
  text-align: center;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  width: 150px;
  min-width: 150px;
}

.carousel-indicator {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin: 0 5px;
  cursor: pointer;
  border: 2px solid #1a4480;
}

.carousel-indicator.active {
  background: #1a4480 !important;
}

.ellipsis {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  cursor: pointer;
  color: #1a4480;
  user-select: none;
  width: 24px;
  height: 24px;
  margin: 0 5px;
}

#ABCCarousel .ABC-carousel__viewport {
  display: flex;
  transition: transform 0.5s ease-in-out;
  will-change: transform;
}

#ABCCarousel .ABC-slide {
  flex: 0 0 100%;
}

#ABCCarousel {
  overflow: hidden;
  /* hide the overflow */
  width: 100%;
  /* full width */
}

#ABCCarousel .ABC-carousel__viewport {
  display: flex;
  /* line up slides horizontally */
  transition: transform 0.5s ease-in-out;
  /* smooth animation */
  will-change: transform;
}

#ABCCarousel .ABC-slide {
  flex: 0 0 100%;
  /* each slide takes full width of viewport */
}
<link rel="stylesheet" href="https://unpkg.com/uswds@latest/dist/css/uswds.min.css">
<section class="bg-base-lightest">
  <div class="grid-container">
    <div class="grid-row">
      <div class="grid-col-12 tablet:grid-col-8 tablet:grid-offset-2">
        <h2 class="text-center">FuyuuyuyC</h2>
        <div class="bg-white shadow-3 radius-md padding-3 margin-bottom-2" style=" border: 1px solid #919191;"><!-- Header -->
          <h3 class="text-center margin-bottom-0">Latest Posts</h3>
          <hr class="border-gray-30 margin-bottom-2" />
          <div id="ABCCarousel" class="ABC-carousel" aria-roledescription="carousel" aria-label="Latest posts">
            <div class="ABC-carousel__viewport" role="group" aria-live="polite" style=" transform: translateX(0%);"><!-- Slide 1 -->
              <section class="ABC-slide" role="group" aria-roledescription="slide" aria-label="1 of 5" aria-hidden="false">
                <div class="grid-row grid-gap-4 margin-bottom-3"><!-- Left card -->
                  <div class="tablet:grid-col-6"><img alt="" src="https://cdn.britannica.com/62/156362-050-4E8FE282/Acacia-tree-savanna-Zimbabwe.jpg?" /></div> <!-- Right post -->
                  <div class="tablet:grid-col-6">
                    <p>ABCD</a></p>
                    <div class="carousel-controls"><button class="carousel-button prev" disabled="">❮</button>
                      <div class="carousel-nav"></div> <button class="carousel-button next">❯</button>
                    </div>
                  </div>
                </div>
              </section> <!-- Slide 2 -->
              <section class="ABC-slide" role="group" aria-roledescription="slide" aria-label="2 of 5" aria-hidden="true">
                <div class="grid-row grid-gap-4 margin-bottom-3">
                  <div class="tablet:grid-col-6"><img alt="" src="https://cdn.britannica.com/62/156362-050-4E8FE282/Acacia-tree-savanna-Zimbabwe.jpg?" /></div>
                  <div class="tablet:grid-col-6">
                    <p>ytyty <a href="#">dffdfd.</a></p>
                    <div class="carousel-controls"><button class="carousel-button prev" disabled="">❮</button>
                      <div class="carousel-nav"></div> <button class="carousel-button next">❯</button>
                    </div>
                  </div>
                </div>
              </section>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

React Router Nested Routes

I’m having issues configuring react-router-dom with nested routes loaded by sub-modules.
In my application I need to dynamically load modules that have their own nested routes. One of the requirement is to have the modules completely independent from the parent application. The loaded modules use relative routes to define their own navigation. The problem is that the relative navigation continue to append URL segments. I’m obviously missing something but I cannot figure it out.

I made a Codesandbox that shows the issue.


export default function App() {
  return (
    <BrowserRouter>
      <div className='App'>
        <h1>React Router Nested Routes</h1>
      </div>

      <Routes>
        <Route element={<OuterLayout />}>
          <Route
            element={<Home />}
            index
            path='home'
          />
          <Route
            element={<Nested />}
            path='nested/*'
          />
          <Route
            element={<Unknown />}
            path='*'
          />
        </Route>
      </Routes>
    </BrowserRouter>
  )
}

function OuterLayout() {
  return (
    <div>
      <ul>
        <li>
          <Link to='/home'>Home</Link>
        </li>
        <li>
          <Link to='/nested'>Nested</Link>
        </li>
      </ul>

      <Outlet />
    </div>
  )
}

function Home() {
  return <section>Home</section>
}

function Unknown() {
  return <section>Unknown</section>
}

function Nested() {
  return (
    <Routes>
      <Route element={<NestedLayout />}>
        <Route
          element={<Sub />}
          index
        />
        <Route
          element={<Sub />}
          path='sub'
        />
        <Route
          element={<Other />}
          path='other'
        />
      </Route>
    </Routes>
  )
}

function NestedLayout() {
  return (
    <div>
      <ul>
        <li>
          <Link to='sub'>Sub</Link>
        </li>
        <li>
          <Link to='other'>Other</Link>
        </li>
      </ul>

      <Outlet />
    </div>
  )
}

function Sub() {
  return <section>Sub</section>
}

function Other() {
  return <section>Other</section>
}

Is there way to use Symbol in React JS like base for key in map function

By the React docs is specified that key value in React lists should be unique. So, in that way, best choice is use ids from our database on client side like a key when we use map for our lists.

But if have some data that would be generated on our client side we can use UUID (thit is from React doc), but can we use Symbol instead?

Maybe are there any other good reasons to use Symbol in React (just like second additional question; u can answer it in short)?

Borrow/return system logic in JS [closed]

Users will also be able to borrow books from the library. Each borrowed book will have a loan date and a return date. When there is only one day left before the return date, the system must send the user an email reminder and also show them a notification on the website. If the book is not returned on time, the Admin will receive a notification message about the overdue book, and the Admin can place restrictions on that user

How to write this logic in JavaScript

Regex replace with /g/ is replacing the value twice

I have a simple regex replace – user provides find string and replace string. I’m using originalString.replace(new RegExp(find, 'gi'), replace) and it’s been working mostly fine. Recently I noticed that one of the edge cases where the replace string is applied twice when the find string is a match all.

For example:

const first =   'bat, batman, manbat'.replace(new RegExp('bat', 'gi'), 'cat');
console.log('first: ', first);
// => 'cat, catman, mancat'  // Every bat is replaced with cat, thanks to the global switch


const second = "bat, batman, manbat".replace(new RegExp('(.*)', 'gi'), '$1, cat');
console.log('second: ', second);
// => 'bat, batman, manbat, cat, cat'  // here, the 'cat' is replaced twice because of 'g'

Why is the ‘cat’ being applied twice for the second result? I would have expected it to just be bat, batman, manbat, cat – I just want to add , cat to multiple instances of strings, but they all have , cat twice at the end now.

The problem goes away in the second case if I take away the global switch, but then the first case would fail. How to fix this?

Why my browsers do not read php files any more [duplicate]

I run php files and echo, nothing comes out but I saw the whole php get commented out in the console,

I try to run php program, but I get nothing in return on browser rather I got this error message in the console

(This page is in Quirks Mode. Page layout may be impacted. For
Standards Mode use “<!DOCTYPE html>”.)

I will like to know if there are possible ways to get out of it

522 connection time out on cloudflair for php laravel and node

I’m running a PHP 8.1 Laravel application on an Apache server. The same server also runs a Node.js API (separate subdomain). The site is behind Cloudflare.

The issue:

The site randomly goes down for 10–20 minutes, then comes back without me doing anything.

During downtime, the Laravel site is inaccessible and Node.js APIs return Cloudflare 522 (connection timeout).

Sometimes the APIs still work when tested directly with Postman, but the Laravel frontend is down.

I’ve confirmed this with Uptime Robot monitoring, which shows repeated outages.

Laravel logs during downtime:

[2025-09-01 04:27:35] production.ERROR: Product Detail Error: cURL
error 56: Recv failure: Connection reset by peer for
http://ip-api.com/json/52.167.144.238

[2025-09-01 04:28:39] production.ERROR: API Request Error: Server
error: POST https://node.byyu.com/api/oneapiseconds resulted in a 522
response: error code: 522

Apache (cPanel) error logs show: [Mon Sep 01 02:19:50.127766 2025]
[authz_core:error] [client 52.71.218.25:19567] AH01630: client denied
by server configuration: /home/byyu/public_html/app/Http/error_log

[Sun Aug 31 22:23:46.573272 2025] [autoindex:error] [client
87.58.67.112:63776] AH01276: Cannot serve directory /home/byyu/public_html/admin/images/: No matching DirectoryIndex
found, and server-generated directory index forbidden

What I’ve observed:

Short outages (~5 min) sometimes produce no Laravel logs.

Longer outages (~10–20 min) always produce the above errors.

The website recovers automatically after some minutes, without restarting services.

My questions:

What could cause Laravel + Apache + Node.js to become unreachable for 10–20 minutes and then recover automatically?

Are the cURL error 56 and Cloudflare 522 hints of a resource bottleneck (CPU/memory), or a configuration issue with Apache/PHP-FPM?

What’s the best way to diagnose this kind of intermittent downtime on a shared server (cPanel)?

Any advice on debugging steps, or configuration changes I should check (Apache KeepAlive, PHP-FPM workers, Node process manager, etc.), would be appreciated.

Environment:

PHP 8.1, Laravel, Apache (cPanel hosting) Node.js backend on same server (node.byyu.com) Cloudflare in front of both domains

I tried changing the apis mentioned above which are node apis and optimized the api queries. Also i break out the api on dashboard again a node api the dashboard api was previously gaetting all data in sigle api i break down that api in one and two part first bings only banners, categories data and other brings the products.

After upgrading from PHP 8.3 to 8.4 I get “Maximum call stack size … reached. Infinite recursion?” [closed]

After upgrading my project from PHP 8.3 to PHP 8.4, I started getting the following error:

Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size – zend.reserved_stack_size) reached. Infinite recursion?

This happens when trying to sync data with Google Cloud Logging through gRPC.
Here is a snippet of the stack trace:

/workspace/vendor/google/gax/src/CredentialsWrapper.php:244
/workspace/vendor/grpc/grpc/src/lib/UnaryCall.php:45
/workspace/vendor/grpc/grpc/src/lib/BaseStub.php:295
/workspace/vendor/google/gax/src/Transport/GrpcTransport.php:267
...
/workspace/vendor/monolog/monolog/src/Monolog/Logger.php:391
/workspace/vendor/laravel/framework/src/Illuminate/Log/Logger.php:183

Environment:

Laravel project
Google Cloud Logging SDK (google/gax, google/cloud-logging),

gRPC extension enabled,

Works fine with PHP 8.3, only fails on PHP 8.4,

Question:

Has anyone encountered this issue after upgrading to PHP 8.4?

Is this a known incompatibility between PHP 8.4 and gRPC/Google Cloud libraries?

Any workaround or configuration change (e.g., zend.max_allowed_stack_size) that helps, or should I downgrade back to PHP 8.3 until support is fixed?

Different Web Authentication Flow [closed]

I read something a few months ago about an Authentication flow, where the server would validate the credentials and store something (token ? id ?) directly in the request’s headers.

The client would then just do normal requests without specifying any header and the token/id/hash would already be in the header for the server to validate (or it might already be validated).

Of course, I forgot about it for a while and now that I want to learn more I can’t find anything about it.

I’ve been crawling the OAuth website and other available documentations but can’t seem to find this one…

I don’t think it’s the Session Token Flow or other Authorization Code Flow but again, I’m not sure of what I read.

Does it ring a bell to you or did I invent this memory of mine ?

Thank you !

Base glyph is incorrect when parsing ligature components with PHP php-font-lib fork [closed]

I’m trying to parse ligature components to Unicode mapping in PHP using my own fork of php-font-lib which implements gsub table parsing. The official library doesn’t support this yet.

I’m using it with the Material Icons Font.
According to Fontdrop, the font contains all necessary ligature and GSUB data:
Fontdrop ligature parse image

The output I am trying to achieve should follow this pattern:

[
"fire_extinguisher": "uniF1D8",
]

However with my current script (You can find the code below), I get an output like this:

2ire_extinguisher -> 

The base glyph is wrong or sometimes missing entirely:

oom_in -> 
2ont_download_off -> 

Steps to reproduce:

1.) Clone my fork:

git clone https://github.com/NLion74/php-font-lib
cd php-font-lib
touch reproduction_example.php

1.) Add this code to reproduction_example.php

<?php
require __DIR__ . '/vendor/autoload.php';
use FontLibFont;

$fontPath = "../MaterialIcons-Regular.ttf";
if (!file_exists($fontPath)) die("Font not found");

$font = Font::load($fontPath);
$font->parse();

$cmap = $font->getData("cmap")['subtables'][0]['glyphIndexArray'] ?? [];
$glyphIDtoChar = [];
foreach ($cmap as $unicode => $gid) {
    if ($gid !== 0) $glyphIDtoChar[$gid] = mb_chr($unicode, 'UTF-8');
}

$gsub = $font->getData("GSUB");
$ligatureMap = [];

foreach ($gsub['lookupList']['lookups'] as $lookup) {
    if ($lookup['lookupType'] !== 4) continue;
    foreach ($lookup['subtables'] as $subtable) {
        if (!isset($subtable['ligSets'])) continue;

        $leadingChars = [];
        if (!empty($subtable['coverage']['rangeRecords'])) {
            foreach ($subtable['coverage']['rangeRecords'] as $range) {
                for ($gid = $range['start']; $gid <= $range['end']; $gid++) {
                    $leadingChars[] = $glyphIDtoChar[$gid];
                }
            }
        }
        if (!empty($subtable['coverageGlyphs'])) {
            foreach ($subtable['coverageGlyphs'] as $gid) {
                $leadingChars[] = $glyphIDtoChar[$gid];
            }
        }

        foreach ($subtable['ligSets'] as $index => $ligSet) {
            $baseGlyph = $leadingChars[$index];
            foreach ($ligSet['ligatures'] as $lig) {
                $components = array_map(fn($gid) => $glyphIDtoChar[$gid], $lig['components']);
                array_unshift($components, $baseGlyph);
                $seqStr = implode('', $components);
                $ligatureGlyph = $glyphIDtoChar[$lig['ligatureGlyph']];
                $ligatureMap[$seqStr] = $ligatureGlyph;
            }
        }
    }
}

foreach ($ligatureMap as $seq => $lig) {
    echo "$seq -> $lign";
}

3.) Run:

composer install
php reproduction_example.php

Expected behavior:

  • The base glyph plus components map correctly to the ligature glyph.

Actual behavior:

  • The base glyph seems to be entirely wrong

Question:

  • How can I correctly extract the base glyph for each ligature set when parsing the GSUB table in PHP?

Line with curves on each side creates background problems?

I am trying to create a line that “flows” from the left side of the screen to the right side with curves at the sides, will post a pictures for clarification. I however don’t know a native way to create an upwards/inwards curving line on the bottom of a div. This creates the problem that I still need everything above the line to be black so the black div to the left named (.start) is needed to make the background black and then a div below it to cover the black and make the line curve with a simple border radius.

This interferes with any background below the line that is not a plain color, like an image or such, since the cover block is not transparent.

What I am trying to create, with the ability to place images and such below it

Current problem, see how the cover piece sticks down a bit into the grey. Ignore how the text is cut off that is simply solved with a transparent background on the container, but its covering the black as of now.

Different colors on all the divs to see how this is built.

Different colors and with the cover piece transparent.

Snippet too see it in action:

      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      html,
      body {
        overflow-x: hidden;
      }

      .container {
        width: 100%;
        height: 200px;
        display: flex;
        background-color: white;
        position: relative;
      }

      .start {
        width: calc(100px - 2rem);
        height: calc(200px - 2rem);
        background-color: black;
      }
      .start-cover {
        width: 120px;
        height: 110px;
        background-color: white;
        position: absolute;
        left: -2.9rem;
        bottom: -1px;
        border-left: 1.2rem solid #ffff00;
        border-top: 1.2rem solid #ffff00;
        border-radius: 100% 0 0;
      }
      .mid {
        width: calc(100% - 200px + 4rem);
        height: 110px;
        background-color: black;
        border-bottom: 1.2rem solid #ffff00;
      }
      .end {
        width: 120px;
        height: 110px;
        position: absolute;
        top: 0;
        right: -2.8rem;
        background-color: black;
        border-bottom: 1.2rem solid #ffff00;
        border-right: 1.2rem solid #ffff00;
        border-radius: 0 0 100%;
      }
    <div class="container">
      <div class="start"></div>
      <div class="mid"></div>
      <div class="end"></div>
      <div class="start-cover"></div>
    </div>

I have tried switching the divs with both a PNG and SVG but none worked as good as I want them to with responsibility. And therefore I’ve stuck with this solution.
If you have a alternative solution feel free to help me but also if it is just a simple fix I haven’t thought of.

How to fix Strapi 5 “middlewares” environment variables not being read when deploying to fly.io through GitHub Actions?

I have a basic Strapi 5 project. Inside I configured config/middlewares.ts like this:

export default ({ env }) => [
  {
    name: "strapi::cors",
    config: {
      origin: env("CORS_ORIGIN").split(","),
      methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"],
      headers: ["Content-Type", "Authorization", "Origin", "Accept"],
      keepHeaderOnError: true,
    },
  },
...

On fly.io I configured this environment variable along with
a bunch of others. I also have this GitHub Action:

name: Fly Deploy
on:
  push:
    branches:
      - main
jobs:
  deploy:
    name: Deploy app
    runs-on: ubuntu-latest
    concurrency: deploy-group    # optional: ensure only one action runs at a time
    steps:
      - uses: actions/checkout@v4
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy --remote-only
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

Which runs this Dockerfile on the fly.io builder:

FROM node:22-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app

FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile

FROM base AS build
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run build

FROM base
COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist
EXPOSE 1337
CMD [ "pnpm", "start" ]

For some reason, every environment variable I am loading in a similair way in other config files are read properly, and even the one in my middleware is loaded locally. My GitHub Action reports an issue from the remote fly.io builder however:

Error: Could not load js config file /app/dist/config/middlewares.js:      ││   Cannot read properties of undefined (reading 'split')

Menu with submenus – The hardware back button takes to first submenu page clicked on instead of menu page

Just started learning React Native (using expo)
I have a profile.jsx in my app folder. It has multiple sub-menu. Each sub-menu also has a custom “<- Go Back” button which takes to profile.jsx.

File structure:

folder app has:

  1. index.jsx

  2. profile.jsx

  3. home.jsx

  4. (auth) folder

  5. (profileMenu) folder

  6. (category) folder

  7. product folder

(auth) has _layout, signIn, login, guest and register jsx files

(profileMenu) has _layout, Favourites, Wallet, Payment, Settings, etc. also all jsx files.

In profile.jsx I have clickable menu items of (profileMenu) which on click go to that particular jsx file.

The <- go back button inside the files themselves work as intended but when using android Hardware back button the page goes back to through all the profileMenu items I have clicked through instead of going back to the default page which is profile.jsx.

Then further once I am on profile.jsx and I click on another profileMenu option (other than the first clicked option) and use the HW back button it takes me to that first clicked file instead of profile.jsx.

I have tried both router.push() and router.replace(). Both show the same bug.

BUT I have a menu item this does not happen with- Logout. I click on it any number of items it does not show this bug. If I click on first, go back and click on another menu item, I am successfully able to go back to profile and the logout page does not appear.

My logout button takes me to another folder (auth) which contains a few other files like signIn.jsx guest.jsx. In all of these files the HW back button takes to the previous page like it should

I will attach the necessary snippets from all the relevant files and also attach an image of my file structure. Please do help me.

/app/ _layout.jsx:

import { Ionicons } from "@expo/vector-icons";

export default function Layout() {
  return (
    <Tabs
      screenOptions={{
        headerShown: false,
      }}
    >
      <Tabs.Screen
        name="profile"
        options={{
          title: "Profile",
        }}
      />

      <Tabs.Screen
        name="(auth)"
        options={{
          href: null,
        }}
      />
      <Tabs.Screen
        name="(profileMenu)"
        options={{
          href: null,
        }}
      />
    </Tabs>
  );
}

profile.jsx ->

//other imports etc.

const profile = () => {

  const router = useRouter();

  const handleMenuPress = (label) => {
  const menuItems = [
  
    { icon: 'percent', label: 'Promotions',  },
    { icon: 'settings',label: 'Settings', },
    { icon: 'log-out', label: 'Logout', },
  ];
    console.log(`Pressed: ${label}`);

    switch (label) {
      case 'Promotions':
        router.push('/(profileMenu)/Promotions');
        break;
      case 'Settings':
        router.push('/(profileMenu)/Settings');
        break;
      case 'Logout':
        router.replace('/(auth)/signIn');
        break;
      default:
        console.log('Unknown menu item');
    }
  }
  return (

    //other profile options line name etc...


      {/* Menu Items */}
      <ScrollView>
        <View>
          {menuItems.map((item, index) => {
            const IconComponent = item.iconSet;
            return (
              <TouchableOpacity
                key={index}
                onPress={() => handleMenuPress(item.label)}
              >
                <Text>{item.label}</Text>
              </TouchableOpacity>
            );
          })}
        </View>
      </ScrollView>
);
};


;
export default profile

Promotions.jsx:

//imports 
import { useRouter } from 'expo-router';

const Promotions = () => {
  const router = useRouter();

  const navigateToProfile = () => {
    router.replace('/profile');
  };
  return (
    <View>
      <View>
        <TouchableOpacity
          onPress={navigateToProfile}
        >
          <Text style={styles.backButtonText}>← Back</Text>
        </TouchableOpacity>
        <Text style={styles.title}>Payments</Text>
      </View>
      <Text>Promotions</Text>
    </View>
  )
}

export default Promotions

Settings.jsx:

//imports plus :
import { useRouter } from 'expo-router';


const Settings = () => {
  const router = useRouter();

  const navigateToProfile = () => {
    router.replace('/profile');
  };
  return (
    <View>
      <View>
        <TouchableOpacity
          onPress={navigateToProfile}
        >
          <Text>← Back</Text>
        </TouchableOpacity>
        <Text>Settings </Text>
      </View>
      <Text>
        Settings
      </Text>
    </View>
  )
}

export default Settings

in (profileMenu) folder: _layout.jsx:

import { Stack } from 'expo-router';

export default function ProfileLayout() {
  return (
    <Stack
      screenOptions={{
        headerShown: false,
      }}
    >
      <Stack.Screen name="Promotions" />
      <Stack.Screen name="Settings" />
      <Stack.Screen name="Wallet" />
    </Stack>
  );
}

(auth) _layout.jsx

export default function AuthLayout() {
  return (
    <Stack
      screenOptions={{
        headerShown: false,
      }}
    >
      <Stack.Screen name="signIn" />
      <Stack.Screen name="login" />
      <Stack.Screen name="register" />
      <Stack.Screen name="guest" />
    </Stack>
  );
}

signIn.jsx:

//imports
import { router } from 'expo-router';


const { width, height } = Dimensions.get('window');

const SignIn = () => {

    const menuItems = [
        { id: 1, label: 'login', text: 'Login to Your Account' },
        { id: 2, label: 'register', text: 'Create an Accound' },
        { id: 3, label: 'guest' },
    ]
    const handleMenuPress = (label) => {
        if (label === 'login') {
            router.push('/(auth)/login');
        } else if (label === 'register') {
            router.push('/(auth)/register');
        } else if (label === 'guest') {
            router.push('/(auth)/guest');
        }
    };

    return (
        <SafeAreaView>

            <ScrollView >
                <View >
                    <Text >Sign in to continue shopping</Text>
                </View>

                <View >
                    <View>

                        <TouchableOpacity
                            onPress={() => handleMenuPress(menuItems[0].label)} 
                        >
                            <Text>{menuItems[0].text}</Text>
                        </TouchableOpacity>

                        <TouchableOpacity
                            onPress={() => handleMenuPress(menuItems[1].label)}
                        >
                            <Text>{menuItems[1].text}</Text>
                        </TouchableOpacity>
                    </View>


                    <TouchableOpacity
                       
                        onPress={() => handleMenuPress('guest')}
                    >
                        <Text >Continue as Guest</Text>
                    </TouchableOpacity>
                </View>

            </ScrollView>
        </SafeAreaView>
    )
}

export default SignIn;

File Structure:

I have tried replacing the whole file twice, I have tried using router.push() as well as router.replace(). Both of them did not work. But for some reason logout menu item works.

I have replaced the _layout.jsx in both (auth) and (profileMenu) twice.
I am unsure at this point why my HardWare back Button is not functioning correctly.