Funky: 806,893 Lines in 24 Days: What Happens When a Hackathon Swerves Into Madness

Published: (December 28, 2025 at 04:04 PM EST)
6 min read
Source: Dev.to

Source: Dev.to

How It All Began

This started as a $work hackathon project — the kind where you get a few days to prototype something and see where it goes.

The original idea was simple: build a UI to replace an unmanageable spreadsheet we were using for testing. Standard CRUD stuff really — forms, tables, the usual enterprise fare. Being 2025, and with “vibe” very much the trend, I naturally looked at the latest and greatest models and settled on Claude Opus to see what it could do.

The plan wasn’t to build just another CRUD app, but to apply a few modern practices along the way:

  • Real‑time updates via WebSockets (entirely unnecessary for the use case)
  • Proper keyboard navigation (who actually uses that?)
  • Full PWA and SPA capabilities — because why not over‑engineer things for fun

All of this while writing very little code myself and mostly just directing the train.

Then something clicked.

As I wired up the WebSocket connections, built modal dialogs, and implemented import/export logic, I stopped seeing a spreadsheet replacement. Instead, I started seeing the shape underneath it — the patterns every CRUD application needs but nobody wants to build from scratch:

  • The real‑time sync layer
  • The keyboard shortcut manager
  • The accessible focus‑trapping logic

The LLM’s code was not actually bad. I began to see what this could be.

So I started pulling those patterns out.

“Let’s just abstract this bit,” I told the LLM. “It’ll make the hackathon code cleaner.”

Then I abstracted another bit. And another. Then I added a custom virtual DOM, because why not; it took about an hour. I benchmarked it against direct DOM manipulation and promptly decided it was pointless in most cases.

The hackathon came, I talked a lot about the security aspects I had implemented with the LLM, and then I stopped building a spreadsheet app and started building the framework the spreadsheet app wanted to exist on. The hackathon project became the basis of the Funky framework.

What began as “let me add unnecessary WebSockets to a CRUD app” has so far turned into a JavaScript “framework” which consists of:

  • 74 components
  • 35 core modules
  • A custom testing framework running over 8,800 tests in real browsers

The Numbers That Don’t Make Sense

I debate to myself whether what I have built is good or not, but let me start with the stats that broke my brain:

MetricValue
TimelineDecember 4‑28, 2025
Total commits195
Lines added1,297,591
Lines deleted490,698
Net lines of code806,893
JavaScript266,551 lines
CSS46,670 lines
Components74
Core modules35
Documentation files127
Test suites858
Individual tests8,800+

Yes, I spend a lot of time on my computer, while I’ve also been doing actual work during that time. Those that have used an LLM know you can’t just let an LLM loose on everything as it’s not magic… however…

Using the industry standard of ~50 lines of tested, documented code per developer per day, this represents approximately 16,138 person‑days of work — that’s 64.5 person‑years. A team of five developers working full‑time would need 13 years to produce this.

Opus came up with those stats, and all of this was done in 24 days

The No‑jQuery Philosophy

Here’s a controversial opinion: you don’t need jQuery. You don’t need React. You don’t need Webpack, Vite, or Babel. You definitely don’t need npm install downloading half the internet just to render a button.

Funky is vanilla JavaScript all the way down. The development workflow is revolutionary:

  1. Edit a file
  2. Refresh the browser

That’s it. No build step. No hot‑module replacement. No watching your terminal for five minutes while Webpack does… whatever Webpack does.

“But vanilla JS is verbose and painful!” I hear you say.

Is it though? Here’s how you create a toast notification:

Funky.Toast.show('Hello world', { type: 'success' });

And here’s how you build a full data table with sorting, filtering, pagination, keyboard navigation, and accessibility support:

Funky.Table.init('#my-table', {
    data: myData,
    columns: myColumns,
    pageLength: 25,
    selectable: true
});

At times this seemed too easy — I rewrote a DataTables‑like component in a day. I’m fairly sure the original took a bit longer. Whether it is robust is another story; I have not used any of this code in a production environment, but I do have working examples and I don’t see many errors in the logs… It’s just JavaScript.

The Perl

Yes, the backend is Perl.

The language everyone assumes is dead but keeps climbing the Tiobe list.

The camel abides.

I’m using Mojolicious for the web framework, Minion for background jobs, and OpenAPI::Modern for API validation. It wouldn’t be possible without them. I have just glued everything together and added JavaScript so far.

I have lots more planned in the future, but for now my focus has been on JS.

PSPWA

PSPWA stands for Progressive Single Page Web Application.

Architecture

  • Progressive: Works offline, installable, push notifications
  • Single Page: No full page reloads, client‑side routing
  • Web Application: Not a document, not a website, an application

And it all runs without a compiled JavaScript framework. Just ES5, some discipline, and a lot of Claude conversations.

8,800+ Tests (In Real Browsers)

“You can’t test vanilla JavaScript properly,” said nobody who actually tried with an LLM.

The test runner executes in real browsers, not Node.js pretending to be one. No jsdom. No happy-dom. Actual Chrome, actual Firefox, actual Safari.

When we test keyboard navigation, we’re testing real keyboard events. When we test focus management, we’re testing real focus.

The testing philosophy is simple:

Run the code in the environment your users will run it in.

ComboBox Test

FunkyTests.describe('ComboBox', function() {
    FunkyTests.it('should open dropdown on click', function() {
        var combo = Funky.ComboBox.init('#test', { items: items });
        TestUtils.click(combo.element);
        expect(combo.isOpen()).toBe(true);
    });
});

Enter fullscreen mode

Exit fullscreen mode

You can, of course, run the tests under a headless browser for CI, but we recommend running them in real browsers during development to catch quirks early. I have a Perl script that does this via WWW::Mechanize::Chrome.

The Learning

Here’s what I learned from directing 800,000 lines of code in 24 days:

  1. Velocity without direction is just chaos.
    Claude can write code faster than any human, but without clear architecture and ruthless monitoring you end up with a mess.

  2. Tests are not optional.
    When you’re moving this fast, tests are the only thing preventing complete disaster. Git helps as well.

  3. Documentation that lies is worse than no documentation.
    We caught Claude documenting features that didn’t exist. Now we verify everything and/or force it to implement the feature it describes. Trust, but verify.

The Tagline

“Write less code. Ship more features. Sleep better at night.”

That’s the promise. Whether we’re going to deliver on it… ask me in another 24 days.

If you would like to learn more about Funky, visit the official website. This will be open‑source, but my vision is not yet finalised. I’ll keep you posted.

Back to Blog

Related posts

Read more »