Documentation
Posts, Threads and Replies

Posts, Threads and Replies

The primary type of content in Storyden is the Post. A flexible way to represent:

  • Rich text written by members
  • Occupies a specific point in time, posts can be old or new
  • Part of the datagraph, holds relations to other kinds of content

The concept will be familiar to anyone who has used WordPress or other CMS platforms.

A thread with one reply

ℹ️

Screenshots of the reference frontend implementation are used throughout this documentation to illustrate concepts. These screenshots may fall out of date as the implementation evolves, but the underlying ideas will remain the same.

The Post resource is considered a primitive in the data model. Posts can come in different forms with different rules, but they share the same database table.

In this documentation, we'll cover the Storyden API specification's view on Posts, Threads and Replies. Though there will be some additional information about the underlying data structure.

Threads

A thread is what you'll see on a traditional forum, a post with zero or more replies. Threads are typically displayed on the main feed or under a category page.

A thread's content

Threads have some extra properties compared to replies:

  • Title: A thread may have a title, while replies do not.
  • Category: Threads live at the top level of the information hierarchy, so they can be organised into categories for browsing.
  • Tags: Tags provide a more granular way to categorise and link discussions.
  • Pinned status: Threads can be pinned to the top of a category or feed.
  • Additional metadata: How many replies are there? has the authenticated user replied?

The /threads endpoint is used to fetch a paginated list of threads, and it can be filtered by category, tag, or pinned status.

Threads contain the rich text body content of the post, but they do not contain a list of replies due to the potentially large size of the payload.

Replies

A reply is a post in reply to a thread. Replies can be nested, forming a tree structure. They can also be used to reply to other replies, similar to sites like Reddit or Hacker News.

A reply

Replies do not have a title, category, or tags. They are always associated with a thread and are accessible through the /threads/{thread_mark} endpoint.

ℹ️

What's a thread_mark!? See the documentation here.

Replies may also refer to another reply in the same thread, sort of like quotes on X or oldschool forums. This self-referential relationship allows for Reddit-style comment trees.

A frontend implementation is free to display these replies in a flat list or as a tree structure. The API does not enforce a specific way to display replies, it returns them as a flat list.

Likes, Reacts and Collections

Any post can be liked, reacted to and added to a member's collection.

Likes are the lowest form of interaction, a simple thumbs up. Reacts are more expressive, allowing members to choose from a set of emojis. Collections are a way to save posts for later reading or reference.

Each of these interactions is used by the Semdex to inform recommendations and feed algorithms.

Technical details

Body content

The chosen format for the body content of posts (and all rich text content within Storyden) is HTML. This allows for a wide range of formatting options and is easy to parse and display in a frontend.

<body>
  <p>hey southclaws!</p>
</body>

It also means frontend implementations (webapps, mobile apps) are free to include any custom data attributes or classes (see security section for information on XSS) in the HTML content. This can be useful for adding custom styling or functionality.

<a> References (@Mentions and other links)

Anchor tags in any rich text content may contain special URIs understood by Storyden as references to other resources. These references are used by the Datagraph to build a graph of linked content. The format is:

sdr:<resource_kind>/<resource_identifier>

The URI scheme is sdr: followed by the resource kind and the resource identifier in xid format.

Valid resource kinds are:

  • profile: Member profile
  • post: A post (thread or reply)
  • node: A library node

For example, you can mention a user with a href value of sdr:profile/<identifier>. In a body value, this looks like:

<body>
  <p>
    yo
    <a href="sdr:profile/crk0gvqfunp7891n7ah0">@odin</a>
    what&#39;s up
  </p>
</body>

When Storyden receives a post with this content, it will parse the URIs and look for any containing the sdr scheme. It will then use the resource kind (profile) and identifier (crk0gvqfunp7891n7ah0) to link the post to a profile. It will then dispatch a notification to the mentioned member, letting them know someone's talking about them.

This functionality can be used for any Datagraph items, such as library nodes or threads.

Security

The HTML content is sanitized on the server to prevent XSS attacks using the microcosm-cc/bluemonday package. The only exceptions to the built in policy are:

  • data attributes
  • sdr: scheme for anchor tags

Database model

The database model for posts is a single table with a polymorphic relationship to itself. This allows for threads to have replies and replies to have replies, forming a tree structure.

There are two columns that make this work:

  • root_post_id: The ID of the root post in the thread. This is the top level post in the thread, and all replies will have this ID.
    • If this is null, that means the post is the root of a thread, it will have a title and category and be listed in the /threads list.
  • reply_to_post_id: Replies may directly reference another post in the thread, this ID holds that reference.
    • This will be null if root_post_id is not null, threads cannot reply to another post.
    • If set, the reply is a reply to another reply. Confusing wording, I know...

To visualise this, lets use Hacker News as an example as it's a very similar structure (at least in terms of outcome)

Annotated screenshot of a Hacker News thread with a basic reply tree with lines showing the relationships