Threads
Loading…
counting.gg
BLOGMajor changes to counting.gg!

Major changes to counting.gg!

by pullAugust 8, 2026
changelog

Hello! A bunch of changes just dropped on counting.gg, so many that I'll probably forget to mention most of them. Most evident is the redesign of the site, although many pages kept a similar format. The frontend was rewritten to support server-side rendering, which is something I've wanted to do since late 2023, and even had a sample project of, but never actually got around to finishing. It's finally here and adds fun new capabilities.

Please report any issues you find on our Discord or at the new /feedback as I probably don't know about them.

Changes

Embeds

We can now actually embed content about the page for it to appear on sites like Discord! Before, I had a friend set up a server for previews. It's much easier with the new setup and doesn't require a separate server.

Example embed:

Replays

Replays are now much less jankily implemented. Check it out! They have a dedicated page and even have a scrubber. They compute pace stats and show mistakes (and an estimate of how much those mistakes cost). These are also now linked from the socket on the "Splits" tab. Replays are capped at 5000 posts.

Split timer

I added an optional timer feature to the "Splits" tab which shows how many counts ahead/behind you are of a self-assigned pace. This probably has bugs in it, but we'll fix 'em as we find them. The counts themselves also show this pace in green/red so you can see it visually.

/r/livecounting integration as a normal "thread"

We now use the same thread layout for /r/livecounting as other threads, and it appears on the sidebar alongside normal threads. Some prefs and features are disabled, e.g. the 333ms rate limit applies and only "Autopaste" textbox behavior is applied. I may add noclear support without keep/delete, or just unnerfed noclear. The daily leaderboard that MNW publishes now appears in the "Stats" tab, LCE username colors now apply, the login should last longer, and the sidebar now mirrors the actual sidebar on the source thread.

Autopaste buff

The "Autopaste" pref got a buff in that you can choose which position your cursor will land after posts now. This is useful for threads like Time, Dates, and Coordinates.

Bingo

I added the bingo section, but we still don't actually have enough challenges to seed any difficulty levels, so we can't even start any games yet. This still needs more testing, but let me cook, this WILL be dope!

Profile editing

I added a small section on your profiles where you can put in anything* you want.

Feedback section

I vibecoded a "feedback" section where you can submit bug reports and feature requests which can be voted on.

Default post format change

It's now much more like the "LC" post style, but with a different font, and it shows profile pictures. Counts also use a mono-space font in this mode.

New prefs

Added a couple of new prefs, e.g. "count font size".

Emotes

You can now type :emote: in the text box and a picker shows up, similar to Discord. I now have the ability to upload emotes to the site dynamically as well! I'll probably grant one-time use emote slots as some sort of reward or shop purchase, too.

Registration

I loosened registration requirements and checks. You can sneak an alternate account in easier now! It's still against the rules, but these checks were blocking legit members from joining too often, but false positives should happen much less frequently now.

Front page

Daily counts

You can now select Daily, Month (since start of month, not 30 days), Year (since start of year, not 365 days) and All. These should live-update.

Thread counts today

These now show the latest count, as well as the increase since you first loaded the page.

"Counting Park"

A new background that isn't the boring blue color it was before. You can click the sign to enter into a special mode where you just see the background. There are a few easter eggs here!

  • The background changes with time of day. CuteBallGames acts as the sun and moon.
  • There's now a safe here... which is used for the "Rob" functionality. "Robbing" also no longer shows you how much money is in the bank before you rob (OK this is probably leaked somewhere temporarily, but I'll patch that), so it's "riskier" now, since you still only get one per day.
  • All counters with posts today have icons on the "grass", which is just a green gradient, sigh.
  • There is a tree which grows with daily activity. I haven't done anything interactive with this yet, but probably will later.
  • The Shop now has community-funded items that will appear here. They are too expensive for one person to grind, but this is probably a better use of money than most individual items that nobody uses.

Why I switched to SSR

SSR is ideal for static sites and one of the last recommendations for a "chat" site (as this basically is a chat app). Swapping over is questionable, but it'll be worth it.

  1. It should be faster on first load, especially for users who live far from the server (which is in Ashburn, VA, USA, at the moment). It should also send less data over for people who want to use less data. Navigating between pages may be slower in some cases, though.
  2. Content that relies on UI can avoid "flashing". The old site worked by showing the "skeleton" view for all components by default then filling in with details as they arrived (e.g. whether we are logged in or not). Now we know immediately. Stuff like dark mode overrides also would "flash" their default state before updating to reflect your prefs, but now we can avoid that, for the most part.
  3. Embeds. Embedding content becomes much easier. Now we can show fancy stuff e.g. replay embeds.
  4. Greater ability to make "hidden" client-side content. I understand this isn't ideal as a user, but I'll mostly use it to hide surprises/easter eggs, instead of ill-intentioned purposes, except I'm collecting metadata about inputs for legitimacy validation... yay. Of course I still did server-side validation on the old site, but frontend components themselves should be able to be permission-scoped properly.
  5. Indexing. Now some pages I have set to not be indexed, so we won't index every single count. But this is nice for discoverability as the site was basically undiscoverable before aside from word of mouth. Now it's a skill issue on my part and a naming issue... nobody will ever find this site searching "counting" but at least it should be google-able soon!
  6. It was easier thanks to both vibe coding (🥀) and already having a mostly-working proof-of-concept from over 2 years ago. But it also introduced a lot of new bugs sigh. I'll try to resolve them as they come up.

Database migration (2026-08-08)

I did an unrelated database migration at the same time, which changes the primary key of the Post table to be the numeric ID rather than the UUID, since this is supposed to have a ton of benefits. I also now index on the first 8 characters of the UUID instead of the whole thing to save space.

Wow this migration was stressful.

This saved a lot of money in storage costs, but the cutover took longer than expected, primarily due to using the default mysql configuration for innodb_ddl_buffer_size which only allots 1 MB, making one step take over five hours! I wasn't aware of it at the time and it took a while to understand why it was going so slowly. I ran the same migration steps on my local computer and it took around an hour, but I had different mysql setting locally that I didn't add to my VPS.

This migration also required swapping to a new Volume on Hetzner as you can't decrease the size of previous volumes, but also required increasing the size of my existing volume since many mysql ops require 2x the amount of space, or more, to run the needed commands. Also discovered that my VPS setup would now cost $50.99 per month... luckily I have grandfathered pricing for much lower, but oof... and that can go away at any time too...

After both the database migration as well as the SSR migration, many issues surfaced, many major ones that I didn't catch! For one, there was no indication client-side when connection to the server failed, so it appeared like resources simply didn't exist... and that we logged out. Then, as SSR changes how cookies work, everyone was logged out and was sending two separate connect.sid cookies, which broke some auth workflow in the websocket, meaning for some cases people couldn't post after they logged in. A few more minor issues surfaced, but everything seems to be running relatively smoothly now, hooray!

Next priorities

What do you want next?

I'll probably more challenges / ranks to threads, and improving the implementation of it.

← All posts