This repository has no description
README.md

EffemKit #

Swift client for the Effem AT Protocol AppView. Provides social podcasting features — subscriptions, comments, recommendations, bookmarks, curated lists, and profiles — built on the AT Protocol.

Requirements #

  • Swift 6.2+
  • iOS 26+ / macOS 26+ / watchOS 26+ / tvOS 26+

Dependencies #

Installation #

Add EffemKit as a dependency in your Package.swift:

dependencies: [
    .package(url: "https://tangled.org/@sparrowtek.com/EffemKit", branch: "main"),
]

Or add it as a local package in Xcode.

Quick Start #

1. Configure the AppView #

import EffemKit
import CoreATProtocol

// At app launch
Task { @APActor in
    setup(appViewHost: "https://appview.effem.xyz")
}

2. Read Data #

@APActor
func loadTrending() async throws -> [PodcastResult] {
    let service = EffemService()
    let response = try await service.getTrending(max: 20)
    return response.feeds
}

3. Write Data (requires authentication) #

@APActor
func subscribe(feedId: Int, userDID: String) async throws {
    // Resolve the podcast's canonical catalog strongRef first so every
    // subscriber points at the same catalog row.
    let resolution = try await EffemService().resolvePodcastSubject(feedId: feedId)
    _ = try await EffemRepoService().subscribe(to: resolution.subject, repo: userDID)
}

Architecture #

EffemKit uses a two-router architecture:

Path Service Target Auth Required
Read EffemService Effem AppView No
Write EffemRepoService User's PDS Yes

Reads go to the Effem AppView, which indexes social records from the AT Protocol firehose and proxies Podcast Index metadata enriched with social overlay data.

Writes go to the authenticated user's PDS using standard com.atproto.repo.createRecord / deleteRecord calls. The AppView picks up new records asynchronously via the firehose.

All public API is isolated to @APActor for thread safety.

API Overview #

EffemService (Read) #

Category Methods
Subscriptions getSubscriptions, getSubscribers
Comments getComments, getCommentThread, subscribeComments (live websocket)
Recommendations getRecommendations, getPopular
Lists getList, getLists
Bookmarks getBookmarks
Episode State getEpisodeStates
Inbox getInbox
Profiles getProfile
Blocks getBlocks
Catalog resolveEpisodeSubject, resolvePodcastSubject, getEpisodeRecord, getPodcastRecord, describeLexicons
Notifications listNotifications, updateNotificationsSeen, getNotificationPreferences, setNotificationPreferences, registerDevice, unregisterDevice
Podcast Search searchPodcasts, searchEpisodes
Podcast Metadata getPodcast, getEpisodes, getEpisode, getTrending, getCategories, getRecentEpisodes, getStats

EffemRepoService (Write) #

Category Methods
Subscriptions subscribe, unsubscribe
Comments postComment, deleteComment, likeComment, unlikeComment, setThreadgate, deleteThreadgate
Episode State putEpisodeState, deleteEpisodeState
Boosts boost
Blocks & Reports blockUser, unblockUser, reportContent
Recommendations recommend, unrecommend
Bookmarks bookmark, removeBookmark
Lists createList, deleteList
Profile updateProfile

Lexicon Namespace #

All Effem records use the xyz.effem.* namespace:

  • xyz.effem.feed.subscription
  • xyz.effem.feed.comment, xyz.effem.feed.commentLike, xyz.effem.feed.threadgate
  • xyz.effem.feed.episodeState
  • xyz.effem.feed.boost
  • xyz.effem.feed.recommendation
  • xyz.effem.feed.bookmark
  • xyz.effem.feed.list
  • xyz.effem.graph.block, xyz.effem.moderation.report
  • xyz.effem.actor.profile

Documentation #

Build the DocC documentation:

swift package generate-documentation

Or in Xcode: Product > Build Documentation.

Testing #

swift test

38 tests across 12 suites covering model decoding, round-tripping, serialization, websocket event decoding, and record shapes.