Why is Safari iOS rendering this Astro page scrolled down on navigation?

The demo can be found here:
https://astro-nano-demo.vercel.app/blog

Source code is here:
https://github.com/markhorn-dev/astro-nano

I’ve been trying to adopt this theme for my usage, but without a fixed header. However, I noticed that Safari on iOS sometimes renders pages on this site so that they are scrolled down a tad bit. This usually happens if the page is navigated to after having scrolled down. For example, go to blog on the demo site, click on the link “Markdown Syntax Guide”, and then notice that you can scroll a bit to the top. Notice there’s extra space between the fixed header and the “Back to Blog” button that is seemingly “hidden” because Safari has scrolled down a bit. If you scroll up, the space is bigger than what it is on first load.

Try as I may, I can’t really figure out what is going on here. Is it CSS? Astro navigation? Or Safari’s scroll restoration? I’ve tried several things in order to resolve this without success. I suspect it’s may be something in the Head component: https://github.com/markhorn-dev/astro-nano/blob/main/src/components/Head.astro but I couldn’t put my finger on what exactly.

3D Rotating Cube with Transparent Window to Background Video (Only Visible Through Cube)

I’m trying to build a 3D rotating cube with a smooth animation, where a single video plays in the background — but the video should only be visible through the cube’s faces, like looking through a window. The goal is to create the illusion that the video exists only behind the cube and is not visible anywhere else on the screen.

I’ve tried several approaches using CSS clip-path, mask, and even WebGL, but I keep facing issues like:

The video appears outside the cube area.

The video is duplicated on all cube faces instead of staying in the background.

I can’t make the cube act like a window while hiding everything else.

What I want:

A 3D cube with a smooth continuous rotation.

One video positioned behind the cube.

The video should only be seen through the cube (not outside it).

The cube should not have the video mapped on all six faces — just act as a viewing window.

Any suggestions, code samples, or best practices would be appreciated! I’m open to using CSS, Three.js, or a combination. Thanks in advance! here is my jsx –

import '../../styles/Cube3D.css';

const Cube3D = () => {
  return (
    <div className="scene">
      <div className="cube">
        <div className="face-wrapper front">
          <div className="face-blur">
          </div>
          <div className="face-content">Front Face</div>
        </div>
        <div className="face-wrapper back">
          <div className="face-blur"></div>
        </div>
        <div className="face-wrapper right">
          <div className="face-blur"></div>
        </div>
        <div className="face-wrapper left">
          <div className="face-blur"></div>
        </div>
        <div className="face-wrapper top">
          <div className="face-blur"></div>
        </div>
        <div className="face-wrapper bottom">
          <div className="face-blur"></div>
        </div>
      </div>
    </div>
  );
};

export default Cube3D;

and here is my css –

.scene {
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 1500px;
  background-color: rgb(0, 0, 0);
  /* background-image: url('../../assets/image1.png'); */
  /* overflow: hidden; */
}
.cube {
  position: relative;
  width: 250px;
  height: 250px;
  transform-style: preserve-3d;
  animation: spinCube 5s linear infinite;
  animation-delay: 3s;
  z-index: 1;
}

.front .face-content {
  animation: fadeOutText 5s linear infinite;
  animation-delay: 3s;
}

@keyframes spinCube {
  0% {
    transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) scale3d(1, 1, 1);
  }
  10% {
    transform: rotateX(-7deg) rotateY(-25deg) rotateZ(4deg)
      scale3d(1.1, 1.1, 1.1);
  }
  25% {
    transform: rotateX(-14deg) rotateY(-51deg) rotateZ(10deg)
      scale3d(1.3, 1.3, 1.3);
  }
  45% {
    transform: rotateX(-21deg) rotateY(-76deg) rotateZ(12deg)
      scale3d(1.5, 1.5, 1.5);
  }
  60% {
    transform: rotateX(-25deg) rotateY(-120deg) rotateZ(12deg)
      scale3d(1.6, 1.6, 1.6);
  }
  75% {
    transform: rotateX(-21deg) rotateY(-240deg) rotateZ(10deg)
      scale3d(1.75, 1.75, 1.75);
  }
  90% {
    transform: rotateX(-14deg) rotateY(-300deg) rotateZ(4deg)
      scale3d(2.5, 2.5, 2.5);
  }
  100% {
    transform: rotateX(-7deg) rotateY(-360deg) rotateZ(0deg) scale3d(3, 3, 3);
  }
}

@keyframes fadeOutText {
  0%,
  45% {
    opacity: 1;
  }
  46%,
  100% {
    opacity: 0;
  }
}

/* Cube Faces */
.face-wrapper {
  position: absolute;
  width: 250px;
  height: 250px;
  clip-path: polygon(
    5% 0%,
    95% 0%,
    100% 5%,
    100% 95%,
    95% 100%,
    5% 100%,
    0% 95%,
    0% 5%
  );
  /* overflow: hidden; */
}

.face-blur {
  position: absolute;
  inset: 0;
  background: linear-gradient(145deg, rgba(255, 0, 0, 0.5), rgba(0, 0, 0, 0.1));
  /* background: linear-gradient(
    145deg,
    rgba(255, 255, 255, 0.05),
    rgba(0, 0, 0, 0.1)
  ); */
  backdrop-filter: blur(6px) brightness(1.1);
  -webkit-backdrop-filter: blur(6px) brightness(1.1);
  z-index: 0;
}

.face-content {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 250px;
  text-align: center;
  font-size: 2.2rem;
  font-weight: bolder;
  color: black;
  font-family: Arial, Helvetica, sans-serif;
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 30px rgba(255, 255, 255, 0.05),
    0 0 20px rgba(0, 255, 255, 0.2), 0 0 40px rgba(0, 255, 255, 0.15);
}

/* Cube Faces Positions */
.front {
  transform: translateZ(125px);
}
.back {
  transform: rotateY(180deg) translateZ(125px);
}
.right {
  transform: rotateY(90deg) translateZ(125px);
}
.left {
  transform: rotateY(-90deg) translateZ(125px);
}
.top {
  transform: rotateX(90deg) translateZ(125px);
}
.bottom {
  transform: rotateX(-90deg) translateZ(125px);
}

Service worker and OIDC

I am using a service worker to cache the static resources for my website. The cache name is key’ed by the Last-Modified header so that I can do a rolling deployment. The user will only ever be shown a full set of static resource from one release. After the release is complete, the service worker cache is updated.

The fetch event looks like this:

event.respondWith(caches.match(event.request).then(r => r || fetch(event.request)))

I’ve hit an issue where I’m getting a 401 when visiting the site root /. It’s a cache miss (which is a problem in itself but I can look at that separately) and is calling fetch().

The site is protected by OIDC where authentication is done via SPNEGO (i.e. there is no login screen). The OIDC access token lifespan has a maximum of 12 hours (including any refreshes).

I assume the fetch is unable to follow the redirects to re-fetch an access token (for the OIDC protocol), but I can’t figure out what I need to do to solve it.

Sidebar: Had it been a cache hit, I would have had an invalid token anyways…I feel like OIDC with service worker should be a solved pattern but I couldn’t find anything via Google.

App claims out of memory despite enough allocated

I am running Windows 11 64bit with 32GB of RAM. No other processes are running. I init Node.js using this command

node index.js --max-old-space-size=16384

In task manager I see 50% memory usage. So why does the app crash at 4GB?

<--- Last few GCs --->
[11724:000001EAD7670000]  9250018 ms: Mark-Compact 4044.3 (4144.3) -> 4043.1 (4143.9) MB, pooled: 0 MB, 2449.39 / 0.00 ms  (average mu = 0.398, current mu = 0.204) allocation failure; scavenge might not succeed
[11724:000001EAD7670000]  9252815 ms: Mark-Compact 4044.5 (4144.3) -> 4043.7 (4144.6) MB, pooled: 0 MB, 2216.51 / 0.00 ms  (average mu = 0.314, current mu = 0.207) allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

forEach on array of DOM elements fails with “Cannot read properties of undefined” but for loop works — why?

I’m trying to attach event listeners to two DOM elements like this (both elements exist):

const signout = document.getElementById('logout');
const signoutMobile = document.getElementById('logout-mobile');

[signout, signoutMobile].forEach(el => {
  if (el) {
    el.addEventListener('click', async () => {
      await logout();
    });
  }
});

async function logout() {
    // fetch logic
}

However, this throws an error in the browser console:

Uncaught TypeError: Cannot read properties of undefined (reading 'logout-mobile')

But when I rewrite the same logic using a for loop, it works perfectly:

const elements = [signout, signoutMobile];
for (let i = 0; i < elements.length; i++) {
  const el = elements[i];
  if (el) {
    el.addEventListener('click', async () => {
      await logout();
    });
  }
}

Why does the .forEach() approach throw an error, while the for loop works fine?

Furthermore, when I place the logout function before the .foreach block, … it works!

Works:

    1. logout declaration, 2)forEach
    1. for, 2) logout declaration
    1. logout declaration, 2) for

Doesn’t work:

    1. forEach, 2) logout declaration

Additional info:

  • Both snippets are placed in the same script file.
  • The variables signout and signoutMobile are assigned using document.getElementById() before the iteration.
  • The script is loaded with defer.
  • The elements with IDs logout and logout-mobile exist in the DOM.
  • The logout function is declared and works properly.

I suspect it has something to do with when the variables are assigned relative to the iteration.

What am I missing here?

Note: chatGPT fails to fix this, or explain the problem.

How to secure client-side code from server side

I have a React web app where I display some D3 diagram. The user can download this diagram as a JPG file. I want to control from the server side (Node.js) who is able to download it and who isn’t.

There is a library that makes this download feature available. I have to pass the root svg element to this library and it completes the rest. As everything is on client side I am not sure how I could control from the server side who has access to this download feature.

I could call a server-side feature before executing the import-to-JPG feature but it is client-side code so this call (to check who has access) can be hacked or just ignored so I presume it is not a very good solution.

What I thought of is to download the import-to-JPG library/code from the server side only in those cases when the user has access, otherwise this library/code won’t exist (i.e. the download code won’t exist in the client code but only on the server). So when the user would click on the download button then the import-to-JPG code would be downloaded from server and executed. However I am not sure if it can be done and how.

Is there any other solution to control this client-side behaviour from the server?

Getting extra space between lines of text (not due to line height)

I have this code which was supposed to highlight some code wrapped in “` (like you wrap snippets on stack overflow):

function Pre({ children, ...props }) {
  ....
  const highlightedHTML = highlight(codeString);

  return <pre {...props} className="" dangerouslySetInnerHTML={{ __html: highlightedHTML }} />;
}

However, the HTML it generates has extra space between the lines.

See the generated element here: https://stackblitz.com/edit/web-platform-2msddmqs?file=index.html

Don’t pay attention to styles and classes in the sandbox they aren’t even defined in CSS.

Why am I getting these extra lines can someone explain?

And how can I amend above that code so that I don’t run into that problem?


highlight is a function from library sugar-high. And this Pre is part of using this where you just say that this component will be used when you want to generate code blocks.

Why am I getting “req.body is not set” when using @apollo/server with expressMiddleware in Apollo Server, even after adding express.json() before it?

Why am I getting “req.body is not set” when using @apollo/server with expressMiddleware in Apollo Server v4, even after adding express.json() or bodyParser.json() before it?

import express from "express";
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import cors from "cors";

async function startServer() {
  const app = express();
  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));
  app.use(cors());

  const server = new ApolloServer({
    typeDefs: `#graphql
        type Todo{
        id : ID!
        Title : String!
        Completed : Boolean
        }
        type Query{
            getTodos : [Todo]
        }
    `,
    resolvers: {},
  });

  await server.start();
  app.use("/graphql", expressMiddleware(server));

  app.listen(8000, () => {
    console.log("server is running on port 8000");
  });
}

startServer();

I followed the official Apollo Server v4 setup using @apollo/server and expressMiddleware. I added express.json() and even bodyParser.json() before the middleware. I expected the GraphQL server to parse JSON requests correctly. However, I keep getting this error:
“req.body is not set; this probably means you forgot to set up the ‘json’ middleware…”

Resolving errors with recharts graph in nextjs, incorrect type/null

I am new to nextJS and I’m experiencing multiple errors when trying to add a graph/chart using recharts

The main error is : Error: Objects are not valid as a React child (found: object with keys {$$typeof, type, key, props, _owner, _store}). If you meant to render a collection of children, use an array instead.

This error occurs when I use the code from this recharts example :

<LineChart width={400} height={400} data={data} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
  <XAxis dataKey="name" />
  <Tooltip />
  <CartesianGrid stroke="#f5f5f5" />
  <Line type="monotone" dataKey="uv" stroke="#ff7300" yAxisId={0} />
  <Line type="monotone" dataKey="pv" stroke="#387908" yAxisId={1} />
</LineChart>

I have also tried adding a barchart using this code :

<ResponsiveContainer width="100%" height={300}>
    <BarChart data={data} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip formatter={(value) => `$${value}`} />
        <Legend />
        <Bar dataKey="price" fill="#8884d8" />
    </BarChart>
</ResponsiveContainer>

The above code gives a different error : TypeError: resolveDispatcher() is null

I have tried adjusting the graph code and the data but the error remains regardless of the changes I make

This is the sample data I tried to use with the line chart code

const data = [
    { name: 'Original Price', price: 100 },
    { name: 'Reduced Price', price: 50 },
];

The LineChart code is within a div within a main within the main return

How to call hook after delete mutation?

In my react app, I would like to navigate to another page after I execute GQL delete mutation using Apollo. This mutation is called from inside a modal popup:

const [deleteDeck, { loading }] = useMutation(DELETE_DECK, {
    onCompleted() { (Navigate("/decks")) },
    onError: (error) => { setError(error.graphQLErrors[0].message)}
  });

The mutation finished successfully but I get the following error:

Invalid hook call. Hooks can only be called inside of the body of a function component.

What am I doing wrong?

OnClick works only once

HTML:

<svg id="settings-icon" xmlns="http://www.w3.org/2000/svg" height="90px" viewBox="0 -960 960 960" width="40px" fill="#FFF"><path d="(thepath)" onclick='settings()'></svg>

JS:

function settings() {alert("hello")}

The alert only happens the first time when clicked. Afterwards I would need to reload then the alert will show again. Or not the alert wouldn’t show after the first time.

Help greatly appreciated.

EDIT: it works but only sometimes. when i click theres bout a 50% chance it alerts

How to put –select zone– as default value on the dropdown input

working with Laravel 10 backend and I have following dropdown for select zone name and existing system show some zone name from table. but I need show –select zone– as the default value of the dropdown when the page load.
zone.blade.php

 <form action="{{request()->fullUrl()}}" id="zoneSubmitForm" class="pb-1">
                            <div class="">
                                <select class="js-select-custom min-w-200 h-35" name="zone_id" id="selectZone">
                                    @if(count($zones)>0)
                                        @foreach($zones as $key =>$zone)
                                            <option value="{{$zone->id}}"
                                                    {{request('zone_id') == $zone->id ? "selected" :""}} data-show-shield="{{ in_array($zone->id, $safetyAlertZones) ? 'true' : '' }}">{{$zone->name}}</option>
                                        @endforeach
                                    @else
                                        <option selected disabled>{{translate("zone_not_found")}}</option>
                                    @endif
                                </select>
                            </div>
                        </form>

<script>
   $('#selectZone').on('change', function () {
                $('#zoneSubmitForm').submit();
            });
</script>

ZonemanageController

public function fleetMap(?Request $request, $type = null)
    {
        $zones = $this->zoneService->getBy(relations: ['tripRequest.safetyAlerts']);
        $safetyAlertZones = $zones->filter(function ($zone) {
            return $zone->tripRequest->contains(function ($tripRequest) {
                return $tripRequest->safetyAlerts->where('status', PENDING)->isNotEmpty();
            });
        })->pluck('id')->toArray();
        $safetyAlertCount = $this->safetyAlertService->getBy(criteria: ['status' => PENDING])->count();

        if (array_key_exists('zone_id', $request->all()) && $request['zone_id']) {
            $zone = $this->zoneService->findOne(id: $request['zone_id']);
        } else {
            $zone = count($zones) ? $this->zoneService->findOne(id: $zones[0]->id) : null;
        }
        $safetyAlertLatestUserRoute = $safetyAlertCount > 0 ? $this->safetyAlertService->safetyAlertLatestUserRoute() : 'javascript:void(0)';
        $safetyAlert = $this->safetyAlertService->findOneBy(criteria: ['status' => PENDING], relations: ['sentBy'], orderBy: ['created_at' => 'desc']);
        $safetyAlertUserId = $safetyAlert?->sentBy?->id ?? null;

        // Calculate center lat/lng
        $latSum = 0;
        $lngSum = 0;
        $totalPoints = 0;
        $polygons = $zone ? json_encode([formatCoordinates(json_decode($zone?->coordinates[0]->toJson(), true)['coordinates'])]) : json_encode([[]]);
        if ($zone) {
            foreach (formatCoordinates(json_decode($zone?->coordinates[0]->toJson(), true)['coordinates']) as $point) {
                $latSum += $point->lat;
                $lngSum += $point->lng;
                $totalPoints++;
            }
        }
        $centerLat = $latSum / ($totalPoints == 0 ? 1 : $totalPoints);
        $centerLng = $lngSum / ($totalPoints == 0 ? 1 : $totalPoints);
        if ($zone) {
            $data = $this->fleetCommon($type, $zone, $request->all());
            $drivers = $data['drivers'] ?? [];
            $customers = $data['customers'] ?? [];
            $markers = $data['markers'];

            return view('adminmodule::fleet-map', compact('drivers', 'customers', 'zones', 'safetyAlertZones', 'safetyAlertCount', 'safetyAlertLatestUserRoute', 'safetyAlertUserId', 'type', 'markers', 'polygons', 'centerLat', 'centerLng'));
        }
        $drivers = [];
        $customers = [];
        $markers = json_encode([[]]);

        return view('adminmodule::fleet-map', compact('drivers', 'customers', 'zones', 'safetyAlertZones', 'safetyAlertCount', 'safetyAlertLatestUserRoute', 'safetyAlertUserId', 'type', 'markers', 'polygons', 'centerLat', 'centerLng'));
    }

how could I select as default value –select zone– when blade file load the zone name?

Why I’m getting error every time i try to access the protected route instead of redirect to /login?

I’m implementing protection route in my vanlife practice project and its not redirecting me it keep giving me this error when i try to access protected route

enter image description here

I’m supposed to get redirected to /login when I try to access the /host.

This is my main.jsx

import { createRoot } from 'react-dom/client'
import Layout from './components/Layout.jsx';
import Home from './pages/Home.jsx';
import About from './pages/About.jsx';
import Login from './pages/Login.jsx';
import Error from './components/Error.jsx';
import Vans, { loader as vanLoader } from './pages/Vans/Vans.jsx';
import VansDetails, { loader as vanDetailLoader } from './pages/Vans/VansDetails.jsx';
import Dashboard from './pages/Host/Dashboard.jsx';
import Income from './pages/Host/Income.jsx';
import Reviews from './pages/Host/Reviews.jsx';
import HostVans, { loader as hostvanLoader } from './pages/Host/HostVans.jsx';
import HostVansDetail, { loader as hostvandetailLoader } from './pages/Host/HostVansDetail.jsx';
import Pricing from './pages/Host/HostVanDetails/Pricing.jsx';
import Photos from './pages/Host/HostVanDetails/Photos.jsx';
import Info from './pages/Host/HostVanDetails/Info.jsx';
import HostLayout from './components/HostLayout.jsx';
import {
    RouterProvider,
    Route,
    createBrowserRouter,
    createRoutesFromElements
} from 'react-router-dom';
import NotFound from './pages/NotFound.jsx';
import './server.js';
import { requireAuth } from './utils.js';
import { StrictMode } from 'react';

const router = createBrowserRouter(createRoutesFromElements(
    <Route element={<Layout />}>
        <Route index element={<Home />} />
        <Route path='about' element={<About />} />
        <Route path='vans' element={<Vans />} loader={vanLoader} errorElement={<Error />} />
        <Route path='vans/:id' element={<VansDetails />} loader={vanDetailLoader} />

        <Route path='host' element={<HostLayout />} >
            <Route
                index
                element={<Dashboard />}
                loader={async () => await requireAuth()}
            />
            <Route
                path='income'
                element={<Income />}
                loader={async () => await requireAuth()}
            />
            <Route
                path='reviews'
                element={<Reviews />}
                loader={async () => await requireAuth()}
            />
            <Route
                path='vans'
                element={<HostVans />}
                loader={async () => {
                    await requireAuth()
                    return hostvanLoader()
                }}
            />
            <Route
                path='vans/:id'
                element={<HostVansDetail />}
                loader={async (obj) => {
                    await requireAuth()
                    return hostvandetailLoader(obj)
                }}
            >
                <Route
                    index
                    element={<Info />}
                    loader={async () => await requireAuth()}
                />
                <Route
                    path='pricing'
                    element={<Pricing />}
                    loader={async () => await requireAuth()}
                />
                <Route
                    path='photos'
                    element={<Photos />}
                    loader={async () => await requireAuth()}
                />
            </Route>
        </Route>
        <Route path='login' element={<Login />} />
        <Route path='*' element={<NotFound />} />
    </Route>
));

function App() {
    return (
        <div className='bg-[#FFF7ED] h-screen font-[inter] relative flex flex-col overflow-x-hidden'>
            <RouterProvider router={router} HydrateFallback={<h1>Loading...</h1>} />
        </div>
    )
}

createRoot(document.getElementById('root')).render(
    <StrictMode>
        <App />
    </StrictMode>
)

This is my utils.js which is supposed to run by the loader and redirect me to /login

import { redirect } from "react-router-dom"

export async function requireAuth() {
    const isLoggedIn = false
    
    if (!isLoggedIn) {
        throw redirect("/login")
    }
}