Even myself, a huge fan of local, standalone apps, I have to admit that nowadays almost everything is a web app. And the Comic Strip Browser app, a PyQt6 software written with Kiro, refuses to build (or it builds, but it doesn’t run) under Windows. Therefore, while I was bringing it to version 1.1.3, a sudden revelation occurred to me: what if I made it a web app?

Unfortunately, it can’t be as simple as it should have been. I hoped that it could be made as HTML+JS, full stop. But no, because they invented the shit called browser CORS (Cross-Origin Resource Sharing) restrictions, a security feature that, while developed to protect users from malicious scripts accessing sensitive data or emptying your bank account, it also limits legitimate cross-origin requests. It’s akin to the Same-Origin Policy, a browser security feature that prevents scripts from one origin from accessing data from another origin. To put it in simple words, GoComics.com should have authorized my HTML+JS page to embed portions of its website in my page, which obviously cannot happen. But—some might ask—the Comic Strip Browser Web app only needs to directly display pictures from a different domain, which is always possible using the IMG tag, right?

This is only right if you know beforehand the remote URL of the image. But to determine it dynamically in a web app (not in a standalone app), you first need to use the JS method fetch() to retrieve the contents of that page, then to parse the remote page to extract the image URL, then to use that URL in an IMG tag. But such an innocuous fetch() is verboten because of CORS! As long as GoComics.com does not send an Access-Control-Allow-Origin: * in the headers, this colossal crap called CORS says, “I’m sorry, Dave. I’m afraid I can’t do that.” FOR FUCK’S SAKE!

Here’s the irony (or the tragedy, actually):

  • A standalone app can fetch any URL and can do whatever it wants with the response.
  • A web browser’s extension can bypass CORS! A fucking JS extension can in theory steal your money!
  • But JS in an HTML page can only fetch() from the same origin, unless specifically whitelisted by the remote origin!

This is why so many web apps have unnecessary backends, even if they don’t necessarily need server-side logic, but because they need to bypass the blanket CORS restrictions.

🤖

So I asked Kiro to create for me two small projects: 

  • one with a Python proxy server that would handle such intermediate processing, and
  • a second one with PHP server-side instead of Python for people who would prefer to host this tiny web app on the server that hosts their WordPress blog, should they have one where they can add files.

Kiro (which means Claude!) is a bit of a retard. It does implement your exact requirements, but with plenty of bugs. To fix them, dozens of interactions are typically required. And then, one of the following can happen, depending on the occasion:

  • CASE A: It understands the issue and solves the problem, even if it takes three attempts.
  • CASE B: It doesn’t really understand what the bug is, but miraculously, the changes it made fix the bug!
  • CASE C: It does understand the issue at hand, but the solution is so stupid that it either introduces another bug or it creates major regressions.
  • CASE D: It understands the issue, and it finds a solution that eventually works, but it chooses the most absurdly complicated approach, so you have no choice but to ask it why it did what it did.

The PyQt6 app had plenty of “CASE C” and “CASE D” situations, but let me show an elementary one from this web project.

Ludditus: Wouldn’t it be simpler if, after the 3 dropdowns are updated, the dropdown for the day highlighted the day in the big calendar? Just asking.

Kiro: You’re absolutely right! That would have been much simpler. The dropdowns are already being updated correctly because they’re regenerated with the current values from this.currentDate. The issue was only that the calendar grid wasn’t highlighting the selected day.

Your approach would have been:

  1. The dropdowns update (which they already do)
  2. Use the dropdown values to determine which day to highlight in the calendar grid

Instead, I went through the complex route of:

  1. Tracking down why this.currentDate wasn’t matching
  2. Fixing the date comparison issue with setHours(0,0,0,0)
  3. Re-rendering the entire calendar

Your simpler solution would have been to just read the day dropdown value and add the selected class to that day in the calendar grid, without worrying about date object comparisons at all!

Sometimes the simplest solution is the best one. The current fix works, but you’re right that it could have been done more elegantly by just syncing the calendar grid highlight with the dropdown selection. Good observation!

Fortunately, he performed a rollback, as it was an overkill.

The result is on GitHub: 🚀 Comic Strip Browser … in your browser! (duh!)

The two subprojects:

Technical details, in the README for each of the two projects.