Storing dark Theme functionality in local storage

So I am a new full stack developer, and making a job portal through some course. He saved the dark theme state value of website in local storage.

Is it a good practice? Like there might be other cookies in very large scale websites and pushing everything to local storage wont affect website loading and performance?

How to use slick carousel rows and slidesPerRow on responsive display?

I want my carousel items on the ff conditions:

  1. 3 rows and 3 slidesPerRow on large desktop above.
  2. 2 rows and 2 slidesPerRow on less than 992px.
  3. 1 rows and 1 slidesPerRow on less than 768px.

But it seems that the rows and slidesPerRow are not working on small desktop below?. It always shows the large desktop settings?

You can check/run the codes below:

$(function() {
  $('.slick-slider-multiple').slick({
      rows: 3,
      slidesPerRow: 3,
      responsive: [
      {
        breakpoint: 992,
        settings: {
          rows: 2,
          slidesPerRow: 2,
        }
      },
      {
        breakpoint: 768,
        settings: {
          rows: 1,
          slidesPerRow: 1,
        }
      }
    ]
  });
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick-theme.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js"></script>

<div class="slick-slider-multiple">
        <div class="slick-single-slide">
            <h1>Slick Slide 1</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 2</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 3</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 4</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 5</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 6</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 7</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 8</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 9</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 10</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 11</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 12</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 13</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 14</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 15</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 16</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 17</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 18</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 19</h1>
        </div>
        <div class="slick-single-slide">
            <h1>Slick Slide 20</h1>
        </div>
    </div>

Google Alerts – alert notifications sent to a different email address

How can I create a Google Alert using my current Google account, but have the alert notifications sent to a different email address (e.g., another Google account or a non-Google email address)?

  1. Can I set up a Google Alert and have it delivered to a different Google account or email address?

  2. Is there a way to change the destination email address for Google Alerts when using a specific Google account?

  3. How do I forward Google Alerts from my current Google account to a different email address or another Google account?

  4. Can Google Alerts notifications be sent to a different email account (Gmail or non-Gmail) than the one used to create the alert?

Image not drawning correctly in

I’m loading an image from a server. I’ve confirmed that the whole file is downloading. The first image is what is being displayed the second image is what the server has. Notice that the top 10%(ish) is missing, from the displayed image.

The HTML body, code and css

<body>
<!-- Image -->
<div id="worldMapContainer" class="world-map-container">
    
</div>

<!-- Zoom control buttons -->
<div class="zoom-controls">
    <button class="zoom-button" onclick="setZoom('fit')">
        <img src="assets/fullscreen-icon.png" alt="Fit to Screen" title="Fit to Screen" />
    </button>
    <div class="zoom-levels">
        <button onclick="setZoom(1)">1x</button>
        <button onclick="setZoom(5)">2x</button>
        <button id="zoom-3x" onclick="setZoom(10)">3x</button>
        <button onclick="setZoom(15)">4x</button>
    </div>
</div>
</body>

.world-map-container {
    position: relative;
    margin-left: 10px;
    margin-top: 20px;
    margin-right: 10px;
    width: 85vw;
    height: 85vh;
    overflow: auto;
    display: flex;
    justify-content: center;
    align-items: center;
}

/* Image styling */
.world-map-container img {
    display: block;
    max-width: none;
    max-height: none;
    image-rendering: pixelated; /* Preserve pixelated effect when scaled */
    image-rendering: crisp-edges; /* Fallback for some browsers */
}

async onWorldMap(msg) {
    const imageData = `data:image/png;base64,${this.arrayBufferToBase64(msg.params.image.data)}`
    console.log('download: ', imageData.length)

    localStorage.setItem("mapData", imageData)
    localStorage.setItem("mapWidth", msg.params.width.toString())
    localStorage.setItem("mapHeight", msg.params.height.toString())

    this.loadImageFromLocalStorage('mapData')
}

arrayBufferToBase64(buffer) {
    let binary = ''        
    const bytes = new Uint8Array(buffer)
    const len = bytes.length
    for (let i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i])
    }
    return btoa(binary)
}

loadImageFromLocalStorage(key) {
    this.map = localStorage.getItem(key)

    if (this.map) {
        console.log('load: ' + this.map.length)
        this.width = parseInt(localStorage.getItem('mapWidth'))
        this.height = parseInt(localStorage.getItem('mapHeight'))

        this.mapImage = document.createElement("img")
        this.mapContainer = document.getElementById("worldMapContainer")
         
        this.mapImage.id = 'worldMap'
        this.mapImage.alt = 'World Map'
        this.mapImage.src = this.map
        this.mapImage.width = this.width
        this.mapImage.height = this.height
        this.mapContainer.appendChild(this.mapImage)
    }
}

Any thoughts would be appreciated, I’m fairly new to web programming.
loaded image

server image

JQuery DatePicker , beforeShowDay

I’m a bit desesperate as I don’t understand why beforeShowDay doesn’t work the way I expect it to work. I’m trying to highlight some date that comes from a database (I get the data from Ajax)

I can’t seems to make it work, the date never highlight even if I try different date format

In the html part, I call the calendar like this :

<div class="calendar" id="Date" ></div>

For the Ajax part, I get my date array like this :

     var days_custom = [];
      URL = 'get_date.php';
      
$.ajax({
    type: "GET",           
    url: URL,
    dataType: 'json',
    success: function(data) {                 
        for (var t in data) {
            days_custom[days_custom.length] = data[t].date
        }
        console.log(days_custom);
       
    }
});

and in the console, I see my dates with that format:

['2024-05-05', '2024-05-07', '2024-05-08', '2024-05-09', '2024-05-11', '2024-05-12', '2024-05-13', '2024-05-14', '2024-05-15', '2024-05-17',  …]

My next step is to uses those date to try to change the backgound color and have an highlight for those specific date :

 $("#Date").datepicker({
            dateFormat: 'yy-mm-dd',
            beforeShowDay: function(date) {       
                          
                t_date = $.datepicker.formatDate('yyyy-mm-dd', date);
                    
                
                if (days_custom.indexOf(t_date) > -1) {
                    return [true, 'event', 'test highlight'];
                    
                }
                return [true];
            }
        });

In my css file, I have this :

.event a {
    background-color: #5FBA7D !important;
    color: #ffffff !important;
}```

And this does nothing.

I also tried to write in the console in the beforeShowDay function, but nothing appears, so I even wonder if I get in this in the code…

Also, I tried to destroy the datepicker just before the code, as I saw that on another question but it’s not my issue, so I removed it from the code because it didn’t change anything.

Thanks for the help guys

How can I handle and debug errors in complex asynchronous applications?

I’m working on an application with multiple asynchronous operations, and I’m finding it challenging to manage and debug errors effectively. When dealing with async code—especially when using a mix of promises and async/await—I’m looking for the best practices to catch and handle errors consistently.

Specifically, I’d like to know:

How do you handle errors in async operations to ensure they don’t go unhandled?
Are there preferred tools or techniques you rely on to debug complex async workflows?
What strategies do you use to pinpoint issues efficiently in nested or chained async functions?
Any advice on tools or general approaches that could help streamline async debugging would be appreciated.

What I’ve Tried:

Standard Try-Catch Blocks: I’ve wrapped async functions in try-catch blocks, but this becomes difficult to manage with deeply nested or chained async calls, where errors still occasionally go unhandled or get lost.

.catch() on Promises: Using .catch() for promises worked to an extent, but tracking the flow in complex chains makes it challenging to identify exactly where things go wrong, especially when multiple promises run concurrently.

Logging with Console Statements: I tried using console.log() at different points, but this quickly got messy in larger operations, making it hard to follow error origins and connections between async tasks.

Debugging Tools: I’ve used Chrome DevTools and Node’s debugging capabilities, but they become harder to use with asynchronous functions, as the call stack often doesn’t reveal the full path of async operations clearly.

Each of these methods has helped to some degree, but none have provided a clear, manageable way to handle and debug async errors in a large-scale setup. I’m hoping to find more effective strategies or tools that can simplify this process.

Is there any way to add input file with name invoice in my code

<div class="mb-6">
                        <div data-hs-file-upload='{
                            "url": "../../_invoice",
                            "maxFiles": 1,
                            "singleton": true
                        }'>
                            <template data-hs-file-upload-preview="">
                                <div class="p-3 bg-white border border-solid border-gray-300 rounded-xl">
                                <div class="mb-1 flex justify-between items-center">
                                    <div class="flex items-center gap-x-3">
                                    <span class="size-10 flex justify-center items-center border border-gray-200 text-gray-500 rounded-lg" data-hs-file-upload-file-icon="">
                                        <img class="rounded-lg hidden" data-dz-thumbnail="">
                                    </span>
                                    <div>
                                        <p class="text-sm font-medium text-gray-800 ">
                                        <span class="truncate inline-block max-w-[300px] align-bottom" data-hs-file-upload-file-name=""></span>.<span data-hs-file-upload-file-ext=""></span>
                                        </p>
                                        <p class="text-xs text-gray-500" data-hs-file-upload-file-size=""></p>
                                    </div>
                                    </div>
                                    <div class="flex items-center gap-x-2">
                                    <button type="button" class="text-gray-500 hover:text-gray-800 focus:outline-none focus:text-gray-800" data-hs-file-upload-remove="">
                                        <svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                        <path d="M3 6h18"></path>
                                        <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                                        <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path>
                                        <line x1="10" x2="10" y1="11" y2="17"></line>
                                        <line x1="14" x2="14" y1="11" y2="17"></line>
                                        </svg>
                                    </button>
                                    </div>
                                </div>

                                <div class="flex items-center gap-x-3 whitespace-nowrap">
                                    <div class="flex w-full h-2 bg-gray-200 rounded-full overflow-hidden" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" data-hs-file-upload-progress-bar="">
                                    <div class="flex flex-col justify-center rounded-full overflow-hidden bg-blue-600 text-xs text-white text-center whitespace-nowrap transition-all duration-500 hs-file-upload-complete:bg-green-500" style="width: 0" data-hs-file-upload-progress-bar-pane=""></div>
                                    </div>
                                    <div class="w-10 text-end">
                                    <span class="text-sm text-gray-800 ">
                                        <span data-hs-file-upload-progress-bar-value="">0</span>%
                                    </span>
                                    </div>
                                </div>
                                </div>
                            </template>

                            <div class="cursor-pointer p-12 flex justify-center bg-white border border-dashed border-gray-300 rounded-xl" data-hs-file-upload-trigger="">
                                <div class="text-center">
                                <span class="inline-flex justify-center items-center size-16 bg-gray-100 text-gray-800 rounded-full">
                                    <svg class="shrink-0 size-6" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
                                    <polyline points="17 8 12 3 7 8"></polyline>
                                    <line x1="12" x2="12" y1="3" y2="15"></line>
                                    </svg>
                                </span>

                                <div class="mt-4 flex flex-wrap justify-center text-sm leading-6 text-gray-600">
                                    <span class="pe-1 font-medium text-gray-800">
                                    Drop your file here or
                                    </span>
                                    <span class="bg-white font-semibold text-blue-600 hover:text-blue-700 rounded-lg decoration-2 hover:underline focus-within:outline-none focus-within:ring-2 focus-within:ring-blue-600 focus-within:ring-offset-2">browse</span>
                                </div>

                                <p class="mt-1 text-xs text-gray-400">
                                    Pick a file up to 2MB.
                                </p>
                                </div>
                            </div>

                            <div class="mt-4 space-y-2 empty:mt-0" data-hs-file-upload-previews=""></div>
                        </div>
                    </div>
<?php

if (isset($_POST['add'])) {
    $user = $_SESSION['iduser'];
    $user_name = $_SESSION['fullname'];

    // Validate and process the form data
    $idproj = $_POST['idproj'];
    $supplier = $_POST['supplier'];
    $phoneno = isset($_POST['phone']) ? mysqli_real_escape_string($conn, $_POST['phone']) : null;
    $email = isset($_POST['email']) ? mysqli_real_escape_string($conn, $_POST['email']) : null;
    $company = isset($_POST['company']) ? mysqli_real_escape_string($conn, $_POST['company']) : null;
    $address = isset($_POST['address']) ? mysqli_real_escape_string($conn, $_POST['address']) : null;
    $serv = $_POST['services'];
    $desc = isset($_POST['desc']) ? mysqli_real_escape_string($conn, $_POST['desc']) : null;

    // Initialize the $target_file variable
    $target_file = null;

    // Check if the invoice file was uploaded
    if (isset($_FILES['invoice']) && $_FILES['invoice']['error'] === UPLOAD_ERR_OK) {
        $pdf_file = $_FILES['invoice'];

        // Check if file is a PDF
        $file_type = mime_content_type($pdf_file['tmp_name']);
        if ($file_type != 'application/pdf') {
            die("Only PDF files are allowed.");
        }

        // Upload directory
        $upload_dir = "../../_invoice/";
        if (!is_dir($upload_dir)) {
            if (!mkdir($upload_dir, 0777, true)) {
                die('Failed to create directories...');
            }
        }

        // Generate a unique name for the file and move it to the upload directory
        $file_name = "SupInv_" . uniqid() . "_" . basename($pdf_file['name']);
        $target_file = $upload_dir . $file_name;

        if (!move_uploaded_file($pdf_file['tmp_name'], $target_file)) {
            echo "Error uploading the file.";
            $target_file = null; // Reset $target_file to null if upload fails
        }
    }

    // Build the SQL query based on whether the invoice was uploaded
    if ($target_file) {
        $sql = "INSERT INTO supplier (idproj, suppliername, suppliernotel, supplieremail, companyname, companyaddress, services, servicesdesc, invoicepdf, supplierCreated, created_by) 
                VALUES ('$idproj', '$supplier', '$phoneno', '$email', '$company', '$address', '$serv', '$desc', '$target_file', '$user_name', '$user')";
    } else {
        $sql = "INSERT INTO supplier (idproj, suppliername, suppliernotel, supplieremail, companyname, companyaddress, services, servicesdesc, supplierCreated, created_by) 
                VALUES ('$idproj', '$supplier', '$phoneno', '$email', '$company', '$address', '$serv', '$desc', '$user_name', '$user')";
    }

    $execute = mysqli_query($conn, $sql);

    if ($execute) {

        echo "<script>
            const Toast = Swal.mixin({
                toast: true,
                position: 'top-end',
                showConfirmButton: false,
                timer: 3000,
                timerProgressBar: true,
                didOpen: (toast) => {
                    toast.addEventListener('mouseenter', Swal.stopTimer);
                    toast.addEventListener('mouseleave', Swal.resumeTimer);
                }
            });

            Toast.fire({
                icon: 'success',
                title: 'New Supplier Added Successfully',
                text: 'Redirecting . . . '
            }).then(() => {
                window.location.href = '../project/vendor.php';
            });
        </script>";

        // Notification
        $newidsupplier = mysqli_insert_id($conn);
        $iduser = $_SESSION["iduser"];
        $noti = "INSERT INTO notiadd (description, iduser, idsupplier)
        VALUES 
        ('New Vendor Added', '$iduser', '$newidsupplier')";
        $sqlnoti = mysqli_query($conn, $noti);
        
    } else {
        echo "Error: " . mysqli_error($conn);
    }
}?>

currently im working on new ui for uploading file. before this im using normal input file so there is no problem at all. but this time im using preline library file upload. the thing is the file i upload is not detect because obviously not have input tag. but now i dont know how and where to put it. if i put it inside the code it seems the input and the file upload not sync and uploading empty data to my database. help me to find the solution

Timer component in React not updating when receiving new value from websocket

This is my first time using React and websockets.
So, I have this TurnTimer component with an initialTime prop, and it ticks down from there, eventually reaching 0 and sending a “skip” request to the API.
To ensure that a player doesn’t get infinite time from reloading the page, the backend keeps a separate timer that is sent in the body of Websocket messages, and that value is sent to my component as initialTime.
The thing, is, even if initialTime is modified, the component keeps ticking down from the initial value and never actually updates.
I included a console.log for debugging and it only prints when the component is first rendered.
Code below:

TurnTimer.jsx:

import React, { useState, useEffect } from "react";
import TurnTimerView from "./components/TurnTimerView.jsx";

const TurnTimer = ({ initialTime, playerId, gameId, isYourTurn }) => {
    const [secondsLeft, setSecondsLeft] = useState(initialTime);
    const [isLoading, setIsLoading] = useState(false);

    useEffect(() => {
        console.log("Nuevo time recibido:", initialTime);
        setSecondsLeft(initialTime);
    }, [initialTime]);

    useEffect(() => {
        if (secondsLeft <= 0) return;
        const interval = setInterval(() => {
            setSecondsLeft((prev) => {
                if (prev <= 0) {
                    clearInterval(interval); 
                    if (isYourTurn) {
                        handleEndTurn();
                    }
                    return 0;
                }
                return prev - 1;
            });
        }, 1000);

        return () => clearInterval(interval);
    }, [secondsLeft, isYourTurn]);

    const handleEndTurn = async () => {
        const data = { player_id: playerId };
        setIsLoading(true);

        try {
            const response = await fetch(`/api/games/${gameId}/skip`, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                },
                body: JSON.stringify(data),
            });

            if (response.ok) {
                console.log(`Jugador ${playerId} ha terminado su turno por timer`);
                setSecondsLeft(15);
            } else {
                console.error("Error al intentar terminar el turno por timer");
            }
        } catch (error) {
            console.error("Error en la solicitud:", error);
        } finally {
            setIsLoading(false);
        }
    };

    return (
        <div>
            <TurnTimerView 
                timer={secondsLeft}
                loading={isLoading}
            />
        </div>
    );
};

export default TurnTimer;

I don’t think the code for TurnTimerView is needed.

StartGame: (where the websocket sends stuff)

//other imports and variables ...
import TurnTimer from "../TurnTimer/TurnTimer.jsx";
const [time, setTime] = useState(120);

...
socketRef.current.onmessage = (event) => {
      const message = JSON.parse(event.data);
      console.log(message);
      if (message.type === "GameStarted") {
        setPlayers(message.payload.players);
        setBoard(message.payload.board);
        setCurrentPlayerId(players[0]?.unique_id);
        calculateCurrentPlayerId(0, players);
        setTurnNumber(message.payload.turn);

        setTime(message.payload.turn_timer);

        calculateCurrentPlayerId(turnNumber, message.payload.players);
        localStorage.setItem(`game_${game_id}_turn`, message.payload.turn);
      } else if (message.type === "TurnSkipped") {
        setBoard(message.payload.board);
        setPlayers(message.payload.players);
        setCurrentTurn(message.payload.turn);
        const newTurn = message.payload["turn"];
        setTurnNumber(newTurn); 
        setIsYourTurn(calculateIsYourTurn(newTurn, players, userId));
        localStorage.setItem(`game_${game_id}_turn`, newTurn);
        calculateCurrentPlayerId(newTurn, message.payload.players);

        setTime(message.payload.turn_timer);

      } else if (message.type === "MovSuccess") {
        setBoard(message.payload.board);
        setPlayers(message.payload.players);
        setTime(message.payload.turn_timer);
      } else if (message.type === "MoveUnMade") {
        setBoard(message.payload.board);
        setPlayers(message.payload.players);
        setTime(message.payload.turn_timer);
      } else if (message.type === "FigureMade") {
        setPlayers(message.payload.players);
        setTime(message.payload.turn_timer);
      }
    };
...

//and the actual component:
return (...
<TurnTimer
                initialTime={time}
                playerId={userId}
                gameId={game_id}
                isYourTurn={isYourTurn}  
/>
...)

I’ve omitted a lot of stuff that I don’t think is needed for this, but I can post the entire 250 LOC for StartGame if needed.

Remove character for specific column

I need to remove thousand comma separator (,) in Total Chargeable column. Currently i’m using
line = line.replace(',', ''); but then it will remove all commas.

Any suggestions how we can remove thousand comma without removing separator comma in JavaScript?

File is csv format but view on notepad

Example :

As-Is

"Modem ID","Total Chargeable"
"BF002062010","1,300.00"
"BF002062013","1,900.00"
"VV878443","1,000.00"
"","2,200.00"
"BF002061500","5,300.67"
"BF002062151","2,000.00"

To-Be

"Modem ID","Total Chargeable"
"BF002062010","1300.00"
"BF002062013","1900.00"
"VV878443","1000.00"
"","2200.00"
"BF002061500","5300.67"
"BF002062151","2000.00"

StripeJS – CSP error: Refused to create a worker from ‘blob:’ URL due to missing ‘worker-src’ directive

I’m encountering an issue related to Content Security Policy (CSP) and Web Workers when integrating the Stripe API in my local project.

Problem description:

When I try to load the page that integrates Stripe.js, I get the following error in the console:

Refused to create a worker from 'blob:https://m.stripe.network/9ebe38a1-64c4-425e-835f-e4af76e27553' because it violates the following Content Security Policy directive: "script-src https://m.stripe.network 'sha256-/5Guo2nzv5n/w6ukZpOBZOtTJBJPSkJ6mhHpnBgm3Ls='". Note that 'worker-src' was not explicitly set, so 'script-src' is used as a fallback.

The error indicates that Stripe is attempting to create a Web Worker from a blob: URL, but it is being blocked by the page’s Content Security Policy (CSP).

What I’ve tried so far:

I have updated the CSP policy in my HTML code, specifically in the worker-src directive, to allow blob: URLs. Here’s the version of CSP I’m using:

<meta http-equiv="Content-Security-Policy" content="default-src *; script-src *; style-src *; img-src *; font-src *; connect-src *; frame-src *; object-src *; child-src *; media-src *; manifest-src *; worker-src * blob:;">

Even though the worker-src * blob: directive is included, I’m still seeing the same error.

This is how my code looks so far:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy"
        content="default-src * blob:; script-src *; style-src *; img-src *; font-src *; connect-src *; frame-src *; object-src *; child-src *; media-src *; manifest-src *; worker-src * blob:;">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
    <script src="https://js.stripe.com/v3/"></script>

    <title>Stripe Integration - Proof of Concept</title>
</head>

<body>
    <form action="">
        <label for="">Label</label>
        <input type="text" name="" id="">
    </form>
    <script>
        const stripe = Stripe('pk_test_---'); 
    </script>
</body>

</html>

Why I believe this is a CSP issue:

The error message suggests that the problem is related to the lack of a proper CSP directive that allows the creation of Web Workers from blob: URLs.

What I’ve tried:

  1. Added blob: to the worker-src directive in CSP.
  2. Tried allowing * for all sources in the CSP (e.g., script-src *).
  3. I’ve read about how blob: URLs need to be explicitly allowed in the CSP, and I’ve followed the suggestions from the official documentation, but the error persists.

What I’m looking for:

I would appreciate any guidance on whether I’ve missed any steps or if there’s a more effective way to allow blob: Web Workers in a content security policy, in a secure manner.

Has anyone faced this issue before, or does anyone know how to resolve it?

Thanks in advance for any help.

Additional details:

  • Stripe.js Version: I am using the latest version of Stripe.js.
  • Environment: Local development using an HTTP server at 127.0.0.1:5500

Next 15 with Sanity CMS, I can’t cache my datas

I’m currently in the process of migrating from Next.js 14 to Next.js 15 and encountered an issue related to caching when using the fetch function to retrieve data from Sanity. In Next.js 14, I was able to cache my data effectively, but this is not working as expected in Next.js 15, which has default caching mechanisms (No cache by default).

Here’s the relevant code:

client.ts

import { createClient } from 'next-sanity';
import { apiVersion, dataset, projectId } from '../env';

const client = createClient({
  projectId,
  dataset,
  apiVersion,
  useCdn: true,
});

export default client;

sanity-query.ts

export async function getExperiences(language: string) {
  return client.fetch(
    groq`*[_type == "experience" && language == $language] | order(endDate desc){
      name,
      company,
      "logo": logo.asset->url,
      url,
      description,
      city,
      province,
      startDate,
      endDate
    }`,
    { language }
  );
}

export async function getSkills() {
  return client.fetch(
    groq`*[_type == "skill"] | order(_createdAt desc){
      localizedName,
      skills[]{
        name,
        "logo": logo.asset->url,
        "darklogo": darklogo.asset->url,
        url
      }
    }`
  );
}

Skills.ts

import { getSkills } from "@/sanity/sanity-query";
import { SkillsType } from "@/types";

const CodingSkills = async () => {
  const skills: SkillsType[] = await getSkills();
  
  return (
    <>
      <Skills codingSkills={skills} />
    </>
  );
};

export default CodingSkills;

In Next.js 15, it seems that the new caching behavior doesn’t automatically apply to external data sources when using custom fetch functions like the ones above. How can I adapt my existing code to Next.js 15 to cache my data when fetching from Sanity function?

Any solutions would be appreciated!

HTMLElement.focus(): What is considered as “visible”?

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
https://html.spec.whatwg.org/multipage/interaction.html#focusing-steps

When calling the focus() method on an HTMLElement, the developer needs to make sure that the element is “visible” in the DOM, otherwise the focus will fail and will either do nothing or return to the body element.

This fact notably appears to be missing from the MDN page on focus(), and I can’t figure out what to make of the associated WHATWG spec.

My understanding is that, to receive focus, the element must:

  • Not have visibility: hidden, using window.getComputedStyle(element).visibility !== 'hidden'
  • Have dimensions element.getBoundingClientRect().width > 0 && element.getBoundingClientRect().height > 0
  • Be in the document flow element.offsetParent !== null
  • Have a tabindex

Without confirming the spec, I can’t confirm if the above is correct.

Can I create a module specifier from an object?

In JavaScript, we can import modules like so:

import defaultExport from "module-name";
import * as name from "module-name";

where module-name is the module specifier.

If I already have an object in memory, can I “create” a module specifier from it?

Like this:

// main.js

const myObj = { text: 'Hello World' };

createModuleSpecifier(myObj, 'my-obj'); // <-- is this possible in JavaScript?
// module.js

import * as MyObj from "my-obj";

console.log(MyObj.text); // <-- this should log 'Hello World' to the console