catskull.net

The Most Dangerous App I've Ever Built

Preamble

“I wonder how hard it would be to build a chat app for my blog in 2025?”

At this point, if I’m going to write some front-end JavaScript, I’m going to build a web component. I simply have no appetite nor desire to npm install anything on the client. As for the back-end, I usually reach for a Cloudflare Worker since their free tier is more than enough to get my hands dirty with.

Fortunately for me, they have an example Durable Object I just ripped off! A “durable object” is a Cloudflare idea - essentially it’s just a Worker and a D1 database. I think really it’s just a special config for Cloudflare under the hood to run your worker and your D1 instance next to each other, but I’m not an infrastructure engineer. At the end of the day, it gives you some compute and some SQL storage so you can quickly and easily build stateful apps.

I quickly forked their example and had it running on my own account quickly. The issue? The example is using “PartyKit” on the client and server, which is a cool, but custom wrapper around websockets.

As I mentioned before, I would rather puke than npm install react, so I quickly threw away their entire front end. Well, who would have thought that a basic chat app can be implemented as a simple web component with 0 external dependencies? No way - that’s illegal. You have to use at least one special thing like Lit. Well, I didn’t. Meet me in the chat, it’s going down.

Little Chat

Want your own little chat?

little-chat Click to copy
<little-chat></little-chat>
<script src="https://catskull.net/public/js/components/little-chat.js"></script>

And here is the entire poorly written JS for the component. Make sure to view on GitHub for the latest version.

little-chat.js </>
class LittleChat extends HTMLElement {
  constructor() {
    super();
    this.socket = undefined;
    this.messages = [];
    this.color = Math.floor(Math.random() * (360 - 0 + 1) + 0);
  }
  
  renderMsg(msg) {
    return `<div class="message" style="--hue: ${msg.user}; color: light-dark(oklch(0.72 0.15 var(--hue, 70)),oklch(0.72 0.15 var(--hue, 70)));">${msg.content}</div>`
  }

  render() {
    this.innerHTML = `
      <div class="messages" style="max-height: 400px; overflow-y: scroll; border: 1px solid; padding: 1rem;">
        ${this.messages.map(msg => this.renderMsg(msg)).join('')}
      </div>
      <audio id="notification-sound" style="display: none; visibility: hidden;"  src="/assets/aim.ogg"></audio>
      <form>
        <input type="text" placeholder="Add a message..." size="50">
        <button type="submit">Post</button>
      </form>
    `;
    this.querySelector('form').addEventListener('submit', (e) => {
      e.preventDefault();
      const input = this.querySelector('input');
      if (input.value.trim()) {
        this.addMessage(input.value.trim());
        input.value = '';
      }
    });
  }

  idk() {
    this.socket = new WebSocket(`wss://little-chat.degraw.workers.dev/parties/chat/${location.hostname}`);
    this.socket.addEventListener("message", (event) => {
      const json = JSON.parse(event.data);
      if (json.type === 'all') {
        this.messages = [...this.messages, ...json.messages]
        this.render();
      } else if (json.type === 'add') {
        this.messages = [...this.messages, json];
        this.querySelector('.messages').innerHTML += this.renderMsg(json);
      }
      this.querySelector('.messages').scrollTop = this.querySelector('.messages').scrollHeight;
      this.querySelector('#notification-sound').play();
    });
  }

  connectedCallback() {
    this.idk();
  }

  addMessage(message) {
    const msg = {"type":"add","id":crypto.randomUUID(),"content":message,"user":this.color,"role":"user"};
    this.socket.send(JSON.stringify(msg));
  }
}

customElements.define('little-chat', LittleChat);

Huge, major, incredibly big shout-out deserved to Carter for cooking up some sweet, sweet CSS magic to get the chat messages a unique color that also contrasts well on both light and dark schemes. This is a suprisngly unsovled problem in CSS… until now? Maybe Carter will share his wealth of knowledge with us at some point, but for now study this code.

Dangerous?

How could a simple, anonymous text-only chat app such as this possibly be dangerous to the public? Some would even say it’s irresponsible to release something like this.

The free-market has a nightmare. Worse than recession. Worse than war. Legislation. Legislation is the only means by which we, the people, can constrain the unbridled passions a purely capitalist endeavor intuitively seeks out. The Children’s Online Privacy Protection Act of 1998, commonly referred to by “COPPA” is the bane of any supposedly well-meaning profit-seeking internet communications service companies. What encompasses “internet communications”? Video games, social media, email, anywhere people are communicating digitally.

Simply providing a platform for individuals to chat in plain text, with absolutely no identifying information, is considered hazardous in 2025. How sad! Does that mean the criminals have won?

No, they have not.

Embracing user-hostile development

Turns out complying with legislation is pretty simple if your a normal, non-evil, non profit-seeking individual. I am not building apps to entice you to use. I approach my personal application development as user-hostile. Hostile, that is, to anyone but pretty much myself. If you want to use it, that’s ok (unless you are under 13, then gtfo). Oh you want a feature like DM’s? Literally, go frick yourself. Why do you want DM’s? You pathetic weasel. Go build DM’s and you can deal with the consequences. You want rich media? No. Text is enough. More than enough. Too much, even.

I have no incentive for you to use my apps. I don’t make money. Fame? lol. So just chat, if you want to.

I’m too lazy to store any of your personal information, and I’m too poor to store your messages forever. I only store the latest 500 messages, and I will probably tone that down.

So there you go. When you’re poor and ethical, complying with random legislation is fun and easy and actually makes your life easier. Don’t let the criminals convince you it makes your life worse. They just want to track little kids and make money doing the things they do, who knows why.

Also - don’t abuse online services. Don’t be a jerk. Just knock it off. Criminals make everything so much worse. We don’t need to let them make our lives worse.

I want you

I build apps for me - and for you! Not for them. I want you to use it. I want you to chat. Just have fun!

Meet me in da chad!