154 comments

[ 2.9 ms ] story [ 243 ms ] thread
(comment deleted)
From the website:

    "Doesn't use analytics = respects your privacy"

Meanwhile, Brave stopped this tracker:

    https://static.cloudflareinsights.com/beacon.min.js/vef91dfe02fce4ee0ad053f6de4f175db1715022073587
On a similar token:

>Doesn't use a server = no downtimes

Except there is a server, whatever and wherever it is behind notepadtab.com.

Is there anything in the HTML spec that tells browsers to always show a cached version a page if it can't be loaded the next time you try to access it?

I think PWAs might have something like that, but haven't tested it in a normal browser or tried building one.

HTML dictates how webpages should be structured and then rendered.

You're probably asking about HTTPS, in which case: No. The first rule about HTTPS is no caching, because you want to validate that what you see is from the server and you can't prove that with a cache.

Maybe the entire page could be a self-updating data-url?

edit: I tried this and common browser security no longer allows this type of thing. 10 years ago it may have worked.

Here:

  data:text/html,<body contenteditable oninput="history.replaceState(0,0,'%23'+btoa(document.body.innerHTML))" onload="if(location.hash)document.body.innerHTML=atob(location.hash.substring(1))">#SGVsbG8sIHdvcmxkIQ==
Beautiful. Beat me to it.

Much better than a relying on an HTTP response from someone else's computer.

Wonderful!

How can I silence the Firefox security error messages?

Unfortunately this doesn't work on FF due to security Uncaught NS_ERROR_FAILURE
I'm not getting anything like that, for some reason. I assume I changed a setting and forgot. (probably something to make bookmarklets work) Pasted in URL bar in a new tab, private browsing, FF version 126.0, up to date fedora, history doesn't save.
Also

> - Doesn't need cookies = immune to data loss by accident

How is this immune if you have to remember to save it manually? That seems much worse than relying on cookies. Sure you can maybe restore it from the browser history, but if cookies are not considered reliable, then the history even more so. It's easier to delete history than cookies.

While you might assume that Cloudflare "insights" is an advertising/analytics system, this is actually part of Cloudflare's anti-DDoS infrastructure. This "beacon" gets injected at random on Cloudflare-served HTML pages, to track you throughout your use of all Cloudflare-proxied sites, as an alternative to an evercookie in building a long-term reputation profile of "human browsing" for your browser.

This reputation profile is then used as part of the heuristic behind CloudFlare Turnstile's "Are you human?" checkbox.

This is why browsers that have NoScript enabled by default for all sites (e.g. Tor Browser), cause Cloudflare-proxied sites to throw endless security interstitials and never let you through, even when you disable NoScript for the protected website. Without reputation-profile data gathered from other sites, Cloudflare just sees a fresh browser profile making its first connection ever to some obscure site that nobody would ever actually visit as the first thing they do on a new computer. And so it thinks your browser is a (not-very-clever) bot.

I don't think it's possible for a site owner to opt out of this reputation-profile data gathering, while still relying on Cloudflare's DDoS protection.

However, I also don't believe that the data Cloudflare gathers via this route is sold to third parties. (Someone please correct me if that's wrong.)

Builds a persistent profile of you across the web… this is directly at odds with "Doesn't use analytics = respects your privacy"

I’m sure the author isn’t aware of it and it’s just an oversight, but still.

Why does a single static html file even need a CDN?

Probably not a CDN, persay, but is using Cloudflare Pages as a host. Hosts static HTML for free on CF's CDNs. I use it for all my sites.
"need", probably not.

But anything that can be served from a cdn is better off if it fits. From a latency and bandwidth efficiency perspective

Why does this static site need DDOS protection is the important question.

Hint: it bloody doesn't.

It doesn't matter that this is a static site; it matters what it's hosted on.

If this static site is sitting on a CDN or Github Pages or something, then sure, there's no need to mask its IP address.

But if this static site is hosted on a cheap VPS or on a home PC with a residential Internet connection — or generally, anything with a monthly bandwidth usage cap — then any teenager who learns its true IP address (and then checks out that IP address's provenance with a whois(1)) could decide to pay $5 to throw a botnet at it for an hour — just because they know they can take it down by spending enough of its bandwidth, and want to try it, to be able to brag to their friends that they took something down.

(Yes, teenagers today do that. The most DDoS-ed things in the world today are Minecraft servers — because teens like messing with other teens.)

---

Also, half of what makes Cloudflare useful for "DDoS protection" isn't actually its "bot fight" security system, but rather its caching layer combined with its lack of egress costs (at least until you get forced into their Enterprise billing.)

If you are hosting your content on e.g. a public S3 bucket, where you're billed for egress bandwidth, but where S3 also sends sensible long-expiry Cache-Control headers; and you put Cloudflare in front of that S3 bucket (even just Cloudflare's free-tier offering!); then suddenly your S3 bucket will only be serving requests for each resource a few times a day, rather than for every single request. 99.999% of the traffic to your bucket will be a cache hit at the Cloudflare level, and so will be only a conversation between Cloudflare and the customer, not between Cloudflare and S3. So, even in the face of a DDoS, your billing won't explode.

And the data that's collected here includes the full page URL-- which, in this case, includes the fragment and therefore whatever data is being "stored", at the time of capture.

This is probably beyond the author's control, but they shouldn't host it somewhere that can inject scripts outside their control (like Cloudflare) and then claim "privacy".

(The Cloudflare script makes a request to `/cdn-cgi/rum`, with the full page URL in its JSON payload at `timingsV2.name`.)

Neat idea. But it pollutes the browser history with every keystroke.
It doesn't for me. Looks like they're just changing the html anchor (# …) with a location.replace which isn't a redirect so shouldn't spam history. Edit: Nevermind. It seems only Edge behaves this way.
Happens for me in Firefox. I press 'Back' and it untypes the last character.
(comment deleted)
Oh, you're right, it does spam history in Firefox. Safari and Chrome too. I'm using Edge and it doesn't - theres just one entry in history.
it's not a bug, its a feature! Unlimited undos
And yet it does. Firefox on Windows 11.
"pollutes the browser history" or "provides infinite undo and redo"?
Nice idea. But looks like this is unreliable, with some indeterminate cut-off point after which it stops working. I created 100 paragraphs of Lorem ipsum which I pasted into the textbox. It didn't show any error, but when I pasted the URL into a different window, the textbox just shows 'undefined'.
probably the URL got cut off and the base64 got corrupt.
You could read back the url after each write to check the validity. If not valid, assume the limit has been reached and inform the user.
This is basically encoding(base64?) the <textarea> and putting it in the URL.

Its a neat idea, but I think theres a limit to how long URLs can be.

Ouch, that's bad :D Won't store too long texts.
It is at least compressed to make the most of the limit
(comment deleted)
base64 is the opposite of compressed. Does it actually apply compression before base64-encoding? Doesn't really look like it by watching the URL.
It’s actually compressed. It uses https://github.com/nodeca/pako and then applies base64. Try entering hundreds of "a" and you’ll see that the base64 doesn’t really get much longer.
What gave you that impression? I tried spamming "a" and the URL indeed did not get longer.

Reassuringly:

   function serialize(value) {
        if (value === '') { return ''; }
        const data = new TextEncoder().encode(value);
        const compressed = pako.deflate(data, { level: 9 });
        return Base64.fromUint8Array(compressed, true);
    }
it does get longer. rather than typing in aaaa copy and paste it and copy and paste that to grow exponentially
IIRC in theory it’s 2048 characters, but in practice it’s 2000 (at least in Chrome a few years ago when I toyed with Google Maps for food).
It's actually much longer, I was implementing a javascript bookmarklet and the old published limitations are not respected by much anymore, so you can shove a LOT of data in there.
Any thoughts how this works under the hood? Like @gurjeet said, every keystroke is a new url. But then how all this is stored? Will it scale? :D
It's stored in your history stack. I spent 15 seconds pressing the back button slowly becoming more and more horrified as I watched my characters disappear one by one.

You can see how it works for yourself by opening your browser devtools, opening the JS console, and typing

    window.location.hash = "test"
You should see a "#test" pop up at the end of your URL. Pressing back will not change the page, but will make that go away.
I made a very similar notepad tab. Only me and my girlfriend use it (since I don't market it or anything) but we've been using it constantly every day for about a year. I'm surprised it's not a default function of browsers to be honest - new tabs are such wasted space. Basically, every tab is the same document, it saves to the browser's cache locally so you don't lose anything when you close the browser. https://github.com/gth001/George-s-Notes-Tab-Extension
I play Simon's Tatham's puzzles from time to time to de-stress. I'm surprised it's not a default function of browsers to be honest - new tabs are such wasted space. How hard would it be to embed it in the new tab so everyone can enjoy some mental recreation?
(comment deleted)
Neat concept but pollutes the browser history and maximum length of 2048 characters defeats the purpose.

Can we use svg instead?

I created Ponder, which does something similar. Mine was inspired by the Alpha Smart, so it has 10 “files” and it saves to local storage, so it might not be loss proof, but I use it as a scratch pad and it works quite well.

https://github.com/codazoda/ponder

Here's what I use (as a bookmark):

    data:text/html,<body contenteditable style="line-height:1.5;font-size:20px;">
No save function obviously but this lets me open a new tab and dump some text.
Nice! I bookmarked it and I'm gonna start using it, thank you.

For a quick and dirty save, you can press Ctrl+P to open the print window/dialog and select "Save as PDF", or you can press Ctrl+S and save as a single HTML file.

Edit: to make the text cursor focus automatically when the page loads, you can add the autofocus attribute to the body tag.

Following might work to save as well.

     data:text/html,<html contenteditable onload="document.body.innerHTML = localStorage['text']" oninput="localStorage['text'] = document.body.innerHTML" style="line-height:1.5;font-size:20px;">
It will need a hostname or a page at least.

  Failed to read the 'localStorage' property from 'Window': Storage is disabled inside 'data:' URLs.
Dug into this for a bit, sadly:

> Webstorage is tied to an origin. 'data:' URLs have unique origins in Blink (that is, they match no other origins, not even themselves). even if we decided that 'data:' URLs should be able to access localStorage, the data wouldn't be available next time you visited the URL, as the origins wouldn't match.

While you can't save to localStorage as my sibling commenters have shown, greyface- down below in the thread posted a version that saves to the hash fragment of the URI. Saving to the (Data) URI has a benefit over localStorage of allowing you to save by bookmarking, which also enables you to save many notes, not just one.

I code-golfed greyface-'s code and made the text cursor autofocus on page load:

  data:text/html,<body contenteditable autofocus oninput="history.replaceState(0,0,'%23'+btoa(this.outerHTML))" onload="location.hash&& document.write(atob(location.hash.slice(1)))">#
dark mode:

  data:text/html,<body contenteditable style="line-height:1.5;font-size:20px;color:lightgray;background-color:black">
Seeing the replies to your comment, I have to ask: Notepad++ persists your unsaved notes, has dark mode and themes, is fast and lightweight... why insist on forcing text-editor-like behavior on the browser? It feels like a solution in need of a problem.
Sublime Text fits the “nameless notes” niche for me for similar reasons. It’s super speedy, has plenty of customizability, and has rock solid auto save+restore for unsaved text.
Can you restore a closed tab of unsaved text?
Not out of the box I believe, but I use a package from their directory to do just that.
> persists your unsaved notes

Except when you brainfart on the OS shutdown and choose the wrong answer.

But yes, I even do the culling every couple of months.

You should pick a text editor that doesn’t throw up a dialog when quitting then. I use CotEditor on macOS specifically for random notes, everything’s unsaved and some notes have survived dozens of reboots over a number of years.
> doesn’t throw up a dialog when quitting then

It doesn't! At least when I Alt+F4 it.

> everything’s unsaved and some notes have survived dozens of reboots

Yep, this is exactly how I use it.

But somehow that one time (note: it was on the shutdown) something went terribly wrong.

I wonder if your notes were borked out of session.xml, but the files were still available at AppData\Roaming\Notepad++\backup.

I've changed machines where the user profile was in a different location, copied my AppData, and replacing the old location in Notepad++'s session.xml was enough to restore my unsaved notes.

Nah.

Of course I tried everything (except looking in the shadow copy? Don't remember), but in the essence the shutdown triggered Save All workflow (somehow) and I responded with 'No'.

*weep*

>why insist on forcing text-editor-like behavior on the browser? It feels like a solution in need of a problem.

Because the browser is the operating system.

I might be only half joking.

I hear people say it a lot and I know what they mean but I just can't agree... to me an OS runs on hardware. (or virtualized hardware) Browsers run on an OS. If you have "boot to browser" the OS is still the kernel. Browsers are userspace.

It's like that saying "The difference between a boat and a ship is that a ship can carry a boat, but a boat can't carry a ship." And I know there is jslinux but at that point we're in a Turing tarpit where you can say that the Lua VM or wasm is "an OS" and the term is just a five-dollar word for "abstraction layer". Is a function call an OS? Come on.

(For myself) because 99% of my time is spent in an IDE or a browser, and there's less mental overhead for me to open a new tab and start typing than for me to open a new app and do so.
The IDE is literally a text editor. Why not hit file -> new file and write stuff in there?
For me it's the risk of littering in a project repo.

So I use Zim wiki instead: https://zim-wiki.org/

AFAIK all editors and IDEs I've ever used can open a random file in a new tab, even if it is outside of the repository.
Because "random human-language notes" are conceptually different from source code for me.
Right? I use the gnome default editor for this. Also persists unsaved notes, its always available and has some few basic features that sometimes come in handy (regex match, etc)
Hehe, that's one of the reasons I made write.sonnet.io a few years back. It's a never-ending strip of paper/stream of consciousness.
Cool concept but I would never use it. It's an archetypal example of the web being the champion of "worse is better." I am happy with just taking notes in a local text file using a text editor. This is not a complicated problem to solve.

Save notes by copying and pasting the URL? Why not just copy and paste the text itself? I don't need formatting in my notes.

I used to use VSCode for this but then they went and effed it up by adding so much spam to the app. If I happened to have an SSH open connection previously, it just reconnects to that and makes me wait, and then I have to press buttons to get back to a blank local workspace. Or sometimes it like splash up a "We added a bunch of features you didn't need" page. Ugh.
This got me thinking... someone should build a local service that hosts a library of static web apps for use cases like this. Essentially, apps that are something between bookmarklets and Electron apps. Might even make Electron unnecessary for a bunch of use cases.

It would be neat to visit /app/notepad, /app/kanban, /app/todo, etc. at a localhost port, with an index of apps at /. There could even be a /get-apps page that connects to an npm-like library of single-HTML-file apps available for download from a github.io static site backed by a public repo that accepts pull requests.

I'd love to see all the VC-funded glorified desktop utilities on the web become unnecessary.

How about a native app collection called "Sidekick", which has a Borland bent?
Thinking about this more - this might be a perfect use case for Redbean. Backend mini-app user data could be stored in SQLite. The server could store the actual apps' static files in its internal zip archive. All of that could easily be managed with a sprinkling of Lua.

The mini-apps could store data in localStorage, but that would expose the data to other mini-apps. Maybe build an easy API that functions nearly equivalently against a Lua endpoint.

This might work....

...But I've not worked out how to get RedBean serving up files outside of the zip... I'll get there.

P'raps LUA could manage the security for different static apps.... as you say.

I'm not saying Redbean should serve files outside of the zip. The mini-apps would all be located inside the zip.

When downloading a new mini-app, the Lua script would add it to the zip archive itself -- it can do this as far as I can tell.

Do you actually need a local server? Why not have a real url, but have the site use service workers to persist offline?

The only issue I see is if you clear your browser’s cache while offline

I'm not a web dev so I might be missing something. Theoretically you could just open .html files directly in the browser without any networking being involved, no?
In the past, yes, and you still could if you use old enough features, but nowadays browsers heavily restrict sites opened as just .html file. For example you could not use modules at all if they're in separate files.

That is at least until we get Isolated Web Apps and what ever the other proposals related to it alö called.

Is blocking access to local files a new thing? Considering the threat (you download a html file, open it in your browser and it tries accessing random files and exfiltrates them using JS), I would be surprised if this has worked in the past 10 years
You should be able to whitelist such files. After all the browser is supposed to be your agent, not your nanny.
The problem with these supposedly local, private web apps on other people’s domains is that they can start stealing your data any time the page is refreshed. The author can turn malicious (or was malicious to begin with), they can sell the app or let the domain expire, or they can be hacked. The only way to prevent that is to firewall/null route that domain entirely after initial load and audit, and then you can’t ever refresh the page.

The web platform simply doesn’t allow you to verify the checksum of an app and reject all further requests.

> The only way to prevent that is to firewall/null route that domain entirely after initial load and audit, and then you can’t ever refresh the page.

I mean, at that point, why not just grab the files are host them yourself?

Well that’s exactly the point. Having a directory of these static files you can self host with eyeballs on updates would be great.
A late edit for a brain fart: “and then you can’t ever refresh the page” should be removed since it can be served from service worker cache. You can’t refresh the page while allowing a connection to the server.
You're going down the todo-app / "second brain" rabbithole, which generates at least a few "start-ups" every month.
The deeper version of this is finding out about smalltalk and realizing that you could make a very configurable system that you could edit on the fly.

Salesforce is basically a smalltalk VM and dominates thanks to that

In what way is Salesforce a Smalltalk VM?

And if it is, why does it dominate "thanks to that"?

If you open up salesforce you have all these resource types and pages, but it's all fully customizable. There's a built-in programming language with many affordances to work in a dynamic environment (stuff like handling API changes), and you're basically able to point at a thing and get a breakdown of what it's like.

On top of this third party developers can build in stuff that is more or less first class to the system, and it can run on the third party systems but you can get away with using Salesforce's "compute". So you're shipping software for the Salesforce VM, so to speak.

I would recommend playing around with the system to see what's going on.

(comment deleted)
> Essentially, apps that are something between bookmarklets and Electron apps.

You're talking about progressive web apps. MacOS / iOS / Android have them, and I started using them more recently. Essentially, they're just webviews wrapped in a native app.

PWAs have nothing to do with web views or native apps. They're just a collection of technologies (service worker, caching API, platform APIs, home screen installation, etc) that makes it possible to have offline available web apps that have a shortcut on your desktop/home screen. There is no web view or native app (outside of your default) browser involved.
On a related note I wish there were an easy way to deelectronfy electron apps. I don't know, perhaps some sort of patch you could apply to get it to act like a normal web app. and a local server to provide the file access.

Mainly I am bitter because nobody has ported electron to openbsd yet, cross platform my ass.

Tiddlywiki - the poster child for a complex app delivered as a single LOCAL web page.
Why would I use that instead of OS native apps? I am failing to see the usecase / appeal.
One reason is because these minimal HTML-based apps would be extremely lightweight (just a few kb each), easy to author, and easy to change.
Coming back to this a few days later... it looks like the fastest way to implement this idea is to host a local TiddlyWiki instance. There are so many TiddlyWiki plugins that fit so naturally into the ideas I had above -- kanban, todo, and the wiki itself, among many others.

I tried this Ruby script for local hosting and it's working great for now: https://gist.github.com/jimfoltz/ee791c1bdd30ce137bc23cce826.... Just make sure you have wiki.html located alongside the script, and navigate to /wiki.html.

The next evolution would be to get it running in RedBean reliably - and maybe even get it saving Tiddlers to the built-in SQLite instance. Simon Willison's work on saving Tiddlers to SQLite in Python might be a good reference: https://github.com/simonw/datasette-tiddlywiki

just use apple notes or equivalent?
Or Text Edit, Notepad, Gedit, vi… the most basic text editor the OS has.

This is a solution for a problem that was solved 40 years ago.

Whats the use case for this? What computing platform doesn't have a text editor, but does have a webbrowser? Or are we just conditioned to use a web browser for everything?
Maybe they misunderstood the site and thought hacker news was related to the hacker ethic of building stuff.
My exact use case was this: I created a tab group in Safari for working on a website, and wanted to jot down some to do items related to that project, and a tab in that tab group made the most sense.

I didn't want to write them down in a text editor, because they wouldn't have been bound to my context anymore.

Hope my explanation makes sense.

Fun fact: I saw people taking notes in translate.google.com for the same reasons that I created notepadtab.com.

Why does this even need a server?
Here's a version that doesn't need a server. Just save as an HTML file and open it in a browser (either localhost or on a fileserver somewhere).

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Note App</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
            textarea { width: 100%; height: 80vh; padding: 10px; font-size: 16px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; }
        </style>
    </head>
    <body>
        <textarea id="textarea" placeholder="Write your notes here..." autofocus></textarea>
        <script>
            document.addEventListener('DOMContentLoaded', function() {
                const textarea = document.getElementById('textarea');
                const loadValue = () => {
                    const hash = window.location.hash;
                    try {
                        const value = hash ? decodeURIComponent(atob(hash.substring(1))) : '';
                        textarea.value = value;
                        textarea.selectionStart = value.length;
                    } catch (e) {
                        console.error('Error decoding hash:', e);
                        textarea.value = '';
                    }
                };
                const storeValue = (value) => window.location.hash = '#' + btoa(encodeURIComponent(value));
                textarea.addEventListener('input', () => storeValue(textarea.value), false);
                window.addEventListener('hashchange', loadValue);
                loadValue();
            });
        </script>
    </body>
    </html>
Neat! Couldn't but ask myself why the OP should need Ruby...
This does not scale well.
It doesn't. Registering a dedicated .com domain is an overkill for this as well.
should have called it *scratch* imo
Tiddly Wiki?

I stumbled upon tiddly desktop, an app that runs tiddly wikis without a browser.

(comment deleted)
at first, i thought, "if this doesn't use a server, then how..." - then i started typing and watched the url change. amazing!