How to setup MySQL?

How to setup MySQL?
I would like to setup MySQL so that I can start investigating the source code. Ideally I would like to be able to compile and run MySQL so that I can use the debugger to step through the code.

Next JS: Getting 404 when for POST api on production env while local same api working

I have usecase in the next JS app for sending the mails, while it is working in the local environment, the same api is throwing 404 on the production app. I am not able to debug as well. It’s an POST API.

import nodemailer from "nodemailer";

export async function POST(req) {
  const { name, email, subject, message } = await req.json();

  const transporter = nodemailer.createTransport({
    service: "gmail",
    auth: {
      user: process.env.EMAIL_USER,
      pass: process.env.EMAIL_APP_PASS,
    },
  });

  try {
    await transporter.sendMail(mailOptions);
    return new Response("Email sent successfully", { status: 200 });
  } catch (error) {
    console.error("Failed to send email:", error.message);
    return new Response("Failed to send email", { status: 500 });
  }
}

and I am calling this POST api on a event click

const handleSubmit = async (e) => {
e.preventDefault();

const response = await fetch("/sendMail", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify(connect),
});

if (response.ok) {
  alert("Message sent successfully!");
  setConnect({ name: "", email: "", subject: "", message: "" });
} else {
  alert("Failed to send the message, please try again.");
}

};

enter image description here

Cyber dialogue analysis index peg

Thl This man needs some therapy man he’s been through it and I think he’s not.

This guy needs some therapy man he’s not good. The only person in our league that’s got that type mentality would probably be. If the other teams have to win to.

Chrome doesn’t keep history of a page that redirects prior to user interaction

I’m looking for info on a browser quirk and a possible workaround:

Navigating to a new page using any of the various methods which push the new URL onto the history stack…

  • window.location = '...'
  • window.location.assign('...')
  • pushState({},"",'...')
  • document.querySelector('a[href=...]').click()
  • etc.

…will subsequently allow the user to return to the previous website / state with the back button — but only if the user “interacted” with the page while that state was rendered on screen.

In other words, any page which redirects to a new page before the user has interacted will be prevented from appearing in the browser’s history. This prevents the user from using the back button to revisit it, as well as prevents history.go(-1) from working as expected. It’s like that page never existed — and only because the user didn’t interact with it.

In some cases, the browser will behave this way even if the user did interact with it. In such cases, if a JavaScript navigation were then to occur, the back button would take the user back even before the page they interacted with.

I set up a test page on w3schools’s code spaces to demo this. On the first visit of the link, the site shows a message with a Continue button asking you to confirm you are viewing user-generated content. If you click the button, and then allow the site to load and redirect you (to example.com) without clicking again, your browser’s back button will take you here to StackOverflow, which is decidedly prior to the page with the button you clicked on. On subsequent visits to the link you can play with clicking vs. not clicking somewhere on the page to experience the quirk.

The demo page contains this line of code which performs the redirect:

setTimeout( ()=> location = 'http://example.com' , 8000 );

Mouseover events are not considered a user action. Neither are scroll events. You have to click, tap, or press a key. Note that the interaction doesn’t necessarily have to be with the page directly — it can also be with a bookmarketlet that runs some JavaScript in the page context, or it can be an interaction with an open DevTools window attached to the page.

There is no time limit either. If you visit a webpage that has a scrolling news feed which you were reading for hours (without clicking) and then a JS event caused a new page to load, you cannot return to the page you were reading.

Firefox does not exhibit this behavior, but, as far as I can tell, all Chromium browsers do.

Where is this behavior documented?

Is there a workaround?

Note: I’ve come across this 15-year-old question which seems to address a similar legacy issue and makes no mention of the “user interaction” component of the problem. The answers suggest that a dynamically generated hidden form submission is a potential workaround. I have found that this approach does not help.


Elaboration on my use case:
I don’t have a good example of this causing real issues “in the wild” but I do have extensive experience with this issue appearing with my Tampermonkey user scripts. Let’s try a short thought experiment: Say you are searching for something on Amazon, and the query returns 50 pages of results. Say you wanted to create a simple user script that called click() on the “next page” nav button using setTimeout() with a delay of 6 seconds. Say you wanted to occasionally scroll down the items list as your script automatically runs through each page of the results. Say you eventually found something interesting — but right before you can click it (or interact), the script triggers a navigation to the next page. If you then press the back button, you are returned all the way back to the beginning — that is, the last page you had clicked on (interacted with), which is likely the first page of the results. Pressing the forward button takes you back to the page that is subsequent to the page with the item you were interested in. There is no history state for any page in between. Now admittedly, in this example you could disable your script and use the on-page navigation buttons to go back one page in the results, then re-scroll to the spot where the interesting item was. But if instead you were storing a list of URLs in localStorage that you cycled through with a stored index value that incremented each execution. In such case, there is no on-page navigation that will bring you back.

How to Resolve Unexpected Token and EOF Errors in React JSX Return Block of a Profile Component?

Hello I am working on creating a profile page, and keep getting this persistent syntax error in line 381 and I can’t figure out how to fix it. If its an easy fix could someone take a look at it tell me what is wrong? I’ve included the entire file even though the error is a the very end, i dont know if there’s a larger structural problem here. Thank you in advance.

import { useEffect, useState, useRef } from 'react';
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
);

export default function ProfilePage() {
  const [user, setUser] = useState(null);
  const [profile, setProfile] = useState({ full_name: '', role: '', bio: '', location: '', avatar_url: '', banner_url: '' });
  const [bannerFile, setBannerFile] = useState(null);
  const [bannerPreviewUrl, setBannerPreviewUrl] = useState(null);
  const bannerInputRef = useRef(null);
  const [avatarFile, setAvatarFile] = useState(null);
  const [previewUrl, setPreviewUrl] = useState(null);
  const [loading, setLoading] = useState(false);
  const [success, setSuccess] = useState(false);
  const fileInputRef = useRef(null);
  const [isEditing, setIsEditing] = useState(true);

  useEffect(() => {
    supabase.auth.getSession().then(({ data: { session } }) => {
      const currentUser = session?.user;
      setUser(currentUser);
      if (currentUser) fetchProfile(currentUser.id);
    });

    supabase.auth.onAuthStateChange((_event, session) => {
      const currentUser = session?.user;
      setUser(currentUser);
      if (currentUser) fetchProfile(currentUser.id);
    });
  }, []);

  const fetchProfile = async (id) => {
    setLoading(true);
    const { data } = await supabase.from('users').select('*').eq('id', id).single();
    if (data) {
      setProfile({
        full_name: data.full_name || '',
        role: data.role || '',
        bio: data.bio || '',
        location: data.location || '',
        avatar_url: data.avatar_url || '',
        banner_url: data.banner_url || ''
      });
    }
    setLoading(false);
  };

  const handleFileChange = (e) => {
    const file = e.target.files[0];
    if (file) {
      setAvatarFile(file);
      setPreviewUrl(URL.createObjectURL(file));
    }
  };

  const handleChange = (e) => {
    const { name, value } = e.target;
    setProfile((prevProfile) => ({
      ...prevProfile,
      [name]: value,
    }));
  };

  const uploadAvatar = async () => {
    if (!avatarFile || !user) return;
    
    const cleanFileName = avatarFile.name.replace(/s+/g, '_'); // replaces spaces with underscores
    const filePath = `${user.id}/${cleanFileName}`;
    
    console.log("Uploading file to path:", filePath);
    console.log("User ID at upload:", user?.id);
    const { error: uploadError } = await supabase.storage
         .from('avatars')
         .upload(filePath, avatarFile, { upsert: true });

    if (uploadError) {
      console.error('Upload failed:', uploadError.message);
      return null;
    }

    const { data: urlData } = supabase.storage.from('avatars').getPublicUrl(filePath);
    return urlData.publicUrl;
  };

  const uploadBanner = async () => {
    if (!bannerFile || !user) return;

    const cleanFileName = bannerFile.name.replace(/s+/g, '_');
    const filePath = `${user.id}/banner_${cleanFileName}`;

    const { error: uploadError } = await supabase.storage
      .from('avatars')
      .upload(filePath, bannerFile, { upsert: true });

    if (uploadError) {
      console.error('Banner upload failed:', uploadError.message);
      return null;
    }

    const { data: urlData } = supabase.storage.from('avatars').getPublicUrl(filePath);
    return urlData.publicUrl;
  };

  const saveProfile = async () => {
    if (!user) return;
    setLoading(true);
    setSuccess(false);

    let avatarUrl = profile.avatar_url;
    if (avatarFile) {
      const uploadedUrl = await uploadAvatar();
      if (uploadedUrl) avatarUrl = uploadedUrl;
    }

    let bannerUrl = profile.banner_url || '';
    if (bannerFile) {
      const uploadedBanner = await uploadBanner();
      if (uploadedBanner) bannerUrl = uploadedBanner;
    }

    const updates = {
      id: user.id,
      full_name: profile.full_name,
      role: profile.role,
      bio: profile.bio,
      location: profile.location,
      avatar_url: avatarUrl,
      banner_url: bannerUrl,
      updated_at: new Date(),
    };

    console.log("Sending to Supabase:", updates);
    const { error } = await supabase.from('users').upsert(updates);
    if (!error) {
      setSuccess(true);
      setProfile((prev) => ({
        ...prev,
        avatar_url: avatarUrl,
        banner_url: bannerUrl
      }));
      setIsEditing(false);
    } else {
      console.error("Failed to save:", error.message);
    }

    setLoading(false);
  };

  return (
    <div className="min-h-screen bg-gradient-to-br from-white to-gray-100 flex flex-col items-center justify-start px-4 text-center">
      {bannerPreviewUrl || profile.banner_url ? (
        <img
          src={bannerPreviewUrl || profile.banner_url}
          alt="Banner"
          className="w-full max-w-4xl h-[150px] object-cover rounded-md shadow-sm mb-6"
        />
      ) : null}
      {isEditing && (
        <div className="relative w-full max-w-4xl flex flex-col items-center -mt-14 z-10">
          {previewUrl || profile.avatar_url ? (
            <img
              src={previewUrl || profile.avatar_url}
              alt="Avatar"
              className="rounded-full shadow-lg border-4 border-white object-cover"
              style={{ width: "120px", height: "120px", marginTop: "-120px" }}
            />
          ) : null}
        </div>
      )}
      <div className="w-full max-w-4xl bg-white rounded-2xl shadow-xl p-8 space-y-6 overflow-visible relative">
        <div className="absolute -top-10 -left-10 w-40 h-40 bg-purple-300 rounded-full opacity-30 filter blur-3xl animate-pulse"></div>
        <div className="absolute -bottom-10 -right-10 w-40 h-40 bg-yellow-200 rounded-full opacity-20 filter blur-2xl animate-pulse"></div>


        {!user ? (
          <p className="text-gray-600">Please sign in to view your profile.</p>
        ) : (
          <>
            {isEditing ? (
              <form className="w-full max-w-md mx-auto text-left space-y-6">
                <div>
                  <label className="block text-sm font-semibold text-gray-600 mb-1 tracking-wide">Full Name</label>
                  <input
                    type="text"
                    name="full_name"
                    value={profile.full_name}
                    onChange={handleChange}
                    placeholder="e.g. Maya Lin"
                    className="w-full px-4 py-2 rounded-lg bg-white/90 border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-300 transition"
                  />
                </div>

                <div>
                  <label className="block text-sm font-semibold text-gray-600 mb-1 tracking-wide">Role</label>
                  <select
                    name="role"
                    value={profile.role}
                    onChange={handleChange}
                    className="w-full px-4 py-2 rounded-lg bg-white/90 border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-300 transition"
                  >
                    <option value="">Select Role</option>
                    <option value="Artist">Artist</option>
                    <option value="Investor">Investor</option>
                    <option value="Gallery">Gallery</option>
                  </select>
                </div>

                <div>
                  <label className="block text-sm font-semibold text-gray-600 mb-1 tracking-wide">Bio</label>
                  <textarea
                    name="bio"
                    value={profile.bio}
                    onChange={handleChange}
                    rows={3}
                    maxLength={1000}
                    placeholder="Tell us about yourself"
                    className="w-full px-4 py-2 rounded-lg bg-white/90 border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-300 transition"
                  />
                  <div className="text-sm text-right mt-1">
                    <span className={`${profile.bio.length >= 1000 ? 'text-red-500' : 'text-gray-500'}`}>
                      {profile.bio.length} / 1000 characters
                    </span>
                  </div>
                </div>

                <div>
                  <label className="block text-sm font-semibold text-gray-600 mb-1 tracking-wide">Location</label>
                  <input
                    type="text"
                    name="location"
                    value={profile.location}
                    onChange={handleChange}
                    placeholder="e.g. Los Angeles, CA"
                    className="w-full px-4 py-2 rounded-lg bg-white/90 border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-300 transition"
                  />
                </div>

                <div className="w-full max-w-md mx-auto mt-6">
                  <label className="block text-sm font-semibold text-gray-600 mb-2 tracking-wide">
                    Upload New Avatar
                  </label>
                  <div
                    onClick={() => fileInputRef.current?.click()}
                    onDragOver={(e) => e.preventDefault()}
                    onDrop={(e) => {
                      e.preventDefault();
                      const file = e.dataTransfer.files[0];
                      if (file) {
                        setAvatarFile(file);
                        setPreviewUrl(URL.createObjectURL(file));
                      }
                    }}
                    className="w-full border-2 border-dashed border-gray-300 rounded-lg px-6 py-4 text-sm text-gray-500 text-center hover:bg-gray-50 transition cursor-pointer"
                  >
                    Drag and drop an image, or click to browse
                  </div>
                  <input
                    type="file"
                    accept="image/*"
                    ref={fileInputRef}
                    onChange={handleFileChange}
                    className="hidden"
                  />
                </div>

                <div className="w-full max-w-md mx-auto mt-6">
                  <label className="block text-sm font-semibold text-gray-600 mb-2 tracking-wide">
                    Upload Banner Image
                  </label>
                  <div
                    onClick={() => bannerInputRef.current?.click()}
                    onDragOver={(e) => e.preventDefault()}
                    onDrop={(e) => {
                      e.preventDefault();
                      const file = e.dataTransfer.files[0];
                      if (file) {
                        setBannerFile(file);
                        setBannerPreviewUrl(URL.createObjectURL(file));
                      }
                    }}
                    className="w-full border-2 border-dashed border-gray-300 rounded-lg px-6 py-4 text-sm text-gray-500 text-center hover:bg-gray-50 transition cursor-pointer"
                  >
                    Drag and drop a banner image, or click to browse
                  </div>
                  <input
                    type="file"
                    accept="image/*"
                    ref={bannerInputRef}
                    onChange={(e) => {
                      const file = e.target.files[0];
                      if (file) {
                        setBannerFile(file);
                        setBannerPreviewUrl(URL.createObjectURL(file));
                      }
                    }}
                    className="hidden"
                  />
                </div>
                <div className="flex justify-center mt-8">
                  <button
                    type="button"
                    onClick={saveProfile}
                    className="px-6 py-2 bg-indigo-600 text-white font-semibold rounded-full shadow-lg transition duration-300 ease-in-out hover:bg-indigo-700 hover:scale-105"
                  >
                    Save Profile
                  </button>
                </div>
              </form>
            ) : (
              <div className="w-full max-w-4xl bg-white rounded-2xl shadow-xl p-8 space-y-6">
                <div className="flex items-center justify-between mt-12">
                  <div className="flex items-center space-x-6" style={{ position: "relative", zIndex: 50 }}>
                    {profile.avatar_url && (
                      <div className="relative" style={{ zIndex: 1000 }}>
                        <img
                          src={profile.avatar_url}
                          alt="Avatar"
                          className="rounded-full border-2 border-gray-300 object-cover"
                          style={{
                            width: "140px",
                            height: "140px",
                            position: "absolute",
                            top: "-100px",
                            left: "40px",
                            zIndex: 1000
                          }}
                        />
                      </div>
                    )}
                    <div className="ml-[220px] -mt-10 space-y-2">
                      <div className="flex items-center justify-start ml-6 space-x-20">
                        <h1 className="text-2xl font-bold text-gray-900">{profile.full_name}</h1>
                        <button
                          onClick={() => setIsEditing(true)}
                          className="px-6 py-2 bg-indigo-600 text-white font-semibold rounded-full shadow-lg transition duration-300 ease-in-out hover:bg-indigo-700 hover:scale-105"
                        >
                          Edit Profile
                        </button>
                      </div>
                      <p className="text-sm font-semibold text-indigo-600">{profile.role}</p>
                      <p className="text-sm text-gray-700 whitespace-pre-line leading-relaxed">{profile.bio}</p>
                      <p className="text-sm text-gray-500">{profile.location}</p>
                    </div>
                    </div>
                </div>
                <div className="flex space-x-10 text-center text-gray-700 mt-2">
                  <div className="cursor-pointer hover:text-indigo-600 transition duration-300">
                    <p className="text-lg font-bold">120</p>
                    <p className="text-sm text-gray-500">Followers</p>
                  </div>
                  <div className="cursor-pointer hover:text-indigo-600 transition duration-300">
                    <p className="text-lg font-bold">75</p>
                    <p className="text-sm text-gray-500">Following</p>
                  </div>
                  <div className="cursor-pointer hover:text-indigo-600 transition duration-300">
                    <p className="text-lg font-bold">9</p>
                    <p className="text-sm text-gray-500">Projects</p>
                  </div>
                 </div>
              </div>
            )}
          </>
        )}
            {success && (
        <div className="bg-green-100 text-green-700 px-4 py-2 mt-4 rounded flex flex-col items-center justify-center text-center">
          <span>Profile saved successfully!</span>
          <button
            onClick={() => setSuccess(false)}
            className="mt-2 text-sm underline text-green-700 hover:text-green-900 transition duration-200"
          >
            Dismiss
          </button>
        </div>
      )}
    </div>
  );
}

Matched JSX brackets

I tried cleaning up an improperly nested set of and </> tags and added a missing in the non-editing (!isEditing) view.

Expected Result: Resolving the initial Unexpected EOF error
Outcome: That error was replaced by a different error — suggesting deeper issues below.

I tried correcting the return structure but I think this is where Im going wrong.

I’ve tried looking for rogue / or unterminated strings

A separate error showed up (Unterminated regexp literal), which often happens when a forward slash / is misinterpreted as a regex start. That specific error was cleared — we returned to syntax/EOF errors.

HOW THE HELL WOULD ONE KNOW THAT THIS CODE IS GOING TO LEAD TO SSTI [closed]

Could be on the wrong site but man i’m annoyed>..>>>>>>>….>>>.>>..>>.>….

So I’m doing a CTF on tryhackme (WhiteRose)

////////

ReferenceError: /home/web/app/views/settings.ejs:14
    12|         <div class="alert alert-info mb-3"><%= message %></div>
    13|     <% } %>
 >> 14|     <% if (password != -1) { %>
    15|         <div class="alert alert-success mb-3">Password updated to '<%= password %>'</div>
    16|     <% } %>
    17|     <% if (typeof error != 'undefined') { %>

////////

Message:
password is not defined

////////
Stack

at eval ("/home/web/app/views/settings.ejs":27:8)
    at settings (/home/web/app/node_modules/ejs/lib/ejs.js:692:17)
    at tryHandleCache (/home/web/app/node_modules/ejs/lib/ejs.js:272:36)
    at View.exports.renderFile [as engine] (/home/web/app/node_modules/ejs/lib/ejs.js:489:10)
    at View.render (/home/web/app/node_modules/express/lib/view.js:135:8)
    at tryRender (/home/web/app/node_modules/express/lib/application.js:657:10)
    at Function.render (/home/web/app/node_modules/express/lib/application.js:609:3)
    at ServerResponse.render (/home/web/app/node_modules/express/lib/response.js:1039:7)
    at /home/web/app/routes/settings.js:27:7
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

//////////

I did see some write ups that just go ahead and add another “&” to the data being passed and fuzz a new variable..

  • What made them deduct that they need to enumerate for a new variable ??
  • How did they know it’s SSTI (Server Side Template Injection)????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

Uncaught SyntaxError: Unexpected end of input in Django Template (inline JS)

I’m developing a Django web application to visualize data from uploaded XML files. I’m encountering a persistent Uncaught SyntaxError: Unexpected end of input in the browser console when loading the data visualization page. This error prevents the JavaScript from running and the chart (using Chart.js) from displaying.

Problem:

When I navigate to the /visualizer/data-visualizer/ page, the browser console shows Uncaught SyntaxError: Unexpected end of input, pointing to a line number within the main HTML response (e.g., data-visualizer/:3149:80). The chart area on the page remains blank.

Context:

  • Django Version: 5.2
  • Python Version: [Your Python version, e.g., 3.9, 3.10]
  • Operating System: Windows
  • Web Server: Django Development Server (manage.py runserver)
  • The application workflow is: Upload XML file -> Select data fields -> View visualization page (/visualizer/data-visualizer/).
  • The visualization page is rendered by the VisualizerInterfaceView using the visualizer_interface.html template.
  • The template includes Chart.js via a CDN and has an inline <script> block containing custom JavaScript logic to retrieve data from JSON embedded in the template and render the chart.

Observed Behavior and Debugging Steps Taken:

  1. The Uncaught SyntaxError: Unexpected end of input error appears consistently in the browser console (tested in Chrome and Edge).
  2. Looking at the browser’s “View Page Source” for the /visualizer/data-visualizer/ page reveals that the inline JavaScript code within the <script> block is being cut off/truncated at the very end. This missing code includes closing curly braces, parentheses, the }); for the DOMContentLoaded listener, and the closing </script> tag.
  3. I have visually confirmed multiple times that the visualizer_interface.html file on my local disk contains the complete and correct JavaScript code, including all the necessary closing elements. I have opened the file in a separate editor instance to verify its content on disk.
  4. Restarting the Django development server does not resolve the issue.
  5. Performing aggressive browser cache clearing and hard refreshes does not resolve the issue.
  6. Trying a different browser (Edge) also shows the exact same SyntaxError and truncation.
  7. The Django development server terminal output shows a GET /visualizer/data-visualizer/ HTTP/1.1" 200 ... response, indicating the page is being served without explicit server-side errors at that stage.
  8. A separate issue related to saving uploaded files to the media/datasets directory was debugged and resolved, confirming that basic file saving/writing works in the project now.

Relevant Code:

(Please include the full, correct code for your visualizer_interface.html here. This is the code you confirmed is complete on your disk.)

{% extends 'base.html' %}
{% comment %} visualizer_interface.html {% endcomment %}
{% load custom_filters %} {# Make sure you have custom_filters.py with the get_item filter and load it here #}
{% load static %}

{% block title %}Data Visualizer{% endblock %}

{# Page-specific CSS, including basic table and chart container styles #}
{% block extra_css %}
    {# You can uncomment the link below if you have a static css/visualizer_interface.css file #}
    {# <link rel="stylesheet" href="{% static 'css/visualizer_interface.css' %}"> #}
    <style>
        /* Basic styling for the table */
        table {
            border-collapse: collapse;
            width: 100%;
            margin-top: 20px;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        /* Style for the chart container */
        .chart-container {
            position: relative; /* Needed for Chart.js responsiveness */
            width: 80%; /* Adjust as needed */
            margin: 20px auto; /* Center the chart */
            height: 400px; /* Give the container a height */
        }
         /* Optional: Style for messages */
        .messages {
            list-style: none;
            padding: 0;
            margin: 10px 0;
        }
        .messages li {
            padding: 10px;
            margin-bottom: 5px;
            border-radius: 4px;
        }
        .messages .success {
            background-color: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }
        .messages .error {
            background-color: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }
         .messages .info {
            background-color: #d1ecf1;
            color: #0c5460;
            border: 1px solid #bee5eb;
        }
    </style>
{% endblock %}


{% block content %}
<div class="container mt-4">
    <h2>Data Visualizer</h2>

    {# Display messages #}
    {% if messages %}
        <ul class="messages">
            {% for message in messages %}
                <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
            {% endfor %}
        </ul>
    {% endif %}


    {# Section to display extracted data in a table #}
    <h3>Extracted Data Preview:</h3>
    {% if extracted_data %}
        <table class="table table-bordered table-striped">
            <thead>
                <tr>
                    {# Display the extracted data field names as headers #}
                    {% for field in chart_data_fields %}
                        <th>{{ field }}</th>
                    {% endfor %}
                </tr>
            </thead>
            <tbody>
                {# Iterate through the extracted data entries (rows) #}
                {% for row in extracted_data %}
                    <tr>
                        {# Iterate through the fields for each row #}
                        {% for field in chart_data_fields %}
                            {# Access data using the field name as the key #}
                            {# Use the get_item filter defined in custom_filters.py #}
                            <td>{{ row|get_item:field }}</td>
                        {% endfor %}
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    {% else %}
        <p>No data has been extracted yet. Please upload an XML file and select data fields.</p>
         <p><a href="{% url 'visualizer:upload_dataset' %}">Upload New File</a></p>
    {% endif %}

    {# Charting Section #}
    {% if extracted_data %} {# Only show chart section if data is available #}
        <hr> {# Horizontal rule for separation #}
        <h3>Chart Options:</h3>
        <div class="mb-3"> {# Margin bottom #}
            <label for="chartType" class="form-label">Chart Type:</label>
            <select id="chartType" class="form-select d-inline-block w-auto"> {# w-auto for bootstrap #}
                <option value="bar">Bar Chart (Amount by Type)</option>
                <option value="line">Line Chart (Amount over Time - Requires Date Handling)</option>
                <option value="pie">Pie Chart (Total Amount by Type)</option>
                <option value="doughnut">Doughnut Chart (Total Amount by Type)</option>
                {# Add other relevant chart types if needed #}
            </select>

            <label for="chartColor" class="form-label ms-3">Chart Color:</label> {# margin start #}
            <input type="color" id="chartColorInput" value="#007bff" class="form-control-color d-inline-block"> {# Default blue color, form-control-color for bootstrap #}
        </div>

        <h3>Data Chart:</h3>
        <div class="chart-container">
            {# Canvas element where the chart will be rendered #}
            <canvas id="myChart"></canvas>
        </div>
    {% endif %}


</div> {# closes <div class="container mt-4"> #}

{# Safely embed JSON data for JavaScript - Place these lines HERE within block content, outside the container div #}
{{ extracted_data|json_script:"extractedDataJson" }}
{{ chart_data_fields|json_script:"chartDataFieldsJson" }}

{% endblock %} {# End of block content #}


{% block extra_js %}
{# Include charting libraries here (e.js., Chart.js) #}
{# Make sure you have internet access or serve this file locally #}
<script src="[https://cdn.jsdelivr.net/npm/chart.js](https://cdn.jsdelivr.net/npm/chart.js)"></script>

{# THIS IS YOUR CUSTOM CHARTING JAVASCRIPT #}
<script>
    // Wrap the entire custom JavaScript code inside a DOMContentLoaded listener
    // This ensures the script runs only after the HTML elements are available in the DOM
    document.addEventListener('DOMContentLoaded', function() {

        // --- Get data passed from the Django view context using json_script ---
        // These elements are created by the {{ ...|json_script }} template tags
        // document.getElementById will find them after DOMContentLoaded
        const extractedDataElement = document.getElementById('extractedDataJson');
        const chartDataFieldsElement = document.getElementById('chartDataFieldsJson');

        let extractedData = [];
        let chartDataFields = [];

        // Safely parse the JSON content if the elements are found
        if (extractedDataElement && extractedDataElement.textContent) {
            extractedData = JSON.parse(extractedDataElement.textContent);
        } else {
             console.error("Extracted data element not found or empty.");
             // You might want to display an error message to the user on the page
        }

         if (chartDataFieldsElement && chartDataFieldsElement.textContent) {
            chartDataFields = JSON.parse(chartDataFieldsElement.textContent);
        } else {
            console.error("Chart data fields element not found or empty.");
             // You might want to display an error message to the user on the page
        }


        console.log("Extracted Data (JS):", extractedData); // Debug log in browser console
        console.log("Chart Data Fields (JS):", chartDataFields); // Debug log in browser console


        // --- Helper Function to Clean and Convert Amount String to a Number ---
        function cleanAmount(amountString) {
            if (typeof amountString === 'string') {
                // Remove dollar signs, commas, and potentially handle parentheses for negative numbers
                let cleaned = amountString.replace(/[$,]/g, '').trim();
                // Handle parentheses often used for negative numbers in accounting
                if (cleaned.startsWith('(') && cleaned.endsWith(')')) {
                    cleaned = '-' + cleaned.substring(1, cleaned.length - 1);
                }
                // Attempt conversion to float
                const value = parseFloat(cleaned);
                return isNaN(value) ? 0 : value; // Return 0 for invalid conversion
            }
            return 0; // Return 0 for non-string input
        }

        // --- Function to Extract Data for Charting ---
        function extractChartData(data, fields, chartType) {
            const chartLabels = []; // For categories (e.g., 'Transfer', 'Credit') - from Column_4
            const chartValues = []; // For numerical values (e.g., Amount) - from Column_5

            // Find the actual keys for Column_4 and Column_5 based on the order in chartDataFields
            // We assume Column_4 is Type and Column_5 is Amount for this specific XML
            // Use Array.find to get the exact key string if it exists
            const col4Key = fields.find(field => field === 'Column_4');
            const col5Key = fields.find(field => field === 'Column_5');

            // Check if the required columns were found in the extracted fields
            if (!col4Key || !col5Key) {
                console.error("Required columns (Column_4, Column_5) not found in extracted fields.");
                 // Return an object indicating an error, which renderChart will check
                return { labels: [], values: [], error: "Required columns (Column_4, Column_5) not found in data fields." };
            }


            data.forEach(row => {
                 // Check if the row is a valid object and contains the required keys
                 if (typeof row === 'object' && row !== null && row.hasOwnProperty(col4Key) && row.hasOwnProperty(col5Key)) {
                     const label = row[col4Key]; // Get value from Column_4
                     const valueString = row[col5Key]; // Get value from Column_5

                     // Only include rows where both label and value string are not null/undefined
                     if (label != null && valueString != null) {
                         const value = cleanAmount(valueString);
                         // Only include if the cleaned value is a valid number (not NaN)
                         if (!isNaN(value)) {
                             chartLabels.push(label);
                             chartValues.push(value);
                         } else {
                             console.warn(`Skipping row due to invalid amount in ${col5Key}:`, valueString);
                         }
                     } else {
                          console.warn(`Skipping row due to missing data in ${col4Key} or ${col5Key}:`, row);
                     }
                 } else {
                     console.warn("Skipping invalid row data structure:", row);
                 }
            });


            // --- Data Aggregation (Necessary for Pie/Doughnut, Optional for others) ---
            const aggregatedData = {};
             // Aggregate values by label (Type)
            chartLabels.forEach((label, index) => {
                if (!aggregatedData[label]) {
                    aggregatedData[label] = 0;
                }
                aggregatedData[label] += chartValues[index];
            });

            // Prepare data and labels for display based on chart type
            let displayLabels = Object.keys(aggregatedData); // Always use aggregated labels for charts
            let displayValues = Object.values(aggregatedData); // Always use aggregated values for charts
            let chartTitle = 'Total Transaction Amount by Type'; // Default title for aggregated data

            // Optional: If you want individual bars/points for Bar/Line, keep this logic:
            // let displayLabels = chartLabels;
            // let displayValues = chartValues;
            // let chartTitle = 'Transaction Amounts by Type (Individual)';


            // --- Return the processed data object ---
            return {
                labels: displayLabels,
                values: displayValues,
                aggregated: aggregatedData, // Include aggregated data for potential future use
                chartTitle: chartTitle
            };

        } // <-- End of extractChartData function


        // --- Function to Render the Chart ---
        function renderChart() {
            // Check if the canvas element exists before trying to get context
            const canvasElement = document.getElementById('myChart');
            if (!canvasElement) {
                console.error("Canvas element with ID 'myChart' not found.");
                return; // Stop if canvas is missing
            }

            // Destroy existing chart instance if it exists to prevent duplicates
            if (window.myChartInstance) { // Use a property on the window object to store the chart instance globally
                window.myChartInstance.destroy();
            }

            // Get selected chart type and color from controls
            const chartTypeSelect = document.getElementById('chartType');
            const chartColorInput = document.getElementById('chartColorInput'); // Corrected ID

             if (!chartTypeSelect || !chartColorInput) {
                console.error("Chart type or color controls not found.");
                // You might want to display an error message to the user
                return; // Stop if controls are missing
            }

            const selectedChartType = chartTypeSelect.value;
            let selectedChartColor = chartColorInput.value; // Use let as it might be overridden for pie/doughnut


            // Extract and process data based on the selected chart type
            // Pass the *selected* chart type to extractChartData to influence aggregation
            const chartData = extractChartData(extractedData, chartDataFields, selectedChartType);

            // Check if extractChartData returned an error
            if (chartData.error) {
                 // Display the error message on the canvas
                 const ctx = canvasElement.getContext('2d');
                 if(ctx) {
                     ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // Clear previous content
                     ctx.font = "16px Arial";
                     ctx.fillStyle = "red";
                     // Draw text, potentially wrapping or adjusting position for long messages
                     ctx.fillText("Error: " + chartData.error, 10, 50); // Display the error text on the canvas
                 }
                 console.error(chartData.error); // Log error to console
                 return; // Stop rendering if data extraction failed
            }

            // Get the 2D rendering context for the canvas
            const ctx = canvasElement.getContext('2d');
             if (!ctx) {
                console.error("Failed to get 2D context for canvas.");
                return; // Stop if context cannot be obtained
            }

            // --- Chart.js Configuration ---
            const datasets = [{
                label: chartData.chartTitle || 'Data', // Use title from extractChartData or default
                data: chartData.values, // Numerical data values
                borderWidth: 1
            }];


            // Set colors based on chart type
            if (selectedChartType === 'pie' || selectedChartType === 'doughnut') {
                // Generate a palette of colors for segments
                // Use HSL for better control over distinct colors
                const backgroundColors = chartData.labels.map((label, index) => `hsl(${(index * 360 / chartData.labels.length) % 360}, 70%, 60%)`); // Generate distinct colors
                datasets[0].backgroundColor = backgroundColors;
                // Create slightly darker border colors based on background colors
                datasets[0].borderColor = backgroundColors.map(color => color.replace('60%)', '40%)'));
            } else {
                 // Use the selected single color for bar/line charts
                 datasets[0].backgroundColor = selectedChartColor;
                 // Use the same color for the border (or calculate a darker shade if preferred)
                 datasets[0].borderColor = selectedChartColor;

                 // Optional: Configure scales if needed for bar/line
                 // scales: { y: { beginAtZero: true }, x: {} }
            }


            // Create the new Chart.js instance and store it
            window.myChartInstance = new Chart(ctx, {
                type: selectedChartType, // User selected type
                data: {
                    labels: chartData.labels, // Labels (Type names or aggregated labels)
                    datasets: datasets // The dataset(s) containing the data and styling
                },
                options: {
                    responsive: true, // Chart resizes with its container
                    maintainAspectRatio: false, // Allows chart to fill the container height
                    scales: { // Define scales based on chart type
                        y: {
                            beginAtZero: true,
                            display: selectedChartType !== 'pie' && selectedChartType !== 'doughnut' // Hide y-axis for pie/doughnut
                        },
                        x: {
                             display: selectedChartType !== 'pie' && selectedChartType !== 'doughnut' // Hide x-axis for pie/doughnut
                        }
                    },
                    plugins: {
                        legend: {
                            display: selectedChartType === 'pie' || selectedChartType === 'doughnut' // Only show legend for pie/doughnut
                        },
                        title: {
                             display: true, // Show the chart title
                             text: chartData.chartTitle || 'Data Chart' // Use title from extractChartData or default
                        },
                        tooltip: { // Optional: Add tooltips for better interactivity
                            enabled: true
                        }
                    }
                }
            });
        }

        // --- Event Listeners and Initial Render ---

        // Add event listeners to the chart controls to re-render the chart when they change
        const chartTypeSelect = document.getElementById('chartType');
        const chartColorInput = document.getElementById('chartColorInput'); // Corrected ID

        // Check if controls were found before adding listeners
        if(chartTypeSelect) {
            chartTypeSelect.addEventListener('change', renderChart);
        } else {
            console.error("Chart type select element not found.");
        }

        if(chartColorInput) {
             chartColorInput.addEventListener('input', renderChart); // Use 'input' for real-time color updates
        } else {
             console.error("Chart color input element not found.");
        }


        // Render the chart initially when the DOM is fully loaded
        renderChart(); // Call renderChart directly now that DOMContentLoaded is complete


    }); // <--- This is the correct closing of the DOMContentLoaded listener
</script> {# <-- This closes the script tag containing your custom JavaScript #}

{% endblock %} {# <-- This is the correct closing of the {% block extra_js %}. It should be the very last line of the file. #} terminal output  PS C:UsersJasonOneDriveDesktopdatavis_project> python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
April 19, 2025 - 19:23:27
Django version 5.2, using settings 'datavis_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

WARNING: This is a development server. Do not use it in a production setting. Use a production WSGI or ASGI server instead.
For more information on production servers see: https://docs.djangoproject.com/en/5.2/howto/deployment/
--- GET method in UploadDatasetView called ---
[19/Apr/2025 19:23:36] "GET /visualizer/ HTTP/1.1" 200 714
--- POST method in UploadDatasetView started ---
Form received. Is valid: True
Form is valid. Proceeding with file processing.
Uploaded file: Bank of America _ Online Banking _ Deposit _ Print Transaction Details.xml, Extension: xml
Handling XML file.
File saved to: C:UsersJasonOneDriveDesktopdatavis_projectmediadatasetsbank-of-america-_-online-banking-_-deposit-_-print-transaction-detailsxml
File content read from saved file and stored in session.
Calling analyze_xml_structure_recursive...
Analyzer: Root Element: {urn:schemas-microsoft-com:office:spreadsheet}Workbook

Analyzer: Namespaces:
  : http://www.w3.org/TR/REC-html40
  o: urn:schemas-microsoft-com:office:office
  x: urn:schemas-microsoft-com:office:excel
  ss: urn:schemas-microsoft-com:office:spreadsheet
  html: http://www.w3.org/TR/REC-html40

Analyzer: Starting recursive element analysis...
Analyzer: Recursive analysis finished.
analyze_xml_structure_recursive finished.
Analyzer returned structure info. Storing in session.
XML structure and namespaces stored in session.
Redirecting to select_data_for_charting.
[19/Apr/2025 19:23:54] "POST /visualizer/ HTTP/1.1" 302 0
[19/Apr/2025 19:23:54] "GET /visualizer/select-data/ HTTP/1.1" 200 53767
[19/Apr/2025 19:23:54] "GET /static/css/style.css HTTP/1.1" 404 1853
--- POST method in SelectDataForChartingView called ---
User selected element tag: {urn:schemas-microsoft-com:office:spreadsheet}Row
User selected data field paths: ['{urn:schemas-microsoft-com:office:spreadsheet}Row__child__{urn:schemas-microsoft-com:office:spreadsheet}Cell', '{urn:schemas-microsoft-com:office:spreadsheet}Cell__child__{urn:schemas-microsoft-com:office:spreadsheet}Data']
XML content parsed in POST method for data extraction.
Found 122 elements matching the selected tag '{urn:schemas-microsoft-com:office:spreadsheet}Row'.
Identified parent of data tag: {urn:schemas-microsoft-com:office:spreadsheet}Cell
Identified data tag: {urn:schemas-microsoft-com:office:spreadsheet}Data
Extracted 122 data entries.
Identified Chart Data Fields: ['Column_1', 'Column_2', 'Column_3', 'Column_4', 'Column_5'] 
SelectDataForChartingView: Final chart_data_fields before saving to session: ['Column_1', 'Column_2', 'Column_3', 'Column_4', 'Column_5']
[19/Apr/2025 19:24:07] "POST /select-data/ HTTP/1.1" 302 0
--- GET method in VisualizerInterfaceView called ---
VisualizerInterfaceView: Request object: <WSGIRequest: GET '/visualizer/data-visualizer/'> 
VisualizerInterfaceView: Request method: GET
VisualizerInterfaceView: Request path: /visualizer/data-visualizer/
VisualizerInterfaceView: Request GET: <QueryDict: {}>
VisualizerInterfaceView: Request POST: <QueryDict: {}>
VisualizerInterfaceView: Session keys: ['uploaded_dataset_name', 'extracted_chart_data', 'chart_data_fields', 'uploaded_file_content', '_xml_namespaces', '_xml_structure']
VisualizerInterfaceView: Retrieved 122 extracted data entries from session.
VisualizerInterfaceView: Retrieved Chart Data Fields from session: ['Column_1', 'Column_2', 'Column_3', 'Column_4', 'Column_5']
VisualizerInterfaceView: Rendering template with context keys: ['extracted_data', 'chart_data_fields']
[19/Apr/2025 19:24:07] "GET /visualizer/data-visualizer/ HTTP/1.1" 200 143476
[19/Apr/2025 19:24:07] "GET /static/css/style.css HTTP/1.1" 404 1853[enter image description here][1]


  [1]: https://i.sstatic.net/fzzjiBp6.png

Posting to Google Sheets via Google Apps Script – “Unexpected token ‘<', "<!DOCTYPE "… is not valid JSON" Error

I’m a beginner web developer building an online RSVP form that should save data to a Google Sheet via a Heroku proxy and Google Apps Script. While fetching data works, submitting form data via a POST request to my Heroku /api/submit endpoint results in a “Unexpected token ‘<‘, “”… is not valid JSON” error in the browser. Postman also returns an HTML error (…

Cannot GET /api/submit

) for the same POST request.

Despite checking Heroku logs, server status, and Google Apps Script deployment (and even after many hours of tutorials), I’m stuck. As a newbie, I want to make a disclaimer that I used AI for assistance and I likely have some fundamental misunderstandings. (Trying to get better at writing and debugging myself though!) I’ll paste my relevant JavaScript code below – any guidance would be greatly appreciated!

            } else if (currentStep === 4) {
                const dietaryNotes = document.getElementById("dietaryNotes").value;
                const messageToHosts = document.getElementById("messageToHosts").value;
            
                const rsvpData = {
                    name: guestNameInput.value.trim(),
                    message: messageToHosts,
                    dietaryNotes: dietaryNotes,
                    rsvps: rsvpChoices  // This includes each guest's RSVP and meal choice
                };

                console.log("About to fetch to Heroku endpoint...");

                fetch("https://immense-plains-30838-adb516d69898.herokuapp.com/api/submit", {
                    method: "POST",
                    body: JSON.stringify(rsvpData),
                    headers: {
                        "Content-Type": "application/json"
                    }
                })

                .then(r => r.json())
                .then(data => {
                    if (data.success) {
                        alert("RSVP submitted! Thanks!");
                        showStep(1);
                        form.reset();
                    } else {
                        alert("Failed to submit RSVP.");
                    }
                })
                .catch(err => {
                    console.error(err);
                    alert("Error submitting RSVP.");
                });
            }
    });

    // Initially show Step 1
    showStep(1);
});

Waiting for all side promises to finish before “then()” execution

In section then3 I want to generate promises with further operations on their content inside 2 “thens”. In case they were fetches, I want to limit their start to for example 3 at once every 1000ms. Next, I want the then4 to wait until generation stops and every promise finish. The problem is then4 runs just after limitedPromises function call. I’m losing my mind trying to understand why exactly the then4 doesn’t wait for any resolve or return function and how to make him do wait just as he does in other “thens”

Promises chain schema

As you can see in then4, I tried to trick the code to check in intervals the last promise started. It almost works, just don’t wait for last promise to finish. I know that it’s a wrong way to go though.
I’m trying to understand promises chaining. I wrote a training code, I understand chaining single promises, but I got totally lost on chaining multiple promises. I read everything on stack, google, libraries, few blogs and didn’t find any example like this. I think I’m incorrectly mixing for loop with promises or I probably should use Promise.all() to get it, but I can’t think of a way to pass those newly created chains to an array to use in Promise.all()

new Promise(function(resolve, reject) {
    a = [8, 5, 6, 10, 11, 2, 1, 0, 3, 5, 6]
    resolve(a)

}).then(function(result1) { // then1
    console.log("then1", result1)
    result1.push(2)
    return result1

}).then(function(result2) { // then2
    console.log("then2", result2)
    result2.push(9)
    return result2

}).then(function(result3) { // then3    
    console.log("then3", result3)
    list1 = []
    promiseLimit = 3
    timeBetweenPromises = 1000
    startIndex = 0
    
    function limitedPromises(){
        setTimeout(()=>{
            for (let i=startIndex; i<startIndex+promiseLimit; ++i){
                if (i > result3.length-1){
                    startIndex = i-1
                    console.log("break")
                    break
                }
                console.log("inside for, i =", i)
                
                new Promise(function(resolve, reject){
                    b = result3[i] + 100
                    resolve(b)
                }).then(function(result3a){
                    console.log("then 3a, inside promise:", result3a, "i =", i)
                    if (result3[i] > 5){
                        list1.push([result3[i]])
                    }
                    if (result3a > 100){
                        if (list1[i] === undefined){
                            list1[i] = []
                        }
                        list1[i].push(1)
                        list1[i].push(result3a)
                        console.log("list1 after pushes", list1)
                    }
                    
                }).then(function(){
                    console.log("then 3b, i:", i, "startIndex:", startIndex, "result3.length:", result3.length, "(i === startIndex+promiseLimit-1):", i === startIndex+promiseLimit-1, "(i < result3.length):", i < result3.length)
                    console.log("i = ", i, "result3.length-1 =", result3.length-1, "(i === result3.length-1):", i === result3.length-1)
                    if (i === startIndex+promiseLimit-1 && i < result3.length){
                        startIndex += promiseLimit
                        if (i === result3.length-1){
                            console.log("%c"+"Returning result3: ", "background: #111; color: #F6FF0DFF", result3)
                            return result3 // then4 should wait for this return
                        } else {
                            limitedPromises()  // recursion
                        }
                    }
                })
                
            }
        }, timeBetweenPromises)
    }
    limitedPromises()
    //return result3  //this is wrong, only for debug
}).then(function(result4) { // then4
    return new Promise(function(resolve, reject){
        intervalNo = setInterval(() => {
            console.log("then4, startIndex:", startIndex, "result4.length -1", result4.length -1, "intervalNo", intervalNo)
            if (startIndex >= result4.length-1){
                console.log(list1, list1.slice(-1))
                clearInterval(intervalNo)
                resolve(list1)
            }
        }, 100)
    })
}).then(function(result5){ // then5
    console.log("%c"+"then5, Final result: ", "background: #111; color: #F6FF0DFF", result5)
})

State is not persisting in popup.html via Chrome storage

I expected the following

  • For handleLogs() to store { site: 'https://google.com' } in sites state and to store in Chrome local storage
  • For useEffect hook to grab the sites array and save in site state whenever the popup is opened

The current issue is that whenever I open the popup, the sites[] is always empty. I can see via dev tools that the site is added to state and storage in local storage in initial interction with input. But subsequent opens, with no interaction with the input shows an empty sites array in state and in local storage. Why is that?

Below is real simplified version of the code I have inapp.jsx file

const App = () => {
    const [sites, setSites] = useState([]);

    useEffect(() => {
        chrome.storage.local.get(['sites'], (res) => {
            setSites(res.sites);
            console.log(res);
        });
    }, []);

    function handleLogs(event) {
        setSites((prevSites) => [...prevSites, { site: 'https://google.com' }]);
        chrome.storage.local.set({ sites });
    }

    return <input type="checkbox" onClick={() => handleLogs(event)} />;
};

Nextjs 15 uploading static website to example.com/admin

The steps I did:

  • Created Nextjs (app route) and I used ‘use client’ on every components.
  • In Dev Env The root is http://localhost:port/ .
  • npm run build, no errors and all the static files in ( out ) folder.
  • uploading part, I created a folder called admin ( example.com/admin )
  • uploaded all files in admin folder.

When I access example.com/admin, the page load for a second and then redirects me because example.com/index.txt 404 (but its exists in /admin/index.txt)

It looks for example.com/index.txt?….
where index.txt is in example.com/admin/index.txt?.. With all the files.

Next config:

const nextConfig: NextConfig = {
  env: {
    type: "production"
  },
  output: process.env.type === 'production' ? "export" : undefined,
  assetPrefix: process.env.type === 'production' ? '/admin' : '/',
  basePath: process.env.type === 'production' ? '/admin' : '',
  typescript: {
    ignoreBuildErrors: true
  }
};

export default nextConfig;

Thank you.

What is a fast combinition of language + 2d graphics library for generative art

To generate static generative art I wrote a small library in javascript. It doesn’t use p5.js, but for convenience I put it in the p5 web editor. Here is the link: Doek.js

The library works smoothly (on chrome browser) for drawing shapes and panning and zooming (the example in the link creates a huge canvas of about 23000 x 11500 pixels).

For heavy calculations however i would like to rewrite the library in another, faster programming language. But here is my problem.
Before i fully immerse myself in a new programming language, i want to know with which combination (language and 2d graphics library) i can realize this.

With the help of AI i tried different combinations (rust, c, zig, java, D, … + SDL, SFML, GLFW, …), but, although drawing the shapes works, the big problem is always copying the offscreen data from the large canvas to the window fast enough at a framerate of 60FPS.

I also tried Löve2D which worked fine, but Löve2d is very limited in drawing itself and also too slow I think (maybe i’m wrong).

processing.org can be a solution, but when the canvas is to big it is a lot slower then in js

I had no success with kotlin and openrndr either, but i am not an expert

So my question is, what combination should work. A fast programming language with a window library and a 2d graphics library (with anti aliased shapes). I do not want to generate the shapes (thin and thick lines with line caps, rectangles, arcs, ellipses, etc) myself with shaders.

I also want to mention that I work with linux (debian, arch, …)

Thanks for the advice

How to fix JS / JQUERY errors when leaving buddypress pages but still logged in

I am using buddypress on my wordpress install. Beside the buddypress pages I also have some other pages where a user can go to. But on all these “non”-buddypress pages I am getting a couple of error messages on the console like the ones below. All thrown by different buddypress plugins like better messages and others. The user ist still logged in, when viewing the other pages.

POST wp-json/better-messages/v1/checkNew?nocache=1745075303595 403
(Forbidden) (anonymous) @ bp-messages-free.min.js?ver=2.8.0:2
xhr @ bp-messages-free.min.js?ver=2.8.0:2
Ss @ bp-messages-free.min.js?ver=2.8.0:2 Promise.then
value @ bp-messages-free.min.js?ver=2.8.0:2
(anonymous) @ bp-messages-free.min.js?ver=2.8.0:2 ….

OR

Uncaught (in promise) Error: A listener indicated an asynchronous
response by returning true, but the message channel closed before a
response was received

OR

Uncaught TypeError: jQuery.cookie is not a function

The code line to the last error is

/*----------------------------------------*/
Display message after review submit
*-----------------------------------------*/
jQuery(function () {
if (jQuery.cookie("response") && jQuery.cookie("response") !== "") {
jQuery(".add_review_msg p").html(jQuery.cookie("response"));
jQuery(".add_review_msg").show();
jQuery.cookie("response", "", -1);
jQuery("#review_subject").val("");
jQuery("#review_desc").val("");
}});

What can I do to fix all these issues?