News for hackers. Stuff that matters.

vicke4

Show HN: I made a white noise generator for my newborn

https://whitenoise.now/

White noise helps my baby sleep quicker and a little longer. All the available options online look like they were built in the 2000s.My biggest pain with those apps is setting timer takes more than 2 clicks and they don't remember my last setting.Now, with this app, one can simply swipe to set timer. Once loaded it works offline, installable as a PWA.Uses AudioContext web API to generate the...

( Read More... | no comments | 2 points | on HN )
Re:Position of Now in Time Visualised on Monday October 13, 2025 @03:55PM (#45572639)
Found this site online, the cookie banner ruins the experience. Tap on it to make it go away.
Hey HN,

Smart Bulk Renamer can bulk rename your local & cloud files. For now, Google Drive, Dropbox & OneDrive are supported.

Local file renaming works only on Chromium-based browsers because they can handle local files using the FileSystemHandle.move API [1].

Smart Bulk Renamer is heavily inspired by the Mac app "Name Mangler" [2].

You can try it without creating an account, and I’d love to hear your feedback!

[1] https://developer.mozilla.org/en-US/docs/Web/API/FileSystemH... [2] https://manytricks.com/namemangler/

Show HN: I built a web app to rename files in bulk

https://syncwithtech.com/smart-bulk-renamer

Hey HN,I built Smart Bulk Renamer to bulk rename files on Google Drive, Dropbox, OneDrive, or even local files directly from your browser. The idea came after I noticed many users on Dropbox forums were searching for a tool to automate file renaming. I expanded it to include Google Drive, OneDrive, and local files for broader utility.The tool leverages the non-standard FileSystemHandle.move API...

( Read More... | no comments | on HN )
Is it made using super.so?
Thanks! Sure, I'll look into the panel placement issue.
I can understand your concern. But, I need to comply with Google APIs Terms of Service. https://developers.google.com/terms#b_confidential_matters

> You will keep your credentials confidential and make reasonable efforts to prevent and discourage other API Clients from using your credentials. Developer credentials may not be embedded in open source projects

I meant that for a fixed purchase. I'm still contemplating setting up subscription plans.
Sure. Without open-source projects, I would not have been able to build Radar. So, I wanted to give something back for the incredible work open-source maintainers are doing out there. Hence, the statement.

You will find it on the pricing page when Radar comes out of beta. The only thing I'm confused about is what kind of criteria I have to set before giving a free license to the person who wants to claim the offer? I'd appreciate it much if any of you guys can help set the criteria.

> How about a $0 starter tier for max. of x monitors, with a max freq. of every y hrs... then move up to a one-time fee that is more generous, but still constrained, and finally have a monthly fee that allows unlimited.

Yeah! That seems like a nice strategy. Do you think people will be ready to pay subscription for unlimited access?

Would love to hear more about your fix.
I haven't finalised the price. But, it'll be more than $20 for sure.
Thanks! I will check the issue.
Thanks! I will check it out. Please get in touch using the support link in the landing page so that, I can let you know once I fix the issue.
Sure. Will do that.
Added a 1-click installer to check HN karma points.
It's 1 minute.
Yeah. But, I felt this is better than opening multiple browser tabs and losing focus. So, I built this.
Will add the Hackernews 1-click installer to check karma points ;)
How about the scriptable output? https://getradar.co/docs/customizing-value ;)
Thanks. I built it as a solution to my problem. Glad that you like it.
Right. The blog post explains how to set it up from scratch and the work put in for automating stuff.
Interesting! Do I need to have my own SES or Sendgrid account?
More readable version of the code:

( function () {

    // Exiting if the webpage is not Twitter or a valid tweet
    if (window.location.origin !== 'https://twitter.com' || window.location.pathname.split('/').length !== 4) return alert('This is not a valid Twitter poll!');

    alert("Please wait this can take up to 30 seconds. Select OK or close to get started. If this is a valid poll, you will get the result when it is ready...:)");

    // This string will hold our poll result
    let result = '';
    // This boolean denotes if our job is done and if true, doesn't execute the addEventListener anymore.
    let processDone = false;
    let oldXHROpen = window.XMLHttpRequest.prototype.open;
    const startTime = Date.now();

    window.XMLHttpRequest.prototype.open = function () {
      if (processDone) {
        return oldXHROpen.apply(this, arguments);
      }

      // onLoad event handler to intercept the Twitter API response to read the poll results.
      function listenEvent() {
        try {
          if (this.responseURL.includes('poll')) {
            // JSON from the Twitter API response
            // On a poll page every 30 seconds, Twitter hits the API to retrieve the latest poll results
            const pollResultJson = JSON.parse(this.responseText);
            const pollBindingValues = pollResultJson.card.binding_values;
            const resultObj = Object.keys(pollBindingValues).reduce(function (accum, key) {
              if (key.includes('_label')) {
                const label = pollBindingValues[key].string_value;
                const choiceNumber = key.replace(/\D/g, '');
                const voteCount = pollBindingValues[`choice${choiceNumber}_count`].string_value;

                accum.choiceVoteCountMap[label] = +voteCount;
                accum.noOfVotes += +voteCount;
              }

              return accum;
            }, { noOfVotes: 0, choiceVoteCountMap: {} });

            const { choiceVoteCountMap, noOfVotes } = resultObj;
            Object.keys(choiceVoteCountMap).forEach(function (label) {
              result += `${label}: ${((choiceVoteCountMap[label] / noOfVotes) * 100).toFixed(2)}%\n`
            })
          }
        } catch (e) {
          processDone = true;
          // For error reporting. Incase if the bookmarklet fails to work in future, people will be able to report...:)
          if (window.confirm("Something went wrong. Could you please report the issue?")) {
            window.open("https://www.syncwithtech.org/twitter-poll-result-wo-voting/", "_blank");
          }

          this.removeEventListener('load', listenEvent);
        }
      }

      this.addEventListener('load', listenEvent);

      // If result holds proper string, we need to stop listening to the event
      if (result) {
        processDone = true;
        alert(result);

        this.removeEventListener('load', listenEvent);
      }

      // If the page is a proper tweet and doesn't have a poll, we must stop listening to the load event. It happens after 40 seconds.
      if (Date.now() - startTime > 40000 && !processDone) {
        processDone = true;

        // To get feedback if it's actually a poll and the script fails to detect it
        if (window.confirm("Seems like it is not a valid Twitter poll. Press OK to report the issue if it is a valid poll and the bookmarklet failed to detect it.")) {
          window.open("https://www.syncwithtech.org/twitter-poll-result-wo-voting/", "_blank");
        }

        this.removeEventListener('load', listenEvent);
      }

      return oldXHROpen.apply(this, arguments);
    }
  }
)();

Older »