Skip to content

Thread identity

Every comment belongs to a thread, and Charcha works out which thread from the address of the page the comment was posted on. That derived value is the page key. Two readers have to land on the same key or they will not see each other’s comments.

Most of the time you will never think about this. The page is here for the times you have to, because a couple of the rules are opinionated and one of them catches people out.

Part of the URL Decides the thread?
Path (/notes/hello) Yes. This is the identity
Uppercase against lowercase in the path Yes. /Post and /post are different threads
https:// against http:// No
Domain, subdomain, port No
Trailing slash No. /post and /post/ are the same thread
?anything=here No
#section No

One Charcha deployment serves one site, so the domain carries nothing worth keeping. Dropping it makes example.com, www.example.com, the http:// version and localhost:4321 while you are drafting all one conversation, with nothing to configure. Move your blog to a new domain and the comments come with it.

If ?utm_source=newsletter counted, one post shared through three channels would become four conversations and none of the readers would see each other. Tracking parameters are unbounded and people keep inventing more, so every parameter is dropped.

That costs you something if your site uses the query string for real identity. /blog?page=2 and /item?id=42 collapse into a single shared thread, and there is no setting yet that keeps a named parameter. Give those pages an explicit thread id instead, which is the section below. If a parameter does become keepable later, order still will not matter: whatever survives is sorted before the key is built, so ?a=1&b=2 and ?b=2&a=1 cannot drift into two threads.

The one that will surprise you: case matters

Section titled “The one that will surprise you: case matters”

/my-post and /My-Post are two different threads.

That is deliberate. Web standards make only the domain case-insensitive, and static hosts really do serve /My-Post and /my-post as different pages, so folding them together would merge two real pages into one comment thread.

The rule behind that choice, and behind several others here:

Splitting one page into two threads is recoverable. Merging two pages into one thread is not.

A comment on the wrong key can be moved. Comments from two pages already mixed together cannot be told apart again. So Charcha splits whenever the answer is ambiguous.

In practice this only bites if your own links are inconsistently cased. There is no setting that folds two casings back together, so the fix is to make the links agree.

When the URL is the wrong identity, a page that moved, a paginated route, a post reachable at two paths, name the thread and the URL stops mattering:

<div id="charcha" data-thread="leaving-the-comment-industry"></div>

The value has to be ASCII, start with a letter or digit, and run to no more than 200 characters.

Explicit ids live in their own namespace and cannot collide with a URL-derived key. URL keys always begin with /, explicit ids are stored as id:<your-value>. That separation matters because data-thread arrives from the page like everything else, and without it a crafted value could be aimed at another page’s thread.

Once you set data-thread on a page, keep it. Take it away and the page goes back to its URL-derived key, leaving the existing comments behind on the old one.

Always. The embed reports the page address and nothing more. It cannot send a key directly, and nothing a browser submits can choose one Charcha would not have produced itself. Anything arriving from a page is attacker-controlled, and the key is unique across the database, so accepting one over the wire would let anybody graft comments onto any thread they liked.

Deriving it in one place has a second effect you benefit from quietly: a reader with a cached copy of an older embed still gets today’s rules rather than the ones that shipped with it.

The limits are enforced rather than advisory. A reported URL is capped at 2,048 characters, an explicit thread id at 200, and the resulting key at 512. A URL containing control characters is refused outright rather than cleaned up, and text is Unicode-normalised so that two identical-looking addresses cannot become two threads.