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.
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.
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.
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 profilepost
: 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'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
attributessdr:
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.
- 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
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...
- This will be null if
To visualise this, lets use Hacker News as an example as it's a very similar structure (at least in terms of outcome)