Route Transition Flickering in React Router v7

I’m currently developing a project utilizing React Router v7 framework where I need to implement protected routes. While I’ve successfully implemented the protection mechanism, I’m encountering an issue where the protected page’s layout briefly flashes before the redirect occurs. I want to prevent this behavior by ensuring the redirect happens before any page rendering takes place. Below are my route.jsx and protected.jsx implementations:

import { Outlet, useNavigate } from "react-router";
import { useDispatch } from "react-redux";
import { getTokenFromCookie } from "./tokenServices";
import { setOpenAuthModal } from "../redux/slices/authSlice";

const ProtectedRoute = () => {
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const token = getTokenFromCookie();

  useEffect(() => {
    if (!token) {
      dispatch(setOpenAuthModal());
      navigate("/");
    }
  }, [token, dispatch, navigate]);

  return token ? <Outlet /> : null;
};

export default ProtectedRoute;
import { index, layout, prefix, route } from "@react-router/dev/routes";

export default [
  layout("./layouts/AppLayout.jsx", [
    index("routes/home/route.jsx"),
    route("/support", "routes/support/route.jsx"),
    route("/rooms/:villaId", "routes/room/route.jsx"),
    route("/archive/:cityName", "routes/archive-city/route.jsx"),

    layout("./services/auth/ProtectedRoute.jsx", [
      route("/profile", "routes/profile/dashboard/route.jsx"),
      route("/wallet", "routes/wallet/route.jsx"),
      route("/invite-friends", "routes/invite-friends/route.jsx"),
      route("/trips", "routes/trips/route.jsx"),
      ...prefix("/comments", [
        index("routes/comments/route.jsx"),
        route("/register/:vilaId", "routes/profile/registerComment/route.jsx"),
      ]),

      ...prefix("/host", [
        route("/profile", "routes/host/dashboard/route.jsx"),
        ...prefix("/comments", [
          index("routes/host/comments/route.jsx"),
          route(
            "/:commentId",
            "routes/host/comments/residenceHostComments/route.jsx",
          ),
        ]),
        route("/list-of-resisdence", "routes/host/listOfResisdence/route.jsx"),
        route("/statistics", "routes/host/statistics/route.jsx"),

        // layout("./services/auth/ProtectedReservationHost.jsx", [
        layout("./layouts/hostRegistration/HostRegistrationLayout.jsx", [
          ...prefix("/residence-registration", [
            route(
              "/specifications",
              "routes/host/residence-registration/specifications/create/route.jsx",
            ),
            route(
              "edit/specifications/:registrationId",
              "routes/host/residence-registration/specifications/edit/route.jsx",
            ),
            route(
              "edit/rooms/:registrationId",
              "routes/host/residence-registration/rooms/route.jsx",
            ),
            route(
              "edit/images/:registrationId",
              "routes/host/residence-registration/images/route.jsx",
            ),
            route(
              "edit/facilities/:registrationId",
              "routes/host/residence-registration/facilities/route.jsx",
            ),
            route(
              "edit/neighborhood/:registrationId",
              "routes/host/residence-registration/neighborhood/route.jsx",
            ),
            route(
              "edit/rules/:registrationId",
              "routes/host/residence-registration/rules/route.jsx",
            ),
            route(
              "edit/prices/:registrationId",
              "routes/host/residence-registration/prices/route.jsx",
            ),
            route(
              "edit/documents/:registrationId",
              "routes/host/residence-registration/documents/route.jsx",
            ),
          ]),
        ]),
        // ]),
      ]),

      layout("routes/reservation/route.jsx", [
        route(
          "reservation/checkout/:reserveId",
          "routes/reservation/check/route.jsx",
        ),
        route(
          "reservation/payment/:reserveId",
          "routes/reservation/payment/route.jsx",
        ),
        route(
          "reservation/delivery/:reserveId",
          "routes/reservation/delivery/route.jsx",
        ),
      ]),
    ]),
  ]),
  // layout("./services/auth/ProtectedRoute.jsx", [
  //   route("/invoice/reserve/:reserveId", "routes/invoice-reserve/route.jsx"), // ✅ Invoice route here
  // ]),
];

How to sync a txt file online and read that file with javascript?

I have a txt file that is on my PC, that txt file gets updated every time a new song plays in my media player. I need a way to sync this txt file somewhere where I can access it over the internet from a website using javascript, but it needs to remain synced to the one on my PC.

Is there any service that can allow me to sync the txt file and have a url that can publicly read the raw text from the file?

I’d like to take the synced text, convert it to a string, and update that every 30 seconds or so on my own website.

How to Merge Multiple SVG Files into a Single Animated SVG?

I have a large number of SVG files that represent frames of a bar chart race animation. I’ve uploaded a sample of these files here:
https://easyupload.io/69jzns

I want to merge them into a single animated SVG file and set a specific FPS (frames per second) for the animation. Each SVG file should act as one frame in the final animated SVG.

I’ve tried the following tools but couldn’t achieve the desired result:

What tool or method can accomplish this? Any help would be appreciated!

How do I show the correct answer if an incorrect answer have been selected?

I’m trying to add a some code that will show the correct answer if the incorrect one have been selected, is this possible if so can someone please show / guide me on how to do this.

as you can see from the attached photo when a incorrect answer is selected you are not able to view the correct one you just move on, how could i change this to either automatically show the correct answer or add a “check answer button”

my code is;

const questions = [
    {
        question: "What is a checkout score for 156?",
        answers: [
            {text: "T19, T19, D20", correct: false},
            {text: "T20, T20, D20", correct: false},
            {text: "T20, T14, D16", correct: false},
            {text: "T20, T20, D18", correct: true}
        ]
    },
    {
        question: "How many world titles does Michael van Gerwen have?",
        answers: [
            { text: "5", correct: false },
            { text: "1", correct: false },
            { text: "0", correct: false },
            { text: "3", correct: true }
        ]
    },
    {
        question: "What is the highest possible checkout in darts?",
        answers: [
            { text: "180", correct: false },
            { text: "170", correct: true },
            { text: "160", correct: false },
            { text: "150", correct: false }
        ]
    },
    {
        question: "Who won the PDC World Championship on their debut appearance in 2018?",
        answers: [
            { text: "Nathan Aspinall", correct: false },
            { text: "Glen Durrant", correct: false },
            { text: "Rob Cross", correct: true },
            { text: "Dimitri Van Den Bergh", correct: false }
        ]
    },
    {
        question: "Which player is nicknamed Bully Boy?",
        answers: [
            { text: "Nathan Aspinall", correct: false },
            { text: "Joe Cullen", correct: false },
            { text: "Jonny Clayton", correct: false },
            { text: "Michael Smith", correct: true }
        ]
    },
    {
        question: "Which player is known for his intense stare at the dartboard and aggressive celebrations?",
        answers: [
            { text: "Adrian Lewis", correct: false },
            { text: "Gerwyn Price", correct: true },
            { text: "Jonny Clayton", correct: false },
            { text: "Danny Noppert", correct: false }
        ]
    },
    {
    question: "What is the standard height from the floor to the bullseye in professional darts?",
    answers: [
        { text: "5 feet 4 inches", correct: false },
        { text: "6 feet", correct: false },
        { text: "4 feet 10 inches", correct: false },
        { text: "5 feet 8 inches", correct: true }
    ]
},
{
question: "In professional darts, what is the “Madhouse”?",
answers: [
    { text: "Missing three darts at double 1", correct: false },
    { text: "Needing double 1 to win", correct: true },
    { text: "Scoring three consecutive busts", correct: false },
    { text: "Hitting only single 5s in a turn", correct: false }
    ]
},
{
    question: "What is the minimum number of darts needed to win a game of 501?",
    answers: [
        { text: "12", correct: false },
        { text: "6", correct: false },
        { text: "15", correct: false },
        { text: "9", correct: true }
        ]
    },
    {
        question: "Phil Taylor won a record 16 World Championships. In which year did he win his first title?",
        answers: [
            { text: "1990", correct: true },
            { text: "1995", correct: false },
            { text: "1992", correct: false },
            { text: "1998", correct: false }
            ]
        },

]

const questionElement = document.getElementById("question");
const answerButtons = document.getElementById("answer-buttons");
const nextButton = document.getElementById("next-btn");

let currentQuestionIndex = 0;
let score = 0;


/**
 * Resets the quiz by setting the question index and score to their original values (0). 
 * Hides the "Next" button and prepares it for the next question, and then displays the first question. 
 * This function ensures the quiz starts fresh and is ready for the user.
 */

function startQuiz() {
    currentQuestionIndex = 0; // Resets the question index to start from the first question.
    score = 0; // Resets the score to 0 for a new quiz session.
    nextButton.innerHTML = "Next"; // Sets the button text to "Next".
    nextButton.style.display = "none"; // Hides the button until an answer is selected.
    nextButton.onclick = nextQuestion; // Sets the button to call the nextQuestion function when clicked.
    showQuestion(); // Calls the showQuestion function to display the first question.
}

/**
 * Displays the current question and its answers, setting up the UI for user interaction.
 * 1. Clears previous question and answers using `resetState()`.
 * 2. Retrieves and displays the current question with its number.
 * 3. Loops through each answer, creating a button for each:
    - Sets button text, adds styling, and appends it to the container.
 * 4. If the answer is correct, adds a `data.correct` attribute.
 * 5. Adds a click event listener to each button to trigger `selectAnswer`.
 */

function showQuestion() {
    resetState(); // Clears the previous question and answers
    let currentQuestion = questions[currentQuestionIndex]; // Gets the current question
    let questionNo = currentQuestionIndex + 1; // Sets the question number
    questionElement.innerHTML = questionNo + ". " + currentQuestion.question; // Displays the current question number and text
    
    currentQuestion.answers.forEach(answer => { // Loops through answers and creates a button
        const button = document.createElement("button"); // Creates a new button element
        button.innerHTML = answer.text; // Sets the button text to the answer text
        button.classList.add("btn"); // Adds the "btn" class to the button for styling
        answerButtons.appendChild(button); // Appends button to the answer container
 
        if (answer.correct) { // If the answer is correct, set a data attribute
            button.dataset.correct = answer.correct;
        }

        button.addEventListener("click", selectAnswer); // Adds an event listener to the button to call selectAnswer when clicked
    });
}

/**
 * Resets the screen by hiding the "Next" button and clearing the answer buttons.
 * 1. Hides the "Next" button so it’s not visible.
 * 2. Removes all the answer buttons from the screen.
 */

function resetState() {
    nextButton.style.display = "none"; // Hides the "Next" button
    while (answerButtons.firstChild) {
        answerButtons.removeChild(answerButtons.firstChild); // Removes all child elements from the answer container
    }
}

/**
 * Runs when the user picks an answer.
 * 1. Checks if the answer is right.
 * 2. Adds a "correct" or "incorrect" class to the button.
 * 3. Updates the score if the answer is right.
 * 4. Shows the "Next" button to move to the next question.
 */

function selectAnswer(e) { 
    const selectedBtn = e.target;
    const isCorrect = selectedBtn.dataset.correct === "true"; // Checks if the selected answer is correct

    if (isCorrect) {
        selectedBtn.classList.add("correct"); // Adds "correct" class to the button for styling
        score++; // Increases the score if the answer is correct
    } else {
        selectedBtn.classList.add("incorrect"); // Adds "incorrect" class to the button for styling
    }
    
         // Disable all buttons after an answer is selected
    const allButtons = answerButtons.querySelectorAll("button");
    allButtons.forEach(button => button.disabled = true);



    nextButton.style.display = "block"; // Display "Next" button once an answer is selected
}

/**
 * Goes to the next question or wraps up the quiz if you're out of questions.
 * - If there are more questions, it shows the next one.  
 * - If you're done, it displays your final score and a "Restart" button.  
 * - Clicking "Restart" reloads the page so you can play again.  
 */

function nextQuestion() {
    currentQuestionIndex++; // Move to the next question

    if (currentQuestionIndex < questions.length) { // If there are more questions
        showQuestion(); // Show the next question
    } else {
        questionElement.innerHTML = `Quiz Finished! Your score: ${score}/${questions.length}`; // Displays the final score
        answerButtons.innerHTML = ""; // Clears any remaining answer buttons
        nextButton.innerHTML = "Restart"; // Sets the button text to "Restart"
        nextButton.style.display = "block"; // Shows the "Restart" button
        nextButton.addEventListener("click", () => { // Adds an event listener to restart the quiz
            window.location.reload(); // Reloads the page to restart the quiz
        } );
    }
}

nextButton.onclick = startQuiz; // Starts the quiz when the page loads

startQuiz();

is anyone able to help or point me in the right direction please?

How to access child route parameters from parent routes in Next.js App Router?

I’m building a Next.js application using the App Router and I’m having trouble accessing route parameters from parent components that are higher in the routing hierarchy.
My route structure:

app/page.tsx (Root page)

app/layout.tsx (Root layout)

app/[category]/page.js (Category-specific layout)

I need to access the [category] dynamic parameter from either app/page.tsx or app/layout.tsx`, which are strictly server components.

For example, if the user navigates to /products/electronics, I want to be able to access the value electronics in my root layout or page, but I’m not sure how to do this with server components since these parameters only exist when that segment of the URL is accessed.

How do we access content script from popup.html file

I am creating a browser extension using WXT
I have set up the basic styles for popup.html and now i was trying to create a element from the dom using the extension. In order to do that i have written up a very basic js code which creates a video element (This is to test if it actually works and to my surprise i got an error saying “document is not defined”). So after debugging for a while i found out that we cannot access dom or storage related stuffs from background worker. In order to get access to these we would have to do so by using content script.

So, then i started digging into implementing an approach where i can create an element using content script of the extension but i cant seem to wrap my head around it.

For you guys:

# popup.html
      const [tab] = await browser.tabs.query({ active: true, currentWindow: true })
      if (!tab?.id) throw new Error("No tab found!")
      console.log("tab ", tab)


      const resp = await browser.tabs.sendMessage(tab.id, "to_content_script")
      console.log("resp ", resp)
# background.ts
import { browser } from "wxt/browser";

export default defineBackground(() => {
console.log("background worker initialized")
}
# content.ts
export default defineContentScript({
  matches: ["*://*/*"],

  async main() {
    console.log("content script initialized")
  },
}); 

CURRENT PROBLEM: the content script never actually initialized, no matter what i do.
I tried sending an message from popup.html to content.ts file where i was listening for the message.
I also tried sending a message from popup.html to background.ts(This worked), then from background.ts to content.ts file, where this didnt worked.

# wxt.config.ts
import { defineConfig } from 'wxt';

// See https://wxt.dev/api/config.html
export default defineConfig({
  extensionApi: 'chrome',
  srcDir: 'src',
  modules: ['@wxt-dev/module-react'],
  runner: {
    startUrls: ["https://wxt.dev"],
  },
  manifest: {
    version: "0.0.1",
    permissions: ["activeTab", "tabCapture", "tabs", "webRequest", "scripting"],
    host_permissions: ["<all_urls>"],
    background: {
      service_worker: "background.ts",
      type: "module"
    },
    content_scripts: [
      {
        "matches": ["<all_urls>"],
        "js": ["content-scripts/content.js"]
      }
    ],
    content_security_policy: {
      extension_pages: "script-src 'self'; object-src 'self';",
    },
    web_accessible_resources: [
      {
        resources: ["*"],
        matches: ["<all_urls>"],
      },
    ],
  }
});

Use opentypejs to loop through all glyphs in a font and output them to the page

TL/DR: How to display each glyph from a font file using some parsing method that shows all of the characters.

I am trying to build a glyph viewer for one of several fonts I want to show on a page.

Currently I have this codesandbox (this is cramped so there is a full page version here)

Here is my JS:

import opentype from "opentype.js";
const htmlElem = document.querySelector("html");

const fontPath = "/src/resources";

const fontMap = (fontName) => {
  const url = `${fontPath}/${fontName}`;
  const buffer = fetch(url).then((res) => res.arrayBuffer());

  buffer.then((data) => {
    const wrapper = htmlElem.querySelector(".characters ul");
    const font = opentype.parse(data);
    const glyphs = font.glyphs.glyphs;
    for (const [key, value] of Object.entries(glyphs)) {
      if (value.name !== null) {
        const template = `<li>${value.name}</li>`;
        wrapper.insertAdjacentHTML("beforeend", template);
        console.log(value);
      }
    }
  });
};

fontMap("Calluna-Regular.otf");

When I log each glyph I get quite a lot of data about the element, however I want to know how to access it on the page using the correct property.

enter image description here

Currently trying to access item.name which works fine for ‘A’, ‘B’, ‘C’ etc, but numbers are named in full ‘one’, ‘two’, etc. And punctuation marks, I guess name makes sense.

I tried adding a prefix to output as html entities, like <li>&${value.name};</li> but of course that will prefix the standard ‘A’ with an ‘&’.

Is there a universal way to parse each character and use some encoding to display each item on the page? Hex maybe but not transform the simple characters. The other thing I wondered is whether certain glyphs have particular properties that distinguish them. I think the unicode property is the only one I can access that will help me.

Also in this font the letter ‘A’ has unicode: 64 in the mapping but the universal unicode character for ‘A’ is U+0041 (or is that already converted using some system), I don’t know if this is some peculiarity of the font file.

Any help greatly appreciated.

Find specific element that follows another specific element

In CSS, if you want to target a specific element that immediately follows another specific element, you would use the next-sibling combinator:

<style>
/* any 'p' that immediately follows 'div' will be red */
div + p { color: red; }
</style>

<div>
  <p>foo</p>  <!-- black -->
</div>
<p>bar</p>    <!-- red   -->
<p>baz</p>    <!-- black -->

<div>
  <p>foo</p>  <!-- black -->
</div>
<p>bar</p>    <!-- red   -->
<p>baz</p>    <!-- black -->

But how to make it in JavaScript? I tried closest, but I’m not surprised it doesn’t work. If I understand its description on MDN, it is intended to work differently.

<div class="input" style="display: none">
foo
</div>
<div class="output"></div>

<div class="input" style="display: none">
foo
</div>
<div class="output"></div>

<script>
  'use strict';

  window.onload = function() {
    for (const input of document.querySelectorAll('.input')) {
      document.querySelector(input.closest('body > .output')).innerHTML = 'input.innerHTML';
    }
  }
</script>

How to make it work?

Implementing dynamic scope using with

Preface:
I have an app where I want to allow users to enter mostly mathematical code to create a simulation. It currently uses mathjs to evaluate code snippets, but without control statements it’s a bit inflexible. Even allowing a user to import arbitrary code and inject it into mathjs is somewhat obtuse. What I’d like is something that is relatively robust against accidental mistakes by non-malicious users.

Both mathjs and scraggy do this by walking parsed syntax trees with optional contexts passed in to provide free variable scopes. That seems to incur a large runtime overhead though, so I’ve worked out an alpha alternative based on with statements and a Proxy’d Map-like object, and I’m hoping to get some constructive criticism about performance and relative safety.

Here was my intent:

  1. prevent any writes to the globalThis, but allow access to global objects.
  2. allow ‘scoped’ contexts (I only need 3 deep). implementation below is derived from mathjs
  3. if a free variable is not found in any scope, create it in the current scope, otherwise update it in the scope its in.

Some lingering uncertainties:

  • I’m currently not parsing the content of the code snippets at all to remove bad stuff, but I’m also thinking that may not be required.
  • I don’t think I understand whether the [Symbol.unscopables] symbol would help protect me or help me shoot myself. I’d like to prevent someone from accidentally overwriting my Proxy’d object properties – is that the way to do that? Do I do that in the Proxy or the object?
  • I haven’t yet done performance tests, but the Proxy certainly involves some overhead.

Here’s the underlying Map-like class:

class MapScope  {
  constructor (parent=null) {
    this.localMap = new Map()
    this.parentScope = parent;
  }

  has (key) {
    return this.localMap.has(key) ? true : this.parentScope?.has(key) ?? false;
  }

  get (key) {
    return this.localMap.get(key) ?? this.parentScope?.get(key)
  }

  set (key, value) {
    const iGetIt = ! this.parentScope?.has(key) || this.localMap.has(key);
    return iGetIt ? this.localMap.set(key, value) : this.parentScope.set(key, value);
  }

  keys () {
    if (this.parentScope) {
      return new Set([...this.localMap.keys(), ...this.parentScope.keys()])
    } else {
      return this.localMap.keys()
    }
  }
  
  size() { return this.localMap.size();}

  forEach(cb, thisArg=this.localMap) {
    this.localMap.forEach(cb, thisArg);
  }
  
  delete (key) {
   // return false;
    return this.localMap.delete(key)
  }

  deleteProperty (p) {
    //return false;
    return this.localMap.delete(p)
 m }

  clear () {
    return this.localMap.clear()
  }

  toString () {
    return this.localMap.toString()
  }
}

Here’s the traps object for the Proxy:

var mapTraps = {
  // This says that variables in the local scope shadow the global ones
  // and that any new variables will be in the local scope
  has(target, key) {
    console.log(`called: has(..., ${key})`);
    if (key in globalThis && ! target.has(key)) {
      return false;
    }
    return true;
  },

  get(target,key,receiver) {
    if (!target.has(key)) {
      if (key in globalThis) {
        console.log(`get ${key.toString()} from globalThis`);
        return globalThis[key];
      } else {
        return undefined;
      }
    }
    console.log(`get ${key.toString()} from target`);
    return target.get(key);
  },

  // 
  set(target, key, val){
    console.log(`called: set(..., ${key.toString()})`);
    return target.set(key,val);
  }
}

Here’s how you put these two together – vars because noodling in Node:

var mscope = new MapScope()
var nscope = new MapScope(mscope)
var rscope = new MapScope(nscope)
var mproxy = new Proxy(mscope, mapTraps)
var nproxy = new Proxy(nscope, mapTraps)
var rproxy = new Proxy(rscope, mapTraps)

So mscope is the toplevel scope, nscope is between it and rscope.

Testing looks like this:

with (mproxy) {t = 0}
--> 0
with (mproxy) {t += 2 * Math.random()}
--> 1.75....
with(rproxy) {t<5}
--> true
with(nproxy) {t<5}
--> true

The intended use though is to use these functions to create runtime functions to run user code in the appropriate scope. See: Changing function’s scope for a similar solution or the MDN write-ups on the with statement and Proxy.

function compileSnippet(exp) {
  return new Function ("fscope", `
    with(fscope) {
     return ${exp} ;
    }
  `);
}

var startFn = compileSnippet(startExpr);
var startEachFn = compileSnippet(startEachExpr);

// evaluate in scope - typically for side-effect

startFn(nproxy)
...
startEachFn(nproxy)
...
// endEachFn and endFn also

ESLint rule to disallow useEffect without dependency list

Is there an ESLint rule for React to disallow writing useEffect without dependency list?

I’m looking for something like this:

useEffect(() => {
  if (error) handleError(error)
}) // ❌ I expect ESLint complains here, because there's no dependency list
useEffect(() => {
  if (error) handleError(error)
}, [error]) // ✅ Now it has an explicit dependency list

Nodejs time is one hour ahead from server time

I have a Node.js application and using date command in the terminal, I get the right time:

Sun Mar 30 12:38:25 PM +0330 2025

But using console.log( new Date().toLocaleString() ) I get this:

Sun Mar 30 13:38:25 PM +0330 2025

As you see it’s an hour ahead!

Why I get this and how to fix it?

sh: tailwind: command not found [closed]

enter image description here

I am developing a project of a blog system, and while being in the early stages of that, while setting up the project, while setting up tailwind, I got this error.

this terminal screenshot shows all the errors and I am not able to run script: npx tailwindcss init -p and it shows the error sh: tailwind: command not found

Terminal showing error

Issues with Render.js: Problems with Puppeteer and Parallel Rendering

I’m having trouble with a Node.js script (render.js) that uses Puppeteer for rendering videos and images in parallel. The script creates a renderer that generates frames based on an HTML page and then combines them into either PNG files or video files using FFmpeg. The script uses multiple worker processes to handle rendering concurrently.

You can find the code for this project on GitHub here: https://github.com/dtinth/html5-animation-video-renderer

However, I’m encountering an issue where the rendering process is not functioning as expected. Here’s an overview of the problem:

Error:
When I run the command:

node render --url="file:///D:/Desktop/airports/New%20folder/Flourish%20template_%20Bar%20chart%20race.htm" --png="D:/Desktop/airports/New%20folder/PNG_output" --no-video

I get the following error output:

Spawn worker 1
Worker 1: getInfo
render

Renders a video

Options:
  --version      Show version number                                   [boolean]
  --help         Show help                                             [boolean]
  --url          The URL to render
                                [string] [default: "file://D:DesktopNew folder
                                 (5)PNG/examples/gsap-hello-world.html?render"]
  --video        The path to video file to render. Without `--alpha` this MUST
                 be .mp4, and with `--alpha` this MUST be .mov
                                                 [string] [default: "video.mp4"]
  --parallelism  How many headless Chrome processes to use to render in parallel
                                                           [number] [default: 8]
  --start        Frame number to start rendering           [number] [default: 0]
  --end          Frame number to end rendering (that frame number will not be
                 rendered)                                              [number]
  --png          Directory for PNG frame output                         [string]
  --alpha        Renders a image/video with alpha transparency. For video, the
                 file extension MUST be .mov                           [boolean]
  --scale        Device scale factor                       [number] [default: 1]

Error: Evaluation failed: ReferenceError: getInfo is not defined
    at __puppeteer_evaluation_script__:9:22
    at ExecutionContext._evaluateInternal (D:DesktopNew folder (5)PNGnode_modulespuppeteerlibcjspuppeteercommonExecutionContext.js:175:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async ExecutionContext.evaluate (D:DesktopNew folder (5)PNGnode_modulespuppeteerlibcjspuppeteercommonExecutionContext.js:110:16)
    at async D:DesktopNew folder (5)PNGrender.js:21:20
    at async Object.getInfo (D:DesktopNew folder (5)PNGrender.js:48:17)
    at async work (D:DesktopNew folder (5)PNGrender.js:128:24)
    at async Object.main [as handler] (D:DesktopNew folder (5)PNGrender.js:261:20)

The error suggests that there is an issue with getInfo not being defined. However, I’m not sure why it is failing or where I should define this function.

What I’ve tried:

  • Ensuring that the getInfo function is properly defined and
    accessible.
  • Verifying that the script is correctly passing information between
    workers and handling the necessary functions.
  • Adding more logging to track down the flow of execution, but the
    issue persists.

The goal:
I want the script to render frames from the provided URL and output PNGs to the specified directory without creating a video, but it’s failing with this getInfo is not defined error.
Has anyone worked with Puppeteer and parallel rendering in Node.js and encountered similar issues? Any suggestions on how to properly define or handle the getInfo function, or how to debug this further, would be greatly appreciated!

Thanks in advance for your help!

Data not rendering in Mantine’s Select Component

The cities data is coming from an Api cityOptions is being logged to
the console, but
when I try to show it in the UI in a dropdown, no data shows.

const cityOptions = cities?.map((city) => ({
    value: city.id.toString(),
    label: city.name,
  })) || [];
  console.log("cityoptions", cityOptions)

<Select
  name="city"
  placeholder="Cities"
  value={city || null}
  maw={200}
  size="md"
  data={isLoading ? []: cityOptions}
  disabled={isLoading}
  onChange={(value) => setCity(value as string)}
  icon={<IconSelector size={18} stroke={1.75} />}
  clearable
  style={{ marginBottom: 0 }}
/>

How can I redirect correctly after logging into Twitter?

When the user is logged in, the code works correctly, the user authorizes the app and redirects me correctly to –> api/x/callback, the problem is when I have a user who is not logged in to X, when I access –> api/auth/x/callback, it redirects me to X’s login, I log in correctly, but it does not redirect me correctly to the (Authorize App) page, but instead it redirects me to X’s profile, does anyone know a solution to this problem, I would greatly appreciate your help

this is –> api/auth/x/callback

import { NextResponse } from 'next/server'
import crypto from 'crypto'

const X_CLIENT_ID = process.env.X_CLIENT_ID as string
const REDIRECT_URI = `${process.env.NEXT_PUBLIC_URL}${process.env.NEXT_PUBLIC_X_REDIRECT_URI}`

export async function GET() {
  if (!X_CLIENT_ID) {
    return NextResponse.json(
      { error: 'X_CLIENT_ID is not defined' },
      { status: 500 }
    )
  }

  const codeVerifier = crypto.randomBytes(32).toString('hex')
  const codeChallenge = crypto
    .createHash('sha256')
    .update(codeVerifier)
    .digest('base64url')

  const response = NextResponse.redirect(
    `https://twitter.com/i/oauth2/authorize?${new URLSearchParams({
      response_type: 'code',
      client_id: X_CLIENT_ID,
      redirect_uri: REDIRECT_URI,
      scope: 'tweet.read tweet.write users.read offline.access',
      state: crypto.randomBytes(16).toString('hex'),
      code_challenge: codeChallenge,
      code_challenge_method: 'S256'
    })}`
  )

  response.cookies.set('code_twitter_verifier', codeVerifier, {
    httpOnly: true,
    secure: true,
    sameSite: 'lax',
    path: '/'
  })

  return response
}

this is –> api/x/callback

import { NextResponse } from 'next/server'
import { cookies } from 'next/headers'

const X_CLIENT_ID = process.env.X_CLIENT_ID as string
const X_CLIENT_SECRET = process.env.X_CLIENT_SECRET as string
const REDIRECT_URI = `${process.env.NEXT_PUBLIC_URL}${process.env.NEXT_PUBLIC_X_REDIRECT_URI}`

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const code = searchParams.get('code')

  if (!code) {
    const redirectUrl = new URL(
      '/admin/organizations',
      request.url
    )

    return NextResponse.redirect(redirectUrl)
  }

  const codeVerifier = cookies().get('code_twitter_verifier')?.value
  if (!codeVerifier) {
    return NextResponse.json(
      { error: 'code_verifier not found' },
      { status: 400 }
    )
  }

  const credentials = Buffer.from(`${X_CLIENT_ID}:${X_CLIENT_SECRET}`).toString(
    'base64'
  )

  const tokenResponse = await fetch('https://api.twitter.com/2/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      Authorization: `Basic ${credentials}`
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code,
      redirect_uri: REDIRECT_URI,
      code_verifier: codeVerifier
    }).toString()
  })

  const tokenData = await tokenResponse.json()

  if (!tokenResponse.ok) {
    return NextResponse.json(
      { error: 'No se pudo obtener el token' },
      { status: 401 }
    )
  }

  const { access_token, refresh_token, expires_in } = tokenData

  const userResponse = await fetch('https://api.twitter.com/2/users/me', {
    headers: {
      Authorization: `Bearer ${access_token}`
    }
  })

  const userData = await userResponse.json()

  const { id, username } = userData.data

  if (!userResponse.ok) {
    return NextResponse.json({ error: 'User not found' }, { status: 401 })
  }

  const redirectUrl = new URL(
    '/admin/organizations/channels/twitter',
    request.url
  )
  redirectUrl.searchParams.append('accessToken', access_token)
  redirectUrl.searchParams.append('refreshToken', refresh_token)
  redirectUrl.searchParams.append('userId', id)
  redirectUrl.searchParams.append('screenName', username)
  redirectUrl.searchParams.append('expiresIn', expires_in)

  return NextResponse.redirect(redirectUrl)
}