n8n: Reddit Node Throws

I’m building a workflow in n8n (v1.100.1, Cloud) that reads a list of Reddit posts from a Google Sheet and posts a unique comment to each one in a loop.

The Goal:

The workflow should iterate through each row in my Google Sheet, post the specified comment to the corresponding Post ID, wait for a set period, and then move on to the next row until the list is complete.
The Problem:
The workflow runs successfully for the first item only. I can go to Reddit and see that the comment has been successfully posted. However, the Create a comment in a post node in n8n then throws the following error, which breaks the loop and prevents it from processing the rest of the items:

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

Because the node errors out (even after a successful action), the workflow doesn’t proceed to the Wait node or the next loop iteration.

What I’ve Tried:

Error Handling: Setting the node’s “On Error” setting to “Continue” allows the loop to finish, but it feels like a workaround, not a solution to the underlying error.

Post ID Format: I have confirmed I am using the correct “Fullname” for the Post ID (e.g., 2919299, not the URL or short ID.

Permissions: My Reddit API credentials have the submit, read, and identity scopes. I can post manually from the same account without issue.

My Question:

  • Why would the n8n Reddit node successfully execute its primary function (posting the comment) but then fail to process the successful response from Reddit’s API?
  • What is the correct way to structure this final part of the workflow to ensure the loop completes reliably for all items?
  • What node should I add? What should I set it to?

Workflow & Node Configuration
Here is a simplified overview of the final section of my workflow and the JSON for the relevant nodes.
Visual Overview:

1.). Loop Over Items (SplitInBatches Node)
This node is configured to process each row from the Google Sheet one at a time.
JSON:


{
 "parameters": {
   "batchSize": 1,
   "options": {
     "reset": false
   }
 },
 "name": "Loop Over Items",
 "type": "n8n-nodes-base.splitInBatches",
 "typeVersion": 3,
 "position": [1540, 1960]
}

  1. Get row(s) in sheet (Google Sheets Node)
    This node fetches the list of posts and comments to be made.
    Output Data Example (one item):
    JSON:
[
  {
    "row_number": 6,
    "Comment": "EXAMPLE COMMENT",
    "Post Text": "EXAMPLE POST TEXT",
    "Subreddit": "n8n",
    "Title": "EXAMPLE TITLE",
    "Upvotes": 45,
    "URL": "https://www.reddit.com",
    "ID": "EXAMPLE ID"
  }

  1. Create a comment in a post (Reddit Node) – THIS IS THE FAILING NODE
    This node takes the data for a single row from the loop and attempts to post the comment.
    Node JSON:

{
  "parameters": {
    "resource": "postComment",
    "postId": "={{ $('Loop Over Items').item.json.ID }}",
    "commentText": "={{ $('Loop Over Items').item.json.Comment }}"
  },
  "name": "Create a comment in a post",
  "type": "n8n-nodes-base.reddit",
  "typeVersion": 1,
  "position": [2100, 1980],
  "credentials": {
    "redditlink": {
      "id": "EXAMPLE ID",
      "name": "Reddit account"
    }
  }

  1. Wait Node
    This node is intended to pause the workflow for a set amount of time between each comment to avoid spam filters.
{
  "parameters": {
    "amount": 30,
    "unit": "seconds"
  },
  "name": "Wait",
  "type": "n8n-nodes-base.wait",
  "typeVersion": 1.1,
  "position": [2300, 1980]
}

Error Details
Here is the full error returned by the “Create a comment in a post” node after it has already posted the comment successfully.

{
  "errorMessage": "Cannot read properties of undefined (reading 'things')",
 }

Any insight into why this might be happening or a more robust way to structure this loop would be greatly appreciated. Thank you!

How to correctly work with string like “1.” in parseFloat, because it is user typing input

I have wrong with it how can I fix the parsing string such as “0., 1.”.
It is user typing input but how to handle it correctly, Here is my simple code and return number in onChange

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value

    if (!value) return onChange?.(null)

    if (isValidNumberInput(value)) {
      const parsed = parseFloat(value)

      if (!isNaN(parsed)) onChange?.(value)
    }
  } 

What may prevent Svelecte from rendering suggestions?

I used Svelecte to create autocomplete component to search books like following:

<script>
  import Svelecte, { addFormatter } from 'svelecte';

  let clearable = true;
  let resetOnBlur = true;
  let fetchResetOnBlur = true;
  let valueField = 'id'
  let labelField = 'fulltitle';
  let minQueryValue = 3;
  let value;

  let fetchCallbackData = [];

  const fetchCallback = ( data ) => {
    fetchCallbackData = [...data]; 
    console.log("Fetch callback got", data.length, "items:", data);
    return data;
  }

  function handleChange(e) {
    if ( e.detail !== null ) {
      const selected = e.detail;
      value = null
    }
  }
  
</script>

<Svelecte
  inputId='query'
  {resetOnBlur}
  {fetchResetOnBlur}
  {labelField}
  {valueField}
  {clearable}
  fetchCallback={fetchCallback}
  bind:value
  valueAsObject
  minQuery={minQueryValue}
  multiple={false}
  placeholder="Sisesta pealkiri..."
  fetch="/autocomplete?fragment=[query]"
  on:change={ handleChange }     
>
  <b slot="icon">⌖</b>
</Svelecte>

<h4>List below renders backend result data even Svelecte does not show it:</h4>
<ul>
  {#each fetchCallbackData as item}
    <li>{item.fulltitle} – {item.id}</li>
  {/each}
</ul>

It is bare minimum component for demo purposes, it works like actual component and fails the same way.

As above stated, I query backend at /autocomplete and on backend based on string properties I decide what kind of DB query is needed and response with corresponding data always with the same structure.

For simplicity let’s say I can distinguish 3 types of queries: title, ISBN10 and ISBN13/EAN (I repeat: this logic is in the backend), the frontend has no distinction of query type and it must just render the results responded from the backend.

But somehow

  • it works happily with searching title,
  • it works when ISBN13/EAN results with 1 match
  • it does not work never with ISBN10 queries

If I enter query “Suur Gatsby” (title) or “9985842243” (isbn10 for same title) on both occasion it results with exact same data from server:

[
  {
    "id": 1666,
    "title": "Suur Gatsby",
    "year": 1996,
    "code": "R0001666",
    "barcode": "R0001666",
    "fulltitle": "Suur Gatsby P 1996 Katherine",
    "url": "/pildid/m32/0001/666.gif",
    "price": "6.00",
    "height": 200,
    "width": 127,
    "weight": "0.160",
    "stocklevels": null,
    "position": 1,
    "shelfId": null,
    "some": 2,
    "standardPrice": "6.00",
    "conditionId": 2
  }
]

Problem is: on first occasion (title) Svelecte always renders result as a suggestion for autocomplete, on second (isbn10) there is never any suggestions in Svelecte.

I mentioned that with ISBN13/EAN Svelecte works fine when result has just one match in, but does not when there is more matches.

Considering that on all occasions I get correct data from server and it is rendered correctly as a list below Svelecte-part I can’t figure out, what interferes isbn10 queries (and isbn13 queries with multiple matches) in frontend when there is no distinction for query type in frontend and resulting data from server is exactly same as for title query.

What may prevent Svelecte from rendering suggestions on described occasions?

How to make a simple Hello World server for QUIC connections?

After I add the --origin-to-force-quic-on=localhost:443 argument for the Chrome launcher, all connections (navigation ones included) start to trigger the QUIC endpoint on my server. That’s totally fine for my project’s goals but I cant find any example on how to process such navigation connections. I’m navigating to https://localhost and my Deno server code looks like this:

import SSL from './SSL.js'

const enc=new TextEncoder,
dec=new TextDecoder
for await(const conn of new Deno.QuicEndpoint({port:443}).listen({alpnProtocols:['h2','h3'],...(SSL.default??SSL)})){
    for await(const {writable,readable} of conn.incomingBidirectionalStreams){
        for await(const data of readable) console.log(dec.decode(data))
        const writer=writable.getWriter()
        await writer.write(enc.encode('Hello World!'))
        writer.close()
    }
}

In this code I’m just trying to read everything that Chrome is sending to me and then respond on everything with Hello World!. However it does not work from both ends.


First problem is that I cannot decipher what Chrome is sending to me. Byte arrays that my server is receiving look like this:

Uint8Array(451) [
    1,  65, 192,   0,   0, 209,  80, 134, 160, 228,  29,  19,
  157,   9, 215, 193, 228,  47,   0,  65,  72, 177,  39,  90,
  209, 255, 184, 254, 116, 157,  63, 220,  63, 119, 108,  29,
   82, 127,  63, 125, 224, 254,  94, 254, 126, 148, 254, 111,
   79,  97, 233,  53, 180, 255,  63, 125, 224, 254,  66, 203,
  223, 207, 210, 159, 206,  35, 158, 106,  10, 165, 233, 236,
   61,  37, 254, 126, 251, 193, 252, 133, 151, 191, 159,  47,
    4,  65,  72, 177,  39,  90, 209, 173,  73, 227,  53,   5,
    2,  63,  48,  47,
  ... 351 more items
]

Chrome is sending 3 exactly the same byte arrays and then closing his writable stream. These bytes clearly cannot be translated into Unicode and when new TextDecoder is used upon them – output is gibberish. So what should I do with these byte arrays and what is their purpose?


Second problem is that I do not understand what Chrome is expecting from me in return. I thought that the browser whould wait to recieve an HTML code to draw it on the browser’s screen however when I send an encoded Hello World! and close my writable stream the connection with my server immediately terminates with ERR_QUIC_PROTOCOL_ERROR. So what exactly should I send to the browser in return?

Swiper slider with box shadow

I have a problem with SwiperJS slider – I would like to add for each item a box-shadow.
When I wrap it with swiper CSS classes then I can see that overflow is hidden and crop my shadow.

How can I display whole my box-shadow without cropping by Swiper JS classes?
I need a 30px gap between the arrows and the content.

Here are my demo code:

document.addEventListener("DOMContentLoaded", function() {
  document.querySelectorAll(".comp-gallery").forEach(function(el) {
    const gallerySwiperEl = el.querySelector(".comp-gallery-swiper");

    const gallerySwiperConfig = {
      loop: true,
      slidesPerView: 1,
      spaceBetween: 30,
      navigation: {
        nextEl: el
          .closest(".comp-gallery")
          .querySelector(".pd-slider-arrow--right"),
        prevEl: el
          .closest(".comp-gallery")
          .querySelector(".pd-slider-arrow--left")
      }
    };

    const gallerySwiper = new Swiper(gallerySwiperEl, gallerySwiperConfig);
  });
});
.comp-gallery {
  display: flex;
  align-items: center;
  gap: 30px;
  width: 500px;
}

.comp-gallery-swiper {
  // overflow: visible;
}

.comp-gallery__item {
  box-shadow: 0px 0px 40px 10px rgb(255 0 0 / 0.8);
}

.comp-gallery__image {
  width: 100%;
  border-radius: 22px;
}
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" rel="stylesheet" />
<div class="comp-gallery">
  <button class="pd-slider-arrow pd-slider-arrow--left" aria-label="Previous">
    ←
  </button>
  <div class="comp-gallery-swiper swiper">
    <div class="swiper-wrapper">
      <div class="comp-gallery__item swiper-slide">
        <img class="comp-gallery__image" src="https://placehold.co/600x400/000/fff/png?text=image-1" alt="Image 1" />
      </div>
      <div class="comp-gallery__item swiper-slide">
        <img class="comp-gallery__image" src="https://placehold.co/600x400/00ff00/fff/png?text=image-2" alt="Image 2" />
      </div>
      <div class="comp-gallery__item swiper-slide">
        <img class="comp-gallery__image" src="https://placehold.co/600x400/00ffff/fff/png?text=image-3" alt="Image 3" />
      </div>
    </div>
  </div>


  <button class="pd-slider-arrow pd-slider-arrow--right" aria-label="Next">
    →
  </button>
</div>

PUG template renders page with different scale or size

everyone.

I am trying to render PUG template that I designed from HTML page. The problem is that, probably, the scale of pages is different. For example, body of HTML page is 1536px whereas PUG’s is 1920px. Besides that, I also have different font sizes and relative size of elements. If I save my pug page as html, it looks the same like original one. Probably, something happens when PUG tries to render the template

Original html page’s code is

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Safka Topics</title>
    <link rel="stylesheet" href="style.css">
    <script>
        function closeSendMsg() {
            document.getElementById('overlay').style.display = 'none'
            document.getElementById('send-msg').style.display = 'none'
        }

        function openSendMsg() {
            document.getElementById('overlay').style.display = 'block'
            document.getElementById('send-msg').style.display = 'flex'
        }
    </script>
    <style>
        #send-msg {
            display: none;
            flex-direction: column;
            justify-content: center;
            position: absolute;
            width: 75%;
            height: 75%;
            background-color: var(--msg-details-bg-color);
            align-self: center;
            z-index: 5;
            border-radius: 10px;
            align-items: center;
            justify-content: center;
        }

        #send-msg>label {
            margin: 15px 10px 5px 5px;
        }

        #send-msg > #key-area {
            height: 10%;
        }

        #send-msg > #message-area {
            height: 30%;
        }

        #send-msg > textarea {
            background-color: white;
            margin: 5px 0;
            overflow-y: auto;
            box-sizing: content-box;
            width: 95%;
            resize: none;
        }

        #send-msg > button {
            border-radius: 10px;
            margin-top: 10px;
        }
    </style>
</head>

<body>
    <div class="page-body">
        <div class="menu" style="height:200px">
            <button class="active-btn">Topics</button>
            <button>Brokers</button>
            <button>Consumers</button>
            <button onclick="openSendMsg();">Send message</button>
        </div>
        <div class="content-table">
            <div id="t-head">
                <div class="row">
                    <h3>Topic name</h3>
                </div>
            </div>
            <div id="t-body">
                <div class="row">
                    <p>Topic1</p>
                </div>
                <hr />
                <div class="row">
                    <p>Topic2</p>
                </div>
                <hr />
                <div class="row">
                    <p>Topic3</p>
                </div>
            </div>
        </div>
    </div>
    <label id="overlay" for="send-msg" onclick="closeSendMsg();"></label>
    <div id="send-msg">
        <label for="topic-name">Topic</label>
        <select id="topic-name">
            <option>Topic1</option>
            <option>Topic2</option>
            <option>Topic3</option>
        </select>
        <label for="key-area">Message key</label>
        <textarea id="key-area"></textarea>
        <label for="message-area">Message</label>
        <textarea id="message-area"></textarea>
        <button>Send</button>
    </div>

    <footer>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="M240-240v-480h60v480h-60Zm447-3L453-477l234-234 43 43-191 191 191 191-43 43Z" />
        </svg>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="M561-240 320-481l241-241 43 43-198 198 198 198-43 43Z" />
        </svg>
        <p>1</p>
        <p>2</p>
        <p class="active-page-num">3</p>
        <p>4</p>
        <p>5</p>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="M530-481 332-679l43-43 241 241-241 241-43-43 198-198Z" />
        </svg>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="m272-245-43-43 192-192-192-192 43-43 235 235-235 235Zm388 5v-480h60v480h-60Z" />
        </svg>
    </footer>
</body>

</html>

PUG file looks like this:

doctype html
html(lang='en')
head
  meta(charset="UTF-8")
  meta(name="viewport" content="width=device-width, initial-scale=1.0")
  link(rel="stylesheet" href="/style.css")
  title Topics Page
  style.
        #send-msg {
            display: none;
            flex-direction: column;
            justify-content: center;
            position: absolute;
            width: 75%;
            height: 75%;
            background-color: var(--msg-details-bg-color);
            align-self: center;
            z-index: 5;
            border-radius: 10px;
            align-items: center;
            justify-content: center;
        }

        #send-msg>label {
            margin: 15px 10px 5px 5px;
        }

        #send-msg>#key-area {
            height: 10%;
        }

        #send-msg>#message-area {
            height: 30%;
        }

        #send-msg>textarea {
            background-color: white;
            margin: 5px 0;
            overflow-y: auto;
            box-sizing: content-box;
            width: 95%;
            resize: none;
        }

        #send-msg>button {
            border-radius: 10px;
            margin-top: 10px;
        }

body
    <div class="page-body">
        <div class="menu" style="height:200px">
            <button class="active-btn">Topics</button>
            <button>Brokers</button>
            <button>Consumers</button>
            <button onclick="openSendMsg();">Send message</button>
        </div>
        <div class="content-table">
            <div id="t-head">
                <div class="row">
                    <h3>Topic name</h3>
                </div>
            </div>
            <div id="t-body">
                <div class="row">
                    <p>Topic1</p>
                </div>
                <hr />
                <div class="row">
                    <p>Topic2</p>
                </div>
                <hr />
                <div class="row">
                    <p>Topic3</p>
                </div>
            </div>
        </div>
    </div>
    <label id="overlay" for="send-msg" onclick="closeSendMsg();"></label>
    <div id="send-msg">
        <label for="topic-name">Topic</label>
        <select id="topic-name">
            <option>Topic1</option>
            <option>Topic2</option>
            <option>Topic3</option>
        </select>
        <label for="key-area">Message key</label>
        <textarea id="key-area"></textarea>
        <label for="message-area">Message</label>
        <textarea id="message-area"></textarea>
        <button>Send</button>
    </div>

    <footer>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="M240-240v-480h60v480h-60Zm447-3L453-477l234-234 43 43-191 191 191 191-43 43Z" />
        </svg>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="M561-240 320-481l241-241 43 43-198 198 198 198-43 43Z" />
        </svg>
        <p>1</p>
        <p>2</p>
        <p class="active-page-num">3</p>
        <p>4</p>
        <p>5</p>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="M530-481 332-679l43-43 241 241-241 241-43-43 198-198Z" />
        </svg>
        <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
            <path d="m272-245-43-43 192-192-192-192 43-43 235 235-235 235Zm388 5v-480h60v480h-60Z" />
        </svg>
    </footer>

    script.
        const popup = document.getElementById('produceMsgPopup');
        const popupClose = document.querySelector('.popup-close');
        const produceMsgBtn = document.querySelector('.produceMsgBtn');
        function handleTopicClick(topic) {
            // Send request to backend here
            // Example using fetch API (replace with your actual backend endpoint)
            fetch('/getTopic/' + topic) // Send topic as query parameter
                .then(response => {
                    if (response.redirected) {
                        window.location.href = response.url;
                    }
                })
        }
        function sendMsg() {
            const selectDropdown = document.getElementById("topic-name");
            const selectedTopic = selectDropdown.options[selectDropdown.selectedIndex].text;
            fetch('/api/postMessage',
                {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json"
                    },
                    body: JSON.stringify({
                        "topic": selectedTopic,
                        "message": document.querySelector(".message-area").value
                    })
                }).then(response => {
                    popup.style.display = 'none';
                    document.querySelector(".msgContent").value = "";
                })
        }
        function closeSendMsg() {
            document.getElementById('overlay').style.display = 'none'
            document.getElementById('send-msg').style.display = 'none'
        }
        function openSendMsg() {
            document.getElementById('overlay').style.display = 'block'
            document.getElementById('send-msg').style.display = 'flex'
        }

CSS is below:

head, body {
    margin: 0;
    padding: 0;
    font: caption;
}

:root {
    --main-bg-color: rgb(255, 232, 205);
    --table-head-bg-color: rgb(228, 203, 171);
    --table-body-bg-color: rgb(253, 250, 246);
    --menu-body-bg-color: rgb(179, 179, 179);
    --msg-details-bg-color: rgb(203, 203, 203);
    --menu-btn-bg-color-hover: rgb(58, 58, 58);
}

body {
    background-color: var(--main-bg-color);
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    margin: 0;
    padding: 0;
}

.page-body {
    display: grid;
    grid-template-columns: auto 1200px;
    overflow-y: auto;
    overflow-x: hidden;
    max-height: 100vh;
}

.content-table {
    z-index: 2;
    background-color: var(--list-bg-color);
    display: grid;
    grid-template-rows: auto;
    box-shadow: 7px 1px 19px 0px rgba(66, 68, 91, 1);
    overflow-y: auto;
}

#t-head, #t-body {
    width: 100%;
    box-sizing: border-box;
}

#t-head {
    background-color: var(--table-head-bg-color);
    border-bottom: 1px solid #735e39;
}

#t-body {
    background-color: var(--table-body-bg-color);
    overflow-y: auto;
    max-height: 100%;
}

.row {
    grid-template-columns: 1fr 1fr 2fr;
    display: grid;
    text-align: left;
    box-sizing: border-box;
    overflow-y: hidden;
    padding-left: 10px;
}

.row > * {
    height: 25px;
}

#t-body > .row:hover {
    background-color: rgb(176, 176, 176);
    transition: 500ms ease;
}

.menu {
    z-index: 1;
    top: 0;
    position: sticky;
    align-self: start;
    display: inline-block;
    display: grid;
    grid-template-columns: auto;
    background-color: var(--menu-body-bg-color);
    align-self: stretch;
    border-radius: 0 0 10px 10px;
    box-shadow: 0px 5px 10px 1px rgba(66, 68, 91, 0.546);
}

.menu > button {
    background-image: linear-gradient(to right, rgb(239, 239, 239) 65%, rgb(197, 197, 197) 100%, black 180%);
    text-align: left;
    border: 0;
    transition: 500ms ease;
}

.menu > .active-btn {
    color: rgb(255, 241, 204);
    background-image: linear-gradient(to right, rgb(72, 72, 72) 65%, rgb(197, 197, 197) 100%, rgb(239, 239, 239) 180%);
    text-align: left;
    border: 0;
    transition: 500ms ease;
}

.menu > :not(.active-btn):hover {
    text-align: left;
    border: 0;
    background-color: var(--menu-btn-bg-color-hover);
    background-image: none;
    color: rgb(255, 241, 204);
    transition: 500ms ease;
}

.menu > button:last-child {
    border-radius: 0 0 10px 10px;
}

#msg-details {
    display: none;
    flex-direction: column;
    justify-content: center;
    position: absolute;
    width: 75%;
    height: 75%;
    background-color: var(--msg-details-bg-color);
    align-self: center;
    z-index: 5;
    border-radius: 10px;
}

#msg-details > label {
    margin: 20px 10px 5px 5px;
}

#msg-details > div {
    background-color: white;
    padding: 5px;
    margin: 5px 0;
    max-height: 20%;
    overflow-y: auto;
}

#overlay {
    display: none;
    position: absolute;
    opacity: 50%;
    width: 100%;
    height: 100%;
    background-color: black;
    align-self: center;
    z-index: 4;
}

button {
    font: caption;
}

footer {
    background-color: rgb(56, 103, 154); 
    display: flex;
    align-items: center;
    justify-content: center;
    align-content: center;
    flex-wrap: wrap;
    width: 100%;
    margin-top: auto;
}

.active-page-num {
    color: white;
    font-size: 1.5rem;
}

footer > p {
    margin: 0 10px;
    transition: 500ms ease;
    text-align: center;
    vertical-align: middle;
    box-sizing: border-box;
}

footer > p:not(.active-page-num):hover {
    font-size: 1.2rem;
    color:rgb(255, 216, 148);
    transition: 500ms ease;
}

Also, as I am using Express backend application which uses NPM manager, I have also added support for “public” dependency to make my PUG render with style.css

app.use(express.static('public', {
  setHeaders: (res, path) => {
    if (path.endsWith('.css')) {
      res.setHeader('Content-Type', 'text/css');
    }
  }
}));

Thank you for help

Event handling in JS, a Pattern, that seems pretty unknown [closed]

I’ve written a JS class to handle Events. It is based on the native handleEvent interface, a interface, i use for over 10 years. When i started using it, i was surprised, that it makes everything so easy, and wondered why i didn’t see it used far more widely? My conclusion since then was, well, seems a unreliable thing, that’s why no one is using it. But because it made things so easy, i didn’t bother and used it for everything.

I have never tried, to make it a reusable package, maybe because i thought it’s so unusual. Now, with all our Programming-Champs like Claude, i thought, why not. Let’s make it a package, and if it’s only for me. While we had developed that tool, it felt, that Claude didn’t understand handleEvent, so i searched the Web. But not that much there, except a few articles. An older Article made it easier for Claude to grasp its mind around that interface.

And after letting our Programming-Champs (DeepSeek, Grok, ChatGPT) reviewing the package. Turns out, not even they knew exactly what this class is doing there. Reviews weren’t to harsh, but they didn’t get it. After pointing out, what handleEvent is doing, they declared it is as a paradigm shift incoming. And now i’m more curious than ever, is there a secret knowledge, why nobody uses it?

The repo is on GitHUB.

How do you annotate a function in JSDoc that accepts a class as a parameter and an instance as the return type?

I have a component architecture in a vanilla Javascript project, and it would be nice to easily query the component collection for a particular subclass and get a return value of the same type (or null if not found). A simplified example:

class Component { /* ... */ }
class MyComponent extends Component { /* ... */ }

function findComponent(cls) {
    // searches an array of components and returns the first component that is
    // instanceof cls, or null if not found
}

let comp = findComponent(MyComponent);
// comp is of type MyComponent or null

I want to comment the function with JSdoc so VS Code understands that the class cls I pass in and the optional returned instance are the same class.

let foo = findComponent(FooComponent);  // VS Code knows foo is type {FooComponent|null}
let bar = findComponent(BarComponent);  // VS code knows bar is type {BarComponent|null}

The most obvious solution to me would be something like this:

/**
 * @template {Component} C
 * @param {typeof C} cls
 * @returns {?C}
 */
function findComponent(cls) {}

But the “C” in typeof C is underlined with the error

'C' only refers to a type, but is being used as a value here.ts(2693)

So typeof doesn’t seem to work with templates, at least to Intellisense.

I also tried @param {C.constructor} cls I saw somewhere, but that complains with

Cannot access 'C.constructor' because 'C' is a type, but not a namespace. Did you mean to retrieve the type of the property 'constructor' in 'C' with 'C["constructor"]'?ts(2713).

The “did you mean” suggestion leads to a different error,

Type '"constructor"' cannot be used to index type 'C'.ts(2536).

As a sanity check of my understanding of the typeof modifier, I tried this and it does work as expected with a concrete type, but the return type isn’t specific so it isn’t quite what I was aiming for.

/**
 * @param {typeof Component} cls
 * @returns {?Component}
 */
function findComponent(cls) {}

let foo = findComponent(MyComponent);
// foo is of type Component or null

Is this possible within JSdoc in a way VS Code understands or do I have to force cast the result every time?

3d styling on website using html css javascript [closed]

how I can style a card for a website that contain like

      Previous Card   Next Card
              main card

the main card is visible and the pre and next are bluer and when the user press on next or pre the card like flipping to take the main card note : the previous and next card like be the half visible with the bluer and anyone help me ??

DynamoDB returning empty between two dates

I have this table that has this line on it as you can see below:

id,"data_dia","nome_completo","nome_produto","nome_tuna","numero_socio","preco_quantidade","quantidade","tipo","valor_conta","valor_pagamento"
compra_pagamento,"2024-11-09T01:26:57.748Z","","chupa chups","joker","177","0.4","1","compra","'-0.40","null"

As I run this code the table returns the line properly

const params = {
      TableName: 'HISTORICO-teste',
      KeyConditionExpression: 'id = :id AND data_dia BETWEEN :data_inicial AND :data_final',
      ScanIndexForward: false,
      FilterExpression: '#nome_tuna = :nome_tuna',
      ExpressionAttributeNames: { '#nome_tuna': 'nome_tuna' },
      ExpressionAttributeValues: {
          ':data_inicial': '2024-08-07T00:00:00.000Z',
          ':data_final':   '2025-07-08T23:59:59.999Z',
          ':nome_tuna': 'joker',
          ':id': 'compra_pagamento'
      }
    }

await dynamo.query(params).then(result => {
  console.log(result.Items);
});

But if I change the code to reflect a data greater then the one above it doesn’t return the line
soo if for example, I change the
':data_final': '2025-07-08T23:59:59.999Z'
to
':data_final': '2025-07-09T23:59:59.999Z'
it returns nothing as you can see below:

START RequestId: b1c332c2-1216-4ed4-ba8a-bbbfa49ed3f2 Version: $LATEST
2025-07-15T17:00:39.393Z    b1c332c2-1216-4ed4-ba8a-bbbfa49ed3f2    INFO    []
END RequestId: b1c332c2-1216-4ed4-ba8a-bbbfa49ed3f2
REPORT RequestId: b1c332c2-1216-4ed4-ba8a-bbbfa49ed3f2  Duration: 108.83 ms Billed Duration: 109 ms Memory Size: 2000 MB    Max Memory Used: 90 MB  Init Duration: 376.07 ms

another bit of information, I have a bunch of others lines of data almost everyday from the date 2024-08-07T00:00:00.000Z to now

Bootstrap card not showing when value is 0 using JavaScript

I am trying to display a Bootstrap card only when the input value is greater than 0.

If the value is 0 or less, the card should be hidden and a warning should show instead.
Here is the HTML and JavaScript I used, but the logic doesn’t seem to be working correctly.

Can someone help me spot the problem?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Card Visibility</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <style>
        .card-counter {
            box-shadow: 2px 2px 10px #dadada;
            margin-top: 20px;
            padding: 20px;
            background-color: #ffffff;
            border-left: 5px solid #28a745;
            display: none;
            max-width: 400px;
        }
    </style>
</head>
<body>

    <input type="number" id="myValue" class="form-control w-25 mb-3" placeholder="Enter value" />
    <button onclick="checkValue()" class="btn btn-success">Check</button>

    <div id="myCard" class="card card-counter">
        <div class="card-body">
            <h5 class="card-title">✔ Value is greater than 0</h5>
        </div>
    </div>

    <div id="warning" class="alert alert-warning mt-3 w-50" style="display: none;">
        ❗ Value is 0 or less. Card will not show.
    </div>

    <script>
        function checkValue() {
            const value = parseFloat(document.getElementById("myValue").value);
            const card = document.getElementById("myCard");
            const warning = document.getElementById("warning");

            if (value > 0) {
                card.style.display = "block";
                warning.style.display = "none";
            } else {
                card.style.display = "none";
                warning.style.display = "block";
            }
        }
    </script>

</body>
</html>

PLEASE HELP ME WITH THIS PHP MAIL TLS ERROR [closed]

2025-07-15 16:17:22 SERVER -> CLIENT: 220 smtp.gmail.com ESMTP 41be03b00d2f7-b3bbe728532sm12105356a12.69 – gsmtp
2025-07-15 16:17:22 CLIENT -> SERVER: EHLO localhost
2025-07-15 16:17:22 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [103.214.61.50]250-SIZE 36700160250-8BITMIME250-STARTTLS250-ENHANCEDSTATUSCODES250-PIPELINING250 SMTPUTF8
2025-07-15 16:17:22 CLIENT -> SERVER: STARTTLS
2025-07-15 16:17:23 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
SMTP Error: Could not connect to SMTP host.
2025-07-15 16:17:23 CLIENT -> SERVER: QUIT
2025-07-15 16:17:23 SERVER -> CLIENT:
2025-07-15 16:17:23 SMTP ERROR: QUIT command failed:
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

PHPMailer Error: SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

Error sending message! Please try again.

Puppeteer can’t access var doc in javascript

I am trying to scrape a web page using puppeteer, however, I can’t access var doc with puppeteer. Although I can see it in the source page of my web browser

var rows = [];
var i = 1;
/*  while(i <= 1476)*/

var doc = {
    rowNum:1,
    userId: "<span style="text-decoration:underline; color: #FF0000;" onclick=tezDetay('Q_Q4obyTBjEPFWaHVCPv0A','BGUg8yaU7zJvXGxQQkpxXA')>933777</span>",
    name: "ÖZKAN EDEN", 
    age: "2025",
    weight: "Investigating the effectiveness of an AI-feedback tool in enhancing EFL writing skills and students' perceptions towards ai-feedback<br><span style='font-style: italic';>Yapay zeka geri bildirim aracının yabancı dil yazma becerilerini geliştirmedeki etkinliğinin ve öğrencilerin yapay zeka geri bildirimine yönelik algılarının incelenmesi</span>",
};

I can access until /* while(i <= 1476)*/ but the var doc is invisible with puppeteer. I tried using BeatifulSoup and Selenium, but still can’t access the var doc. Here’s my code:

const puppeteer = require('puppeteer');
const fs = require('fs'); // For saving output

async function scrapeTezData(keyword = "yapay zeka") {
    let browser;
    try {
        browser = await puppeteer.launch({
            headless: true, // Set to false to see the browser
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });
        const page = await browser.newPage();

        await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
        await page.setViewport({ width: 1280, height: 800 });
    
        });

        console.log("Waiting for page content to load and JS to execute...");
        await new Promise(resolve => setTimeout(resolve, 5000)); // Arbitrary wait

        // Extract script content from the page
        const scriptData = await page.evaluate(() => {
            const scripts = Array.from(document.querySelectorAll('script[type="text/javascript"]'));
            let docBlocks = [];

            scripts.forEach(script => {
                const content = script.innerHTML;
                if (content.includes('var doc =') && content.includes('var rows = []')) {
                    const docBlockPattern = /var doc = {[^}]*};/g;
                    const matches = content.match(docBlockPattern);
                    if (matches) {
                        docBlocks = docBlocks.concat(matches);
                    }
                }
            });
            return docBlocks;
        });


    } catch (error) {
        console.error(`Scraping failed: ${error.message}`);
    } finally {
        if (browser) {
            await browser.close();
        }
    }
}

Any help is appreciated as I’m new in web scraping. Thanks!

I tried BeautifulSoup with different scrapers and Selenium, and still can’t access the var doc.

MediaRecorder record screen with audio in seperated webm files and play in sequence goes wrong when there is no movement in videos

I want to record my whole screen with audio in Chrome using MediaRecorder and getDisplayMedia and i want to have multiple 2 seconds video files (each 2 seconds, 1 new video file (.webm))
and because i need a new .webm file each 2 seconds, i have a new MediaRecorder each 2 seconds so i have list of .webm videos (each one 2 seconds).
In recording, everything is just fine ! I record multiple .webm content (blob) each 2 seconds and store them in an blobs array named videos

But what i want is to play this videos blobs (each is a .webm blob with its own header) in row like it is a single video file. So i decided to create a video element and by stopping the record and getting some .webm independed blobs, a MediaSource opens and the first video blob append to its sourceBuffer and this appending continues until the last video blob appended.

This too correct to me and also works !!! but the problem is that there must be too many activity in each recorded video (mouse movements, a playing video or …) otherwise the playback goes to waiting status !!!!! Yes !!!! If any of this recorded videos has no activity like mouse movement, when the time reaches to that video (video with no movement recorded in it), puts the player to waiting status !!!!!!!

You can run this code and start recording (select fullscreen + audio) and wait for 7-8 seconds then click stop, the recorded videos (each is 2 seconds) starts to play in the player (video element).

If you keep anything silence (no movement or anything playing during the records), in playback, between videos you find some loading on the player and player status goes to waiting !!!! but if there is any movement in your videos, the player plays all video in sequence just fine !!!!!!!!!!!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .button { background: #e4e5e7; color: #030712; font-weight: bold; padding: 10px 20px; display: inline-block }
    </style>
</head>
<body>

<h2 class="button" onclick="doStart()">Start</h2>
<h2 class="button" id="button_stop" onclick="doStop()">Stop</h2>
<h4>Playback, once clicked on Stop</h4>
<video id="video-player" autoplay controls style="max-width: 1000px"></video>

<script>
    const eVideoPlayer = document.getElementById("video-player"),
        mimeType = 'video/webm; codecs="vp8, opus"'

    let videos = [], iv, stream1

    function record(stream) {
        const mediaRecorder = new MediaRecorder(stream, {
            mimeType: mimeType,
            videoBitsPerSecond: 60000000
        })

        let video

        mediaRecorder.ondataavailable = async (ev) => {

            console.log("data ready")
            videos.push(ev.data)
        }
        setTimeout(() => mediaRecorder.stop(), 2000)
        mediaRecorder.start()
    }

    function doStart() {
        navigator.mediaDevices.getDisplayMedia({
            video: true,
            audio: true
        }).then(stream => {
            stream1 = stream
            iv = setInterval(() => record(stream), 2000)
        })
    }

    async function doStop() {
        clearInterval(iv)
        stream1.getTracks().forEach(track => track.stop())

        let sourceBuffer, mediaSource = new MediaSource()

        eVideoPlayer.onwaiting = () => console.log("waiting")

        let counter = 1
        mediaSource.onsourceopen = async () => {
            sourceBuffer = mediaSource.addSourceBuffer(mimeType)
            sourceBuffer.mode = "sequence"
            sourceBuffer.onupdateend = async () => {
                if(eVideoPlayer.paused) {
                    eVideoPlayer.play()
                }
                if(counter < videos.length) {
                    sourceBuffer.appendBuffer(await videos[counter++].arrayBuffer())
                }
            }
            sourceBuffer.appendBuffer(await videos[0].arrayBuffer())
        }
        eVideoPlayer.src = URL.createObjectURL(mediaSource)
    }

</script>
</body>
</html>