What are the popular dishes at Malabar Menu?

Our most loved dishes include Thalassery Chicken Biryani, Arabic Mandhi, Poratta & Beef, Alfaham, and classic Malabar snacks.text

Malabar Menu is best known for its flavorful Thalassery Chicken Biryani, cooked with fragrant rice, tender meat, and traditional Malabar spices. Our Arabic Mandhi is another top favorite — juicy, smoky, and perfectly seasoned. Guests also love our Poratta and Beef Roast, a timeless Kerala combo. For snack lovers, we offer Malabar-style Samosas, Unnakaya, and Pazham Nirachathu, each handmade with care. Every item on our menu reflects the rich heritage of Malabar cuisine with a modern twist.text

How to completely disable build-time HTML generation for a pure SPA?

I’m using React Router v7 and I want a pure SPA setup—no server-side rendering (SSR) or pre-rendered HTML at all.

I set in my router config:

import type { Config } from "@react-router/dev/config";

export default {
  ssr: false,
  prerender: false,
  future: {
    v8_middleware: true,
  },
} satisfies Config;

Vite config:

import { reactRouter } from "@react-router/dev/vite";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
  build: {
    ssr: false,
  },
  plugins: [tailwindcss(), reactRouter(), tsconfigPaths()],
});

Even with this configuration, my build still generates HTML for the root route, and I get hydration mismatch errors in the browser.

The error:

Uncaught Error: Hydration failed because the server rendered text didn’t match the
client. As a result this tree will be regenerated on the client. This can happen if a
SSR-ed Client Component used:

  • A server/client branch if (typeof window !== 'undefined').
  • Variable input such as Date.now() or Math.random() which changes each time it’s called.
  • Date formatting in a user’s locale which doesn’t match the server.
  • External changing data without sending a snapshot of it along with the HTML.
  • Invalid HTML tag nesting.

It can also happen if the client has a browser extension installed
which messes with the HTML before React loaded.

I found this note in the docs:

“It’s important to note that setting ssr:false only disables runtime server rendering. React Router will still server render your root route at build time to generate the index.html file. This is why your project still needs a dependency on @react-router/node and your routes need to be SSR-safe. That means you can’t call window or other browser-only APIs during the initial render, even when server rendering is disabled.”

Is there a way to completely disable all build-time HTML generation in React Router v7 so that it behaves as a pure client-side SPA? Or do I need to bypass React Router’s build system entirely?

performAction function in WebdriverIO for iOS is executing but the gesture is not performed. Why and how to make the gesture executed?

I’m executing automation script using WebdriverIO and Appium in Android and ‘iOS’. I have automation test in javascripts. The functions in the automation scripts are working great in ‘Android’ but I have problem in executing the same functions in ‘iOS’. Suggestion that has been executed:

  1. The function in ‘Android’ is working ok but amazingly not working when executed in ‘iOS’. Following are the sniped of the code that I have turn into a function to be used as gesture of scrolling and touch.
export async function performScrollGesture01({
    startX,
    startY,
    endX,
    endY,
    delay = 1000,
    tapclickdelay = 50
  }) {
    console.log("START ACTION");
    const actions = [
      {
        type: 'pointer',
        id: 'finger1',
        parameters: { pointerType: 'touch' },
        actions: [
          { type: 'pointerMove', duration: 0, x: startX, y: startY },
          { type: 'pointerDown', button: 0 },
          { type: 'pause', duration: tapclickdelay },
          { type: 'pointerMove', duration: delay, 'origin': 'viewport', x: endX, y: endY},
          { type: 'pointerUp', button: 0 }
        ]
      }
    ];
    await browser.pause(100);
    await browser.performActions(actions);
    console.log("END ACTION");
}
  1. XCUITest version changes. Currently the latest.
  2. WebDriverAgent version changes.
  3. Using actions and touchActions functions instead of performActions.

Why does a cookie set with document.cookie in Safari show an expiration longer than 7 days under ITP?

I have a question regarding Safari’s Intelligent Tracking Prevention (ITP).

My understanding is that under Safari’s current ITP policy, any cookie created client-side using JavaScript’s document.cookie is capped at a maximum expiration of 7 days.

To test this behavior, I ran the following code in the Safari Developer Tools console to create a cookie with an expiration set to 30 days from now.

document.cookie = "cookie_test=hoge; expires=" + new Date(Date.now() + 30*24*60*60*1000).toUTCString() + "; path=/; SameSite=Lax";

After running the code, I inspected the cookie in the Developer Tools’ Storage tab. To my surprise, the Expires field for the cookie_test cookie was set to the full 30 days in the future, exactly as specified in the code.

This appears to contradict my understanding of the 7-day limit imposed by ITP.

  1. Is the 30-day expiration date shown in the Developer Tools merely a display value, while ITP will still delete the cookie internally after 7 days?

  2. Or, are there specific circumstances (such as running code directly from the console) where the 7-day ITP limit does not apply?

I would appreciate any clarification on the correct interpretation of this behavior.

Clearing memory in WebApp, after completion

Its a WebApp written in Delphi 12 using TMS Webcore.

At Logout (which happens by user action, or after idle timeout) I want to clear the memory

  • For security
  • In case there are undiscovered memory leaks
  • To allow the browser to download a new version if it exists

I keep getting an exception (below) on Restarting the Application.

Question : How can I

  • Either stop it form occurring (ideal)
  • Or Capture it silently and attempt another restart

I have tried a few options, but I keep getting an exception in the constructor of the Main form. This indicates that the memory from the previous session has not been cleared.

Code for Log_Out

procedure Tfrm_Ops_Main.Log_Out (AAuto : Boolean = False);
begin
  TConsole.Log (msg_Logging_Out);
  if AAuto
  then Stop_Warning_User_At_Tab_Close;
  Free_Child_Form;
  Close;
  { Allowing for Form to Close }
//  THtml.Replace_Page;
  THtml.Reload_After_Delay (400);
end;

I have tried the three methods

  • Replace_Page
  • Reload_Page
  • Reload_Page_After_Delay

THtml class code

class procedure THtml.Replace_Page  (AUrl : string = '');
var
  lUrl  : string;
  lTime : Int64;
begin
  { Add time in ms if same URL }
  if AUrl = ''
  then begin
       LTime := Trunc ((Now - UnixEpoch) * ToMS);
       LUrl := window.location.href + '?t=' + IntToStr (LTime);
  end
  else LUrl := AUrl;
  document.location.replace (LUrl);
end;

class procedure THtml.Reload_Page;
begin
  document.location.reload (True);
end;

class procedure THtml.Reload_After_Delay (ADelayMS : Integer);
var
  LTimer : TWebTimer;
begin
  LTimer          := TWebTimer.Create(nil);
  LTimer.Interval := ADelayMS;
  LTimer.Enabled  := True;
  LTimer.OnTimer  := Do_Reload;
end;

class procedure THtml.Do_Reload (Sender : Tobject);
begin
  TWebTimer (Sender).Free;
  THtml.Reload_Page;
end;

The exception fragment is

Error: Duplicate component name: "divHeading" 
at Object.Create$1 (https://example.com.au/ops-test/ops_1_0_2109.js:3634:23) 
at Object.CreateFmt (https://example.com.au/ops-test/ops_1_0_2109.js:3641:12) 
at c.$create (https://example.com.au/ops-test/ops_1_0_2109.js:366:19) 
at Object.ValidateRename (https://example.com.au/ops-test/ops_1_0_2109.js:15533:188) 
at Object.SetName (https://example.com.au/ops-test/ops_1_0_2109.js:15513:21) 
at Object.SetName (https://example.com.au/ops-test/ops_1_0_2109.js:33680:38) 
at Object.LoadDFMValues (https://example.com.au/ops-test/ops_1_0_2109.js:127837:25) 
at Object.CreateNewForm (https://example.com.au/ops-test/ops_1_0_2109.js:43375:13) 
at Object.DoFormLoad (https://example.com.au/ops-test/ops_1_0_2109.js:43010:12) 
at XMLHttpRequest.cb (https://example.com.au/ops-test/ops_1_0_2109.js:282:28)

How does jspdf transformation matrices work?

I am using transformation matrices with jspdf to change the origin and scaling of my drawings. setCurrentTransformationMatrix has no official documentation from what I found (well, except if “sets the current transformation matrix” counts as one). Matrix, however, has one, that goes something like “Creates a Matrix. In jspdf, matrices are applied to the right, i.e vTransformed = v x M“. It is also mentionned that :

new Matrix(a,b,c,d,e,f) 
<=>
|ab0|
|cd0|
|ef1|

But there seem to be something I just don’t get. For instance, I tried drawing a circle centered at (10.5, 14.85) (on a standard a4 paper) with the following transformation matrix :

let doc = jspdf({ unit: "cm" })
let m = doc.Matrix(1,0,0,1.7,0,0)
doc.setCurrentTransformationMatrix(m)
doc.circle(10.5, 14.85, 1)

I expected the circle’s coordinates to transform as x -> x*1 and y -> y*1.7, and thus have it located at the bottom of the page. However, it actually popped at the top. Taking m = doc.Matrix(1,0,0,0.3,0,0) seemed to yield the correct result, although I’m unable to explain why. Furthermore, there is apparently no such thing as a x-reversal, as that weird behavior only affects the y-axis. Taking f != 0 makes things even more unclear, so I’m also searching for an explanation regarding the role of e and f and how does it combine with a, b, c and d.

Thanks !

Change background text color for canvas [closed]

First of all, I would like to point out that I am using a ready-made script and since it contained too many lines and I did not know where to split it, stackoverflow did not allow me to add it, I had to upload the codes to codepen.

https://codepen.io/Koray-Gen-/pen/YPwpKzJ

What I want to do is change the color of the scrolling text in the background with the button.

<button onclick="draw('green')">Green</button> 

I wonder where I’m doing wrong?

JavaScript WebView on Android, need to be able to detect the virtual keyboard being removed (Cordova App)

I have a Cordova app We Vote Ballot Guide that is having trouble when the Android hide keyboard button is pressed on Android’s navigation bar at the bottom of the screen.

When the virtual keyboard is displayed the Android navigation bar’s ‘backbutton’ (the right most icon), it turns into a down arrow which then is a “virtual keyboard close button”.

I need a way to detect the pressing of the “Android keyboard close button”, or a way to disable it.

My app has its own bottom navigation bar, that I need to hide when the virtual keyboard appears (so that there is enough room left on the screen to see the input field on the underlying page.)

It is easy enough to hide my app’s nav bar when the focus goes to the input field, and restore it when the input field loses focus. The problem is that I can’t find a way to detect if the Android “virtual keyboard close button” has been clicked.

iOS has a keyboardDidHide eventListener which allows me to know when the virtual keyboard goes away, but Android does not seem to have the equivalent.

I tried:

  1. navigator.virtualKeyboard.addEventListener('geometrychange' ()=>{console.log('BUTTONTEST geometry'});, but it was not invoked.

  2. document.addEventListener('keydown', (event) => { console.log('BUTTONTEST keydown: ', JSON.stringify(event)); });, but it did not return useful data.

  3. const hideKeyboardButton = document.getElementById('hideKeyboardButton');, but that element does not exist (at least in Android).

  4. window.addEventListener('keyboardDidHide', console.log('BUTTONTEST keyboardDidHide'));, which only works on iOS.

generating public token via server action and set it on cookies on client component forward by router refresh sometimes not available sever actions

When using Next.js Server Actions to generate a token and then set a cookie on the client, calling router.refresh() immediately after may not always expose the cookie to subsequent server actions or server components.

'use server';

import {cookies} from 'next/headers';
import {defaultLocale} from './constants';

const baseFetch = async ({
  endPoint,
  method = 'GET',
  options = {},
  queryParams = {},
  body,
  url,
  headers = {},
}) => {
  try {
    const appCookies = await cookies();
    const publicToken = appCookies.get('token')?.value;
    const locale = appCookies.get('NEXT_LOCALE')?.value || defaultLocale;

    const queryString = new URLSearchParams(queryParams).toString();
    const fullUrl =
      url ||
      `${process.env.NEXT_PUBLIC_API_URL}${endPoint}${
        queryString ? `?${queryString}` : ''
      }`;

    const response = await fetch(fullUrl, {
      method,
      headers: {
        ...(publicToken && {Authorization: `Bearer ${publicToken}`}),
        'Content-Type': 'application/json',
        'Accept-Language': locale,
        Accept: 'application/json',
        'User-Agent': 'Next.js Server',
        ...headers,
      },
      ...(body && {body: JSON.stringify(body)}),
      cache: 'no-store',
      ...options,
    });

    const text = await response.text();
    let json;
    try {
      json = text ? JSON.parse(text) : null;
    } catch {
      json = {error: text};
    }

    if (!response.ok) {
      return {
        ...json,
        status: response?.status,
        headers: Object.fromEntries(response.headers.entries()),
        endPoint,
      };
    }

    return {
      data: json,
      headers: Object.fromEntries(response.headers.entries()),
    };
  } catch (err) {
    return {
      error: err?.message || 'Unexpected error occurred',
    };
  }
};

export default baseFetch;

'use client';

import {generatePublicToken} from '@/services';
import {setCookie} from 'cookies-next';
import {useEffect, useState} from 'react';
import useRouter from './useRouter';
import useHandleAnalytics from './useHandleAnalytics';
import {useDispatch, useSelector} from 'react-redux';
import {getPublicToken} from '@/selectors/auth';
import {setPublicToken} from '@/slices';
import {ONE_MONTH_IN_SECONDS} from '@/lib';

const useHandlePublicToken = () => {
  const publicToken = useSelector(getPublicToken);
  const [isCreatingPublicToken, setIsCreatingPublicToKen] = useState(false);
  const dispatch = useDispatch();
  const [createPublicTokenError, setIsCreatePublicTokenError] = useState(null);
  const router = useRouter();
  const {logException} = useHandleAnalytics();

  const onCreatePublicToken = async () => {
    setIsCreatingPublicToKen(true);
    setIsCreatePublicTokenError(null);

    const publicTokenRequest = await generatePublicToken();
    if (publicTokenRequest?.data?.access_token) {
      dispatch(setPublicToken(publicTokenRequest?.data?.access_token));
      setCookie('token', publicTokenRequest?.data?.access_token, {
        maxAge: ONE_MONTH_IN_SECONDS,
      });
      router.refresh();
    } else {
      setIsCreatePublicTokenError({
        error: publicTokenRequest?.error || publicTokenRequest?.errors?.[0],
        requestId: publicTokenRequest?.headers?.['x-request-id'],
      });
      logException({
        description:
          publicTokenRequest?.error || publicTokenRequest?.errors?.[0],
        requestId: publicTokenRequest?.headers?.['x-request-id'],
        endpoint: publicTokenRequest?.endPoint,
      });
    }

    setIsCreatingPublicToKen(false);
  };

  useEffect(() => {
    if (!publicToken && !isCreatingPublicToken) {
      onCreatePublicToken();
    }
  }, [publicToken]);

  return {
    isCreatingPublicToken,
    createPublicTokenError,
    onRetry: onCreatePublicToken,
  };
};
export default useHandlePublicToken;

'use server';

import baseFetch from '@/lib/baseFetch';

export const generatePublicToken = async () => {
  const response = await baseFetch({
    endPoint: `oauth/token`,
    method: 'POST',
    body: {
      grant_type: 'client_credentials',
      client_id: process.env.CLIENT_ID,
      client_secret: process.env.CLIENT_SECRET,
    },
  });
  return response;
};


then if this hook called

  useEffect(() => {
    if (
      !cartId &&
      storeId &&
      publicToken &&
      !isCreatingOrder &&
      !creatingOrderError
    ) {
      handleNewOrderCreation();
    }
  }, [cartId, storeId, publicToken, isCreatingOrder]);
  const handleNewOrderCreation = async () => {
    clearOrderCookies();

    const response = await onCreateOrder();
    if (response?.error || response?.errors) {
      logException({
        description: response?.error || response?.errors?.[0],
        requestId: response?.headers?.['x-request-id'],
        endpoint: response?.endPoint,
      });
    } else {
      router.refresh();
    }
  };

  const onCreateOrder = async () => {
    const storeId = getCookie('storeId');
    const tableId = getCookie('tableId');

    setIsCreatingOrder(true);
    setCreatingOrderError(null);
    const storeResponse = await getStore(storeId);

    if (storeResponse?.error || storeResponse?.errors) {
      setCreatingOrderError({
        error: storeResponse?.error || storeResponse?.errors?.[0],
        requestId: storeResponse?.headers?.['x-request-id'],
      });
      setIsCreatingOrder(false);
      return storeResponse;
    }

    const deliveryMethodId =
      storeResponse?.data?.stores?.delivery_methods?.[0]?.id;

    const orderData = {
      store_id: storeId,
      delivery_method_id: deliveryMethodId,
      ...(tableId && {table_id: tableId}),
    };

    const response = await createCart(orderData);

    if (response?.error || response?.errors) {
      setCreatingOrderError({
        error: response?.error || response?.errors?.[0],
        requestId: response?.headers?.['x-request-id'],
      });
      logException({
        description: response?.error || response?.errors?.[0],
        requestId: response?.headers?.['x-request-id'],
        endpoint: response?.endPoint,
      });
    } else {
      setCookie('cartId', response?.data?.orders?.id, {
        maxAge: ONE_MONTH_IN_SECONDS,
      });
      setCookie('cartStoreId', response?.data?.orders?.store?.id, {
        maxAge: ONE_MONTH_IN_SECONDS,
      });
      setCookie('guest_token', response?.data?.orders?.guest_token, {
        maxAge: ONE_MONTH_IN_SECONDS,
      });
    }

    setIsCreatingOrder(false);

    return response;
  };
export const createCart = async body => {
  const response = await baseFetch({
    endPoint: `api/v1/orders/create_cart`,
    method: 'POST',
    body: {...body, source: process.env?.CLIENT_SOURCE},
  });
  return response;
};

so baseFetch when getting token from cookies sometimes it’s undefined for random users

How can I create a RegEx pattern that matches strings in both directions?

So, I have written a RegEx, all by myself. It works quite well, although there is one problem; I cannot figure out how to make that RegEx work both ways. Currently it supports this:

€ 10
€10
EUR 10
EUR10

But I want it to be able to support this:

10€
10 €
10 EUR
10EUR

This is my current RegEx:

const regex = /(?<!w)(?:€s?|EURs?)([0-9]{1,3}(?:[.,s][0-9]{3})*(?:[.,][0-9]+)?|d+(?:[.,]d+)?)(?:s?(?:€|EUR))?(?!w)/g;

How to check if you have multiple nested objects in an object in javascript? [duplicate]

I’m trying to find a way to check if there is another nested object in an object.

const data = {animal: "dog"}

// 2nd layer keys test1: Expected true; Result: false
console.log(Object.keys(data.animal) === "undefined");        

// 2nd layer keys test2: Expected undefined; Result: [ '0', '1', '2' ]
console.log(Object.keys(data.animal));                        

// 2nd layer values test1: Expected true; Result false
console.log(Object.values(data.animal) === "undefined");      

// 2nd layer values test2: Expected undefined; Result [ 'd', 'o', 'g' ]
console.log(Object.values(data.animal));                      

502 Gateway Timeout when generating large Excel reports (60MB+) with ExcelJS and AWS — works for 1 month, fails for 2-3 months range

I’m working on a Node.js + Express backend where I need to generate and download Excel reports from MongoDB using ExcelJS.
When the user selects a large date range (2-3 months) — around 60 MB of Excel data — the server times out with a 502 Gateway Timeout on AWS.

When I select a 1-month range, it works fine.

What I tried:

Initially, my code generated a single Excel file for the entire range:

   downloadReportsExcel: async (req, res) => {
    try {
    req.setTimeout(0); 
    const { from, to } = req.query;
    const fromDate = new Date(from);
    const toDate = new Date(to);

    const reports = await Report.find({
      createdAt: { $gte: fromDate, $lte: toDate },
    }).populate("case reportedBy");

    const workbook = new ExcelJS.stream.xlsx.WorkbookWriter({ stream: res });
    const worksheet = workbook.addWorksheet("Reports");

    worksheet.columns = [
      { header: "CONTRACTOR NAME", key: "contractorName", width: 25 },
      // ...other columns
    ];

    res.setHeader(
      "Content-Disposition",
      `attachment; filename="Reports_${from}_to_${to}.xlsx"`
    );

    for (const report of reports) {
      worksheet.addRow({
        "CONTRACTOR NAME": report.contractorName || "N/A",
        // ...
      }).commit();
    }
    worksheet.commit();
    await workbook.commit();
  } catch (err) {
    console.error(err);
  }
};

✅ This worked for smaller date ranges (1 month),
❌ But failed for larger ranges (2–3 months, ~60MB file) with 502 Gateway Timeout after 2–3 minutes (AWS default limit).

Attempted fix (split into monthly chunks and zip)

To fix it, I tried splitting the range into monthly chunks, generating separate Excel files for each month, and then zipping them together:

    const chunks = getMonthlyChunks(fromDate, toDate);
    const zip = new JSZip();

for (const chunk of chunks) {
  const reports = await Report.find({
    createdAt: { $gte: chunk.start, $lte: chunk.end },
  });

  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet("Reports");

  worksheet.columns = [...];

  for (const report of reports) {
    worksheet.addRow({...});
  }

  const buffer = await workbook.xlsx.writeBuffer();
  const chunkName = `Reports_${chunk.start.toISOString()}_${chunk.end.toISOString()}.xlsx`;
  zip.file(chunkName, buffer);
}

const zipBuffer = await zip.generateAsync({ type: "nodebuffer" });
res.setHeader("Content-Type", "application/zip");
res.setHeader("Content-Disposition", `attachment; filename="Reports.zip"`);
res.send(zipBuffer);

✅ Works locally for 1-month data,
❌ Still times out for 2–3 months on AWS (file ~60 MB, 2–3 min processing).

How do I load multiple folders in one Astro content collection?

I want to make a blog page where it queries all the blogs I have.
Here’s the current file tree of what I’m thinking of doing. The reason I want to have multiple folders is so I can put these posts in a more organized way.

src
├── blog
│   ├── config.ts
│   ├── dist
│   ├── images
│   └── posts
│       ├── 2024
│       │   └── huntress-ctf.mdx
│       └── 2025
│           └── netcomp-ctf.mdx

But when I try to import the collection, it returns this:

The collection "posts" does not exist or is empty. Please check your content config file for errors.
[]

Here’s what my config currently looks like:

import { z, defineCollection } from "astro:content";
import { glob } from "astro/loaders";

const posts = defineCollection({
  loader: glob({ pattern: "{2024,2025}/**/[^_]*.md", base: "./src/blog/posts" }),
  schema: z.object({
    title: z.string(),
    pubDate: z.date(),
    description: z.string(),
    tags: z.array(z.string()),
  }),
});

export const collections = { posts };

And I tried loading my collection like this:

---
import { getCollection } from "astro:content";
import Layout from '../layouts/Layout.astro';

const posts = await getCollection("posts");
console.log(posts);
---

I wonder what I’m doing wrong here, I want to find a workable solution of:

  • Keeping my posts organized in folders
  • Importing my post collection through one collection
  • Side note: I also want my posts to be able to refer to the dist (for file downloads) and images (for optimised images embedded using [alt]() instead of something like <Image>), so I also need to know how to reference them properly in my blog posts through imports/collections because I’m still confused on how to approach this

How do I preserve the colors of an image when I lower its overall opacity to almost transparent? (html javascript) [duplicate]

When I convert an image to almost transparent (1% opacity), either by using imageData or globalAlpha, the original color data is lost in the conversion. When I open up the saved image in any image editing software (I checked and the image editing software is not the problem here) and put it back to full opacity there, I notice that only 16 or 24 colors remain. The image looks like as if it was posterized.

For example, if my image had a color “#90F59A”, after the conversion, the color would now become “#AAFFAA”.

const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;

ctx2.clearRect(0, 0, canvas2.width, canvas2.height);

for (let i = 0; i < data.length; i += 4) {
    const red = data[i];
    const green = data[i + 1];
    const blue = data[i + 2];
    const alpha = data[i + 3];
    if (alpha == 0 || (red == 0 && green == 0 && blue == 0)) {
        // black pixels become fully transparent
        data[i] = 0;     // Red
        data[i + 1] = 0; // Green
        data[i + 2] = 0; // Blue
        data[i + 3] = 0; // Alpha
    } else {
        // all other pixels turn almost transparent
        data[i + 3] = 255 * 0.01;
    }
}
ctx2.putImageData(imageData, 0, 0);

I tried using globalAlpha and found that the quality was reduced. I then tried using imageData because I thought it would preserve the image data since I was modifying the image’s data itself (or the array or color values the image contains), but it also didn’t work.

I also tested if the color quality loss would happen with images that are more opaque (like 80%), and saw that the image quality did not get lower. I also tested with an opacity that is just a bit higher than 1% (like 3%) and saw that there was less reduction in color quality, so I assume the color quality loss was because of some computation with transparent pixels.

I was expecting the image to become almost transparent (1% opacity) but still have the colors be the same.

storybook error: “Cannot read properties of undefined (reading ‘tap’)”

trying to run storybook (v8.6.14) in a next.js 14 project with @storybook/nextjs,
but it keeps breaking on startup with this error:

TypeError: Cannot read properties of undefined (reading 'tap')

stack trace points to:
node_modules/next/dist/compiled/webpack/bundle5.js

looks like storybook is somehow using next’s internal webpack instead of its own.

already tried:

removed all addons (even @storybook/addon-styling-webpack)

cleared cache + reinstalled everything

tried forcing storybook to use its own webpack via @storybook/builder-webpack5 and aliasing webpack

made sure everything’s on webpack 5.101

still same thing, crashes the moment it starts

weird thing is – I had it working few times on another local clone of the same repo, but after working on it for a while, it started happening there also, so weird.. feels like cache problem but I really don’t know why non of the things I have done fixed it

I will appreciate your help 🙂

main.ts:

import type { StorybookConfig } from '@storybook/nextjs'

const config: StorybookConfig = {
  stories: [
    '../ui/**/*.stories.@(js|jsx|mjs|ts|tsx)',
  ],
  addons: [],
  framework: {
    name: '@storybook/nextjs',
    options: {},
  },
  staticDirs: ['../public'],
  docs: {
    autodocs: 'tag',
  },
}
export default config