#ActivityPub 64 hashtags

Todd Sundsted

Polls are rendering!

screenshot of the latest emoji poll rendered on the ktistec server

I'm working to get all of the little visual elements available across the Fediverse to render in a usable way on Ktistec. When released, users will also be able to vote on polls.

#ktistec #activitypub #fediverse

Todd Sundsted
Release v3.2.3 of Ktistec

Release v3.2.3 of Ktistec includes two big features:

  • FEP-1b12 Group federation
    Improved federation with Lemmy and other forum-type servers. Ktistec supports community and thread follow/unfollow, as well as up-vote/like (down-vote/dislike is supported but there is no visual affordance for that yet).
  • FEP-9098 Custom emojis
    Support for viewing custom emoji in posts and on actor profiles. Ktistec does not yet support custom emoji creation and management.

The full changelog:

Added

  • Support for viewing custom emoji in posts and on actor profiles.
  • Actor type (Person, Group, etc.) overlay badges on actor panels.
  • Colored fallback avatars for actors without icons.
  • Support for robots.txt.

Fixed

  • Federation with Lemmy and other servers that support FEP-1b12.
    • Shared inbox support for local actors.
    • Serialization of Undo includes the undone activity.
    • Serialization of Like and Dislike does not.
  • Notify only once for an object's first received activity.

Changed

  • Accumulate metrics by hour for finer granularity.
  • Clean up presentation of public followers/following pages.

The next release will include support for Mastodon polls (FEP-9967).

#ktistec #crystallang #activitypub #fediverse

Todd Sundsted

I've improved federation support for Lemmy and other servers that support FEP-1b12 Group Federation.

I had to increase the number of available file descriptors on my personal server 4x because of the resultant inbound volume of ActivityPub activities! I liked a federated post and DOSed my server.

#ktistec #activitypub #fediverse

Todd Sundsted
Release v3.2.2 of Ktistec

The big feature in release v3.2.2 of Ktistec is pinned posts with support for the Mastodon Featured Posts collection. Federation works both ways—pin a post on Ktistec and it will show up as a pinned post on Mastodon and vice versa. When you refresh an actor profile, Ktistec also fetches and updates the actor's pinned posts. This is another small step in the direction of supporting all features that Mastodon-compatible client applications expect to access via the API. It's also useful in its own right.

The other major feature, which I posted a short video demonstrating here, is X-Ray Mode. X-Ray Mode is a developer and power-user tool for inspecting ActivityPub JSON-LD representations of actors, objects, and other content. Pressing Ctrl+Shift+X on any page displays the data behind the page—like an x-ray. You can:

  • Cached Version: View the local JSON-LD representation stored in the Ktistec database
  • Remote Version: Fetch and view the original JSON-LD representation from the source server
  • Navigation: Click on any ActivityPub IRI to navigate to that object
  • History: Use Alt+Left and Alt+Right to navigate through your viewing history

This feature is useful for debugging federation issues, understanding ActivityPub structures, and verifying how content is stored and represented.

Here's the full changelog for the release:

Added

  • Support for pinned posts and the Mastodon "featured posts" collection.
  • X-Ray Mode for viewing and navigating JSON-LD resource (actor, object, etc.) representations.
  • Back links on thread pages for easier navigation. (fixes #1)
  • License page for LibreJS compliance. (fixes #127)
  • Highlighting of recently fetched hashtagged posts.

Changed

  • Improved presentation of audio and video media.
  • Refactored theming/styling implementation.

The next release will focus on smaller features and bug fixes.

Enjoy!

#ktistec #crystallang #activitypub #fediverse

Todd Sundsted

I've streamlined theme development in Ktistec. The theming system uses a hierarchy of CSS custom properties and fallbacks. Theme authors can customize a theme at multiple levels:

Base Colors Only

Define only base colors like --text-primary, --bg-primary, --bg-input, --semantic-primary, etc. Derived colors will auto-generate using color-mix formulas. For example:

:root { --semantic-primary: #ffa500; }

From this one line, theme-appropriate colors like --bg-accent-code, --anchor-color, etc. auto-generate.

Base Colors Plus Derived Colors

Define base colors and derived colors. Derived colors use custom values when defined. Undefined derived colors auto-generate. For example:

:root {
    --text-primary: #333;
    --text-primary-2: #ff0000;  /* red for this specific shade */
}

Given this theme, derived shades like --text-primary-1, --text-primary-3, and --text-primary-4 auto-generate. --text-primary-2 is red.

The simplest possible interesting theme redefines the primary semantic color. The single line above (in Base Colors Only) would result in the following, with button color, link color, disabled, selected, and hover states all derived automatically:

screenshot of the setting page with the primary semantic color defined

These changes will be in the upcoming release. Existing themes will continue to work, as is.

#ktistec #crystallang #activitypub #fediverse

Todd Sundsted
Todd Sundsted
Release v3.2.1 of Ktistec

Release v3.2.1 of Ktistec adds support for bookmarking posts. This was so immediately useful I don't know why it took me so long to get around to it!

Pinned/featured posts are in the works for the next release.

The full changelog:

Added

  • Support for bookmarking posts.

Fixed

  • Invalidate user's sessions after changing password.
  • Ignore supplied languages that don't conform to expected format.

Changed

  • Upgrade Kemal.

In other thoughts... I'd like to make followed hashtags more consumable. I follow ~10 hashtags and: 1) it's hard to tell what's new, 2) it feels like they arrive in large batches that are difficult to digest, and 3) the reading experience is meh.

#ktistec #fediverse #activitypub #crystallang

Todd Sundsted
Release v3.2.0 of Ktistec

The major feature in v3.2.0 of Ktistec is thread analysis. The previous release, v3.1.2, added support for viewing threads from Lemmy communities. I follow the Open Source community, which leads to many large threads. The thread on FFMpeg and Google has 112 posts and is still growing.

Thread analysis helps me navigate these extensive conversations. It includes: top contributors, a timeline histogram, and notable branches.

The analysis applies several heuristics to identify interesting branches of the main thread. “Interesting” is subjective, but the algorithm currently looks for sudden bursts of activity and highlights those areas. Ktistec uses this to create a table of contents that links directly to those branches. Clicking on one of these links takes you to a branch-only view that focuses on the selected part of the thread.

It's fast—I anticipated needing to cache analyses, but analyzing a thread with over 400 posts takes only about 50 milliseconds on my production server.

Figure 1: Screenshot of the final design. Notable branches link to subsets of the thread.

This release also addresses an object visibility regression that was introduced in a previous version.

Full Changelog

Added

  • Thread analysis that displays key participants, a timeline histogram, and notable branches
  • New MCP tools: analyze_thread and get_thread
  • Focal point rendering support for image attachments

Fixed

  • Regression in object visibility affecting replies to threads

Changed

  • Enhanced MCP tool details for likes, dislikes, and announces
  • Improved cookie security.

#ktistec #fediverse #activitypub #crystallang

Todd Sundsted

I ended up with a solution that exaggerates the focal point offset from center to try to get more of the image around the focal point inside the container:

def normalized_focal_point
  return nil unless has_focal_point?
  x, y = focal_point.not_nil!
  norm_x = x / 2 + 0.5      # normalized x = x / 2 + 0.5
  norm_y = -y / 2 + 0.5     # normalized y = -y / 2 + 0.5 (y inverted)
  # push the focal point toward the edges so that more of the focused image is in view
  {
    exaggerate(norm_x),
    exaggerate(norm_y)
  }
end

private def exaggerate(value, strength = 0.75)
  centered = value - 0.5
  exaggerated = centered.sign * (centered.abs ** strength)
  (exaggerated + 0.5).clamp(0.0, 1.0)
end

Reading up on object-position and its use for focal point support in Mastodon and looking at examples in practice it doesn’t seem like the existing implemented approach works well (link). I'm open to better ways to do this, and I welcome course correction if I'm heading in the wrong direction.

#ktistec #activitypub

Todd Sundsted
Release v3.1.3 of Ktistec

There are two big features in release v3.1.3 of Ktistec: auto-approve followers and a new image viewer.

Auto-approve followers is conceptually simple ("the server automatically sends an Accept activity when it receives a Follow activity") but it required extensive changes to some of the oldest code in the codebase: the inboxes and outboxes controllers. I refactored inbox and outbox side-effect processing into independent services, which made it possible to support side-effects like auto-approve follow (and also auto-follow back), without having to go through the controllers.

A more significant change for me personally was replacing the lightGallery image gallery (an external dependency) with my own implementation. It's not as slick, and not as full of features—I wrote it in two days—but it is fully free software, and that's important to me.

Added

  • Add admin page for managing OAuth access tokens.
  • Add support for auto-approve followers. (fixes #26)
  • Add support for auto-follow back.

Fixed

  • Prevent triggering actor refresh when user is anonymous.

Changed

  • Replace "lightgallery" dependency with custom image viewer.
  • Set OAuth access token expiry to 30 days (previously expired after 24 hours).
  • Refactor inbox and outbox processing into dedicated processor services.

The OAuth changes set the groundwork for better support of the Mastodon API and the Fediverse clients that depend on it. Stay tuned!

#ktistec #fediverse #activitypub #crystallang