Solana transaction sending but never confirming on devnet – “Transaction not found on chain”

I’m building a React app with Solana wallet integration and experiencing a
persistent issue where transactions are successfully sent (I get a valid
transaction signature), but they never confirm on-chain.

The Problem:

  1. User connects a wallet (Phantom) successfully
  2. User signs a transaction (I get the wallet popup and signature)
  3. Transaction is sent (I get a transaction ID)
  4. Transaction fails to confirm with “Transaction confirmation timeout –
    not found on chain”
  5. When checking the explorer, the transaction is “not found”

This happens consistently, even with different transaction amounts and
recipient addresses.

My Environment:

  • Solana devnet
  • @solana/web3.js v1.98.0
  • @solana/wallet-adapter-react
  • Phantom wallet

Here’s my transaction sending code:

  // Get latest blockhash with context - using PROCESSED for fastest 
  blockhash
  const {
    context: { slot: minContextSlot },
    value: { blockhash, lastValidBlockHeight }
  } = await connection.getLatestBlockhashAndContext('processed');

  // Create transaction with priority fee
  const transaction = new Transaction({
    feePayer: publicKey,
    recentBlockhash: blockhash,
  });

  // Add priority fee instruction
  transaction.add(
    ComputeBudgetProgram.setComputeUnitPrice({
      microLamports: 100000 // 0.0001 SOL priority fee
    })
  );

  // Add transfer instruction
  transaction.add(
    SystemProgram.transfer({
      fromPubkey: publicKey,
      toPubkey: recipientPubkey,
      lamports: amount * LAMPORTS_PER_SOL
    })
  );

  // Send transaction with consistent commitment
  const txSignature = await sendTransaction(transaction, connection, {
    minContextSlot,
    skipPreflight: false,
    preflightCommitment: 'processed', // Match the blockhash commitment
    maxRetries: 5
  });

  // Transaction sent! Now confirm it...

  And here's my confirmation code:

  // Wait for confirmation with timeout
  const waitForConfirmation = async (txSignature, blockhash,
  lastValidBlockHeight) => {
    try {
      // Method 1: Use confirmTransaction
      const confirmationPromise = connection.confirmTransaction({
        signature: txSignature,
        blockhash: blockhash,
        lastValidBlockHeight: lastValidBlockHeight
      }, 'confirmed');

      // Method 2: Poll for status
      const statusCheckPromise = new Promise((resolve, reject) => {
        let retries = 0;
        const maxRetries = 30;

        const checkStatus = async () => {
          try {
            // Check if block height has been exceeded
            const currentBlockHeight = await
  connection.getBlockHeight('confirmed');
            if (currentBlockHeight > lastValidBlockHeight) {
              reject(new Error(`Transaction expired: block height 
  exceeded`));
              return;
            }

            const status = await connection.getSignatureStatus(txSignature);
            if (status && status.value) {
              if (status.value.confirmationStatus === 'confirmed' ||
                  status.value.confirmationStatus === 'finalized') {
                resolve(status);
                return;
              }
            }

            retries++;
            if (retries >= maxRetries) {
              reject(new Error('Transaction confirmation timeout - not found
   on chain'));
              return;
            }

            // Continue polling
            setTimeout(checkStatus, 1000);
          } catch (error) {
            setTimeout(checkStatus, 1000);
          }
        };

        checkStatus();
      });

      // Race both methods
      const result = await Promise.race([confirmationPromise,
  statusCheckPromise]);

      // Verify transaction is really on chain
      const txStatus = await connection.getTransaction(txSignature, {
        commitment: 'confirmed',
      });

      if (!txStatus) {
        const status = await connection.getSignatureStatus(txSignature);
        if (!status || !status.value || !status.value.confirmationStatus) {
          throw new Error('Transaction not found on chain');
        }
      }

      return result;
    } catch (error) {
      throw error;
    }
  };

I’ve tried many approaches:

  • Increased priority fees
  • Different commitment levels (‘processed’, ‘confirmed’)
  • Changed blockhash fetching strategies
  • Added proper error handling and retries

I also see this in my logs:
Got blockhash: ABCDE12345… (valid until block 352651718)
Current block height: 352651568
Added priority fee: 100000 microlamports
Transaction sent: 5g7upHabZCYUjUUmuXATXbt1aMHCqzujvTEqq6WQymD7bcxzkWCE14zW
KFfGAM2TWoSL8Km11mY8L1nhCZ8vGcen

Is there something wrong with my approach? Why would the transaction
signature be valid but the transaction never shows up on-chain?

Is there a way to wait for a function to finish before running it again?

I stumbled across this problem when i was trying to make an animation using JavaScript, and the animation itself turned out fine. The problem was, if you were to run the animation multiple times in a row (using a button), the function would run multiple times even if the first animation wasn’t finished. Here is my example:

var x = 1;
function test() {
    if(x == 1) {
        x == 0;
        document.getElementById("test").innerHTML = "I was clicked.";
        setTimeout(() => {x == 1;}, 5000);
    }
    else {
        document.getElementById("test").innerHTML = "You already clicked me!";
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <p onclick="test()" id="test">click me</p>
    <script src="test.js"></script>
</body>
</html>

Disallowed MIME type (“text/html”)

I’ve tried to import a file like so:

import config from "./config.js";

but I’ve been recieving this error:

Loading module from “https://thealoysianarticle.github.io/config.js” was blocked because of a disallowed MIME type (“text/html”).

(for the record – this is being done in a vanilla JS project)

I had tried putting .js on the end of the import but I was still getting the same error. After that, I tried changing the import code to this:

import * as config from "./config.js";

But that didn’t work either.

Can someone please tell me a solution and how a problem like this occurs so I can avoid it next time? Thank you!

Get definition of Knockout.js computed observable evaluator function

I would like to programmatically access the string representation of an evaluator function definition of a KO computed field. For example, in the case of:

self.field = ko.computed(function () {
    return 'HELLO WORLD';
});

I would like to retrieve the string:

"function () {
    return 'HELLO WORLD';
}"

I’ve tried several things with Object.keys() and JSON.stringify() but I can’t seem to get to the function definition.

How to handle @ symbol in URL path with React Router?

I’m trying to build a user profile page in my React app with a URL like http://localhost:3000/@john. I’ve seen platforms like YouTube use a similar format (/@username), but I’m unable to replicate it. React Router is throwing a 404 error when I try to access the profile with the @ symbol in the URL.

Here’s what I’ve tried:

  1. I’ve used React Router’s <Route path="/@:username"> to try and match the @username format, but this results in a 404 error: No routes matched location “/@john”.

  2. Using encoding (e.g., /@%40john), but it still didn’t work properly and gave the same error.

  3. Using React Router with query parameters, but I’d prefer to maintain the @username format in the URL path.

Here’s the relevant code:

<>
      <Routes>
        <Route path="/" element={<MainLayout />}>
          <Route index element={<Home />} />
        </Route>

        <Route path="/@:username" element={<Layout />}>
          <Route index element={<UserProfile />} />
        </Route>
      </Routes>
    </>

How do I get React Router to properly handle routes with @ in the path? Is there a way to modify my route setup or another workaround to achieve this behavior without receiving a 404 error?

Resubscribing to NGRX Effect loading old data

I’m having an odd interaction with NGRX and Routing whereby when I revisit a page I have previously been on and subscribe to an Effect it gets the data twice; but this only happens when the page I have visited in between does not do a dispatch. For example:

Page A subscribes and dispatches.
Page B subscribes and dispatches.
Page C subscribed and does not dispatch.

If I were to load Page A, then B then A; everything works as expected.

If I were to load Page A, then C, then A; the second time I visit page A the data gets loaded twice (once from some sort of invisible cache then once from the API).

My services all look like this:

@Injectable({
  providedIn: 'root',
})
export class ForumService {
  private store = inject(Store);
  private httpClient = inject(HttpClient);

  getCategories(page: number): Observable<PaginatedResponse<ForumCategoryResponse, 'categories'>> {
    let token: string | null = null;
    this.store
      .select(selectToken)
      .pipe(take(1))
      .subscribe((t) => {
        token = t;
      });

    return this.httpClient.get<PaginatedResponse<ForumCategoryResponse, 'categories'>>(
      `${environment.baseApiUrl}/forum/categories?page=${page}`,
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      }
    );
  }
}

My effects all look like this:

@Injectable()
export class ForumEffects {
  private actions$ = inject(Actions);
  private forumService = inject(ForumService);

  getCategories$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(getCategories),
      exhaustMap((action) => {
        return this.forumService
          .getCategories(action.page)
          .pipe(
            map((response) => getCategoriesSuccess(response)),
            catchError((error: ApiError) => of(getCategoriesFailure(error))),
          );
      })
    );
  });
}

And my components all look like this and all implement a pipe with takeUntil:

@Component({
  selector: 'app-forum-categories',
  imports: [ContainerComponent, HorizontalRuleComponent, NgFor, RouterLink],
  templateUrl: './forum-categories.component.html',
})
export class ForumCategoriesComponent implements OnInit, OnDestroy {
  private readonly store = inject(Store);
  private readonly actionsSubject = inject(ActionsSubject);
  destroy$ = new Subject<boolean>();
  forumCategories: ForumCategoryResponse[] = [];
  currentPage = 1;
  morePages = true;

  ngOnDestroy() {
    this.destroy$.next(true);
    this.destroy$.complete();
  }

  ngOnInit(): void {
    this.actionsSubject
      .pipe(ofType(getCategoriesSuccess))
      .pipe(takeUntil(this.destroy$))
      .subscribe((action) => {
        if (action.categories !== null) {
          this.forumCategories.push(...action.categories);
        }
        this.currentPage = action.page;
        this.morePages = action.morePages
      });

    this.store.dispatch(getCategories({ page: 1 }));
  }
}

So to reiterate; with the above code this.forumCategories.push(...action.categories); will get called with the old data, then the dispatch happens, then it will get called again and I get two sets of data. It doesn’t happen on first load and it doesn’t happen if I’ve visited a page which has done another dispatch call.

Pretty new to NGRX so I wouldn’t be surprised if I’m doing something wrong but I don’t understand it because in this case the data isn’t even saved in the store.

sendFile not working although the path is correct

We have this structure in the server:

enter image description here

Inside controller.js:

const path = require('path');

console.log(path.join(__dirname, "../views/recognition/index.html"))

return res.sendFile(path.join(__dirname, "../views/recognition/index.html"));

The log I get:

/home/exampleServerName/app/views/recognition/index.html

But nothing happens and I cannot get the recognition/index.html page

In the main server.js:

app.use('/service', require('./service/controller'));
app.use('/recognition', express.static(__dirname + '/views/recognition'));

How to correctly load a JSON file inside a JavaScript file

When I attempt to load a JSON file (containing translations) from within a JavaScript file like this:

import locales from './../locales.json'

then I get the error TypeError: error loading dynamically imported module:

Failed to register controller: [...] TypeError: error loading dynamically imported module: http://127.0.0.1:3000/assets/controllers/[...]

Context:

  • The JavaScript file is a Stimulus Controller.

  • I’m trying to set up the JS library i18n-js, from the docs

  • Rails: version 7.2

Rails: How to correctly load a JSON file inside a Javascript file

How do I correctly load a JSON file inside a Javascript file?

When I attempt to load a JSON file (containing translations) from within a Javascript file like this:

import locales from './../locales.json'

…then I get the error TypeError: error loading dynamically imported module:

Failed to register controller: [...] TypeError: error loading dynamically imported module: http://127.0.0.1:3000/assets/controllers/[...]

Context:

JavaScript / CSS – The print preview is adding some extra space for , , tag in the print preview

I am trying to generate a bill and trying to print it using print button.

This is print preview and extra white space is added before , before


and after

as shown in the image

In UI, there is no white space added before , before


and after

as shown in the image

function generateBill() {
    
    const salespersonId = document.getElementById("salesperson_id").value;
const customerName = document.getElementById("customer_name").value;

// Capitalize each word
const customerNameFormatted = customerName
    .toLowerCase()
    .split(" ")
    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
    .join(" ");

const customerNameFormattedToUpper = customerNameFormatted;
    
    const itemRows = document.querySelectorAll('.item-row');

    let totalAmount = 0;
    let totalQuantity = 0;
    let totalDiscount = 0;
    let discountAmount = 0;

    const itemsDetails = Array.from(itemRows).map((row, index) => {
        const itemName = row.querySelector('input[type="text"]').value.trim() || `Item ${index + 1}`;
        const quantity = parseInt(row.querySelector('.quantity').value) || 0;
        const rate = parseFloat(row.querySelector('input[type="number"]').value) || 0;
        const discountPercentage = parseFloat(row.querySelector('.discount').value) || 0;

       if (quantity === 0 || rate === 0) {
            return; // Skip items with zero quantity or rate
        }
        
        const itemTotal = quantity * rate;
        totalQuantity += quantity;
        const discountAmount = (itemTotal * discountPercentage) / 100;
        const finalAmount = itemTotal - discountAmount; // Corrected calculation
        totalAmount += finalAmount; 
        // Calculate commission (1% on non-innerwear items)
        const totalComission = ((totalAmount - discountAmount) * 1) / 100;
        totalDiscount += discountAmount;

        
    // Save values to global salesData object
    salesData.totalQuantity = totalQuantity;
    salesData.totalAmount = totalAmount;

        return {
            name: itemName,
            quantity,
            rate,
            discount: `${discountPercentage}%`,
            discountAmount: discountAmount.toFixed(2),
            total: finalAmount.toFixed(2),
        };
    }).filter(Boolean);
        salesData.totalComission = ((totalAmount - discountAmount) * 1) / 100;

   if (totalAmount === 0) {
   //     alert("Cannot generate a bill with zero values. Please add valid items.");
        return;
    }

    let billHTML = `
        <div class="bill-page" style="width:10.5cm; height:15.5cm; padding:5px; position:absolute; border:1px solid black; ">
            <h3 id="title" style="margin-bottom:0px; font-size:30px; text-align:center;">नॅशनल रेडिमेड</h3>
            <p id="address" style="text-align:center; font-size:15px;">
                नवीन फॅन्सी रेडिमेड कपड्यांचे भव्य शोरूम<br>
                दगडी दरवाजा, सराफ बाजार, अमळनेर जि. जळगांव<br>
                GSTIN - 27AGWPR9307F1ZQ
            </p>
            <p style="text-align:center; font-size:14px; font-weight:bold;">CASH MEMO ESTIMATE</p>
            <hr style="border: 1px solid black;">
            <p style="font-size:14px;"><strong>Bill No.:</strong> ${billID}
            <strong>&nbsp;&nbsp;&nbsp;&nbsp;SM:</strong> ${salespersonId}
            <strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date:</strong> ${new Date().toLocaleString('en-GB', {hour12: true})}</p>
            <p style="font-size:14px;"><strong>Customer's Name:</strong> ${customerNameFormattedToUpper}</p>
            <hr style="border: 1px solid black;">
            <p style="font-size:14px;"><strong>Particulars:</strong></p>

<table style="width: 100%; font-size:12px; border-collapse: collapse; max-height:200px;">
    <thead>
                    <tr>
                        <th style="text-align: left; border-left:1px solid black; border-top:1px solid black; border-bottom:1px solid black;">ITEM NAME</th>
                        <th style="text-align: right; border-left:1px solid black; border-top:1px solid black; border-bottom:1px solid black;">RATE</th>
                        <th style="text-align: right; border-left:1px solid black; border-top:1px solid black; border-bottom:1px solid black;">QTY</th>
                        <th style="text-align: right; border-left:1px solid black; border-top:1px solid black; border-bottom:1px solid black;">DISC</th>
                        <th style="text-align: right; border-left:1px solid black; border-top:1px solid black; border-bottom:1px solid black;">DISC AMT</th>
                        <th style="text-align: right; border-left:1px solid black; border-top:1px solid black; border-bottom:1px solid black; border-right:1px solid black;">AMOUNT</th>
                    </tr>
    </thead>
    <tbody>
        ${itemsDetails.map(item => `
        <tr>
                    <td style="text-align: left; border-left:1px solid black;">${item.name}</td>
                    <td style="text-align: right; border-left:1px solid black;">${item.rate}</td>
                    <td style="text-align: right; border-left:1px solid black;">${item.quantity}</td>
                    <td style="text-align: right; border-left:1px solid black;">${item.discount}</td>
                    <td style="text-align: right; border-left:1px solid black;">${item.discountAmount}</td>
                    <td style="text-align: right; border-left:1px solid black; border-right:1px solid black;">${item.total}</td>
        </tr>`).join('')}
        
        <!-- Total Row (Now Part of the Same Table) -->
        <tr>
            <td colspan="2" style="border-top: 1px solid black; border-bottom: 1px solid black; border-left:1px solid black; border-right:1px solid black; font-weight:bold; text-align:center;">
            Total
            </td >
            <td style="text-align: right; border-top: 1px solid black; border-bottom: 1px solid black; border-right:1px solid black; font-weight:bold;">
                ${totalQuantity}
            </td>
            <td style="border-top: 1px solid black; border-right: 1px solid black; border-bottom: 1px solid black;">
            </td>
            <td style="text-align: right; border-top: 1px solid black; border-bottom: 1px solid black; border-right:1px solid black; font-weight:bold;">
                Rs. ${totalDiscount.toFixed(2)}
            </td>
            <td style="text-align: right; border-top: 1px solid black; border-bottom: 1px solid black; border-right:1px solid black; font-weight:bold;">
                Rs. ${totalAmount.toFixed(2)}
            </td>
        </tr>
        <tr>
        <td colspan="4">
                <p style="text-align:left; font-size:11px;">Subject to AMALNER jurisdiction</p>
        </td>
        </tr>
    </tbody>
</table>
        <hr style="border: 1px solid black;position:absolute; bottom:40px; width:98%;">
        <p style="text-align:center; font-size:10px; font-weight:bold; position:absolute; bottom:5px; width:100%;">
            फॅशन के दौरान गॅरंटी की इच्छा ना करें<br>
            उत्पादक मालाची गॅरंटी देत नसल्यामुळे विक्रेते कोणत्याही मालाची गॅरंटी देऊ शकत नाही
        </p>`;

    billHTML += `</div>`;

    // Increment bill number and store it in LocalStorage
    billNumber++;
    localStorage.setItem("billNumber", billNumber);

    document.getElementById('billDisplay').innerHTML = billHTML;
}
<div class="column right-column">
    <button id="printButton" style="display: none; margin-bottom:0px;" type="button"><img src="img/printer.png" width="12" height="12"> <strong>PRINT BILL</strong></button>
    <div id="billDisplay" class="bill-display thermal-receipt" style="margin:0 auto;">
    </div> 
</div>

Please help me out to get rid of the extra white spaces added before , before


and after

as shown in the image]1 in the print preview. Thanks.

I tried adding the CSS externally but it is not working at all:

    @media print {
    @page {
        size: 10.5cm 15.5cm;
        margin: 0; /* Remove margins */
    }
    body {
        margin: 0;
        padding: 0;
    }
    .bill-display {
        width: 10.5cm;
        height: 15.5cm;
        overflow: hidden;
    }
    #title, h3{
        padding-bottom:0px;
        padding-bottom:0px;
        margin-bottom:0px;
        margin-bottom:0px;
        font-size:30px;
        text-align:center;
    }
    #address{
        font-size:15px;
    }
    #hr{
        padding-bottom:0px;
        padding-bottom:0px;
        margin-bottom:0px;
        margin-bottom:0px;
        font-size:30px;
        text-align:center;
    }   
}   

Trying to install ANY JavaScript Module/Package with PNPM ended up Failing

So, recently, i just install NodeJS on my system, i switch to PNPM because NPM is too slow, so i install it using the command:

npm i -g pnpm

then, i run pnpm -v, it says: 10.5.2, but, problem arise when trying to install any JavaScript Package via PNPM, when trying to install ErudaJS for example, it says:

Packages: +1
+
Progress: resolved 1, reused 1, downloaded 0, added 0


#
# Fatal error in , line 0
# unreachable code
#
#
#
#FailureMessage Object: 0xa4df874c
----- Native stack trace -----

 1: 0xfbdb20c  [node]
 2: 0x10efbe14 V8_Fatal(char const*, ...) [node]
 3: 0x10f08a3c v8::base::TimeTicks::Now() [node]
 4: 0xfeb7ff8 v8::internal::Compiler::Compile(v8::internal::Isolate*, v8::internal::Handle<v8::internal::SharedFunctionInfo>, v8::internal::Compiler::ClearExceptionFlag, v8::internal::IsCompiledScope*, v8::internal::CreateSourcePositions) [node]
 5: 0xfec274c v8::internal::Compiler::Compile(v8::internal::Isolate*, v8::internal::Handle<v8::internal::JSFunction>, v8::internal::Compiler::ClearExceptionFlag, v8::internal::IsCompiledScope*) [node]
 6: 0x104b3cec v8::internal::Runtime_CompileLazy(int, unsigned int*, v8::internal::Isolate*) [node]
zsh: trace trap  PNPM_DEBUG=1 pnpm install eruda

but, the weird thing is, when i install the “outdated” version of PNPM via Pacman package manager, which is 8.6.7 in my case, it works, I don’t understand, can someone help me with this Problem, oh yes, additional info:

  • System: Arch Linux
  • NodeJS Version: v23.7.0
  • PNPM Version: 10.5.2
  • NPM Version: 11.1.0

How to fix the Gradient on this ReactJS component?

I am trying to adjust the styling of a linear gradient I made. I have attached a picture of it. I want to make the white middle section bigger so when there are the 3 sections of red white red, then are all evenly sized. Whenever I try to adjust the “y” values in “start” and “end” all it does is change shade of my component and not the actual gradient itself.

import React from 'react';
import { Text, StyleSheet } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
const ZoneRideCard = ({zoneCardColor}) => {
  return (
    <LinearGradient
      colors={[zoneCardColor, '#FFFFFF', zoneCardColor ]}
      start={{ x: 0, y: -.1 }}
      end={{ x: 0, y: 1.1}}
      style={styles.container}
    >
    </LinearGradient>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 0,
    height: 140,
    width: 405,
    borderRadius: 10,
    alignItems: 'center',
    margin: 0,
    marginLeft: 25,
    marginTop: -45,
    marginBottom: 70,
  },
  
});

export default ZoneRideCard;

Linear Gradient with current values

After adjusting the Y values

closing a modal window in Javascript

I am trying to close a modal window after it has sent an email. At the moment i can get the form cleared but because the modal form is open I cannot see the message that the email has been sent successfully. Any ideas ? Thank you

<script>
$(document).ready(function(){
const dialog = document.getElementById("modalForm");
$('#quote-request').on('submit',function(e) {  //Don't foget to change the id form

$.ajax({
  url:'send-mail.php', //===PHP file name====
  data:$(this).serialize(),
  type:'POST',
  success:function(data){
    console.log(data);
     

    //Success Message == 'Title', 'Message body', Last one leave as it is
 $("#quote-request")[0].reset();
    swal("�Success!", "Message sent!", "success");
      dialog.close();
  },
  error:function(data){
    //Error Message == 'Title', 'Message body', Last one leave as it is
    swal("Oops...", "Something went wrong :(", "error");
  }
});
 e.preventDefault(); //This is to Avoid Page Refresh and Fire the Event "Click"
});
});
</script>

my data is being shown two times when change data

so i am trying to learn firebase , i have made a simple html file where i can upload topic and content ,
here is my code

this is index.html , i have used bootstrap

<!DOCTYPE html>
<html lang="en">
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>write data</title>
    <link rel="stylesheet" href="../css/vote.css">
</head>
<body>
    <div class="container mt-5">
        <div class="mb-3">
            <label for="gossip_title" class="form-label">What do u want to gossip about?</label>
            <input type="text" class="form-control" id="gossip_title" placeholder="">
          </div>
          <div class="mb-3">
            <label for="gossip_content" class="form-label">What do u want to say?</label>
            <textarea class="form-control" id="gossip_content" rows="3"></textarea>
          </div>
          <div class="col-auto">
            <button type="submit" class="btn btn-primary mb-3" id="gossip-submit">submit</button>
          </div>
          <div class="gossip-container"></div>
    </div>

</body>
<script type="module" src="../js/script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

</html>

and here is my js file

import { initializeApp } from 'https://www.gstatic.com/firebasejs/11.4.0/firebase-app.js';
import { getDatabase, ref, set, push, onValue , update ,increment  } from 'https://www.gstatic.com/firebasejs/11.4.0/firebase-database.js';
import firebaseConfig from './configs.js'


const app = initializeApp(firebaseConfig);
const db = getDatabase();

var gossip_submit = document.querySelector("#gossip-submit")

gossip_submit.addEventListener('click', (e) => sendGossip(e))

function sendGossip(e) {
    var gossip_title = document.querySelector('#gossip_title').value
    var gossip_content = document.querySelector('#gossip_content').value

    if (gossip_title == "" || gossip_content == "") {
        alert("Empty fields detected.")
        
        return
    }
    e.preventDefault()
    console.log("clicked")
    console.log(gossip_title)
    console.log(gossip_content)
    document.querySelector('#gossip_title').value = "";
    document.querySelector('#gossip_content').value = "";
   
    writeUserData(gossip_title, gossip_content)
}


function writeUserData(gossip_title, gossip_content) {
    var post_unique_key = push(ref(db, 'posts/')).key
    set(ref(db, 'posts/' + post_unique_key), {
        gossip_title: gossip_title,
        gossip_content: gossip_content,
        upvotes: 0,
        downvotes: 0,
        timestamp: new Date().getTime(),
        comments:{}
    });

}
// function updateUpvoteCount(post_unique_key) {
//         update(ref(db, 'posts/' + post_unique_key), {
//         upvotes: increment(1) 
//     })
// }


function getDataWithKey(key) {
    onValue(ref(db, 'posts/' + key), (snapshot) => {
        const data = snapshot.val();
        console.log(data)
    });
}




let gossip_container = document.querySelector('.gossip-container')
function getAllData() {
    gossip_container.innerHTML = '';
    onValue(ref(db, 'posts/'), (snapshot) => {
        const data = snapshot.val();
        for (const key in data) {
            console.log(data[key])
            let card_div = document.createElement('div')
            card_div.classList.add('card')
            let card_body = document.createElement('div')
            card_body.classList.add('card-body')
            let card_title = document.createElement('h5')
            card_title.classList.add('card-title')
            card_title.innerText = data[key].gossip_title
            let card_text = document.createElement('p')
            card_text.classList.add('card-text')

            let span_downvote = document.createElement('span')
            span_downvote.classList.add('downvote')
            span_downvote.innerHTML = '<svg width="36" height="36"><path d="M2 10h32L18 26 2 10z" fill="currentColor"></path></svg>'
            let span_upvote = document.createElement('span')
            span_upvote.classList.add('upvote')
            span_upvote.innerHTML = '<svg width="36" height="36"><path d="M2 26h32L18 10 2 26z" fill="currentColor"></path></svg>'

            card_text.innerText = data[key].gossip_content
            card_body.appendChild(card_title)
            card_body.appendChild(card_text)
            card_body.appendChild(span_upvote)
            card_body.appendChild(span_downvote)
            card_div.appendChild(card_body)
            gossip_container.appendChild(card_div)

            span_upvote.addEventListener('click', function () {
                span_upvote.classList.toggle('on');
                span_downvote.classList.remove('on');
                console.log('upvote:', span_upvote.classList.contains('on'));
                // updateUpvoteCount(key)
                console.log(card_text.innerText)
                console.log(key)

            });
            span_downvote.addEventListener('click', function () {
                span_downvote.classList.toggle('on');
                span_upvote.classList.remove('on');
                console.log('downvote:', span_downvote.classList.contains('on'));
                console.log(key)

            });
        }
    });
}


getAllData()

i am facing a problem ,

when ever i post new content or do upvote or delete a post from database, the whole container is being rendered twice , how can i fix it please help me