Getting started
Install the SDK, configure it for your AT Protocol session, and make your first call.
The SDK is TypeScript-first but ships dual ESM + CJS, so any modern Node, Bun, Deno, or browser bundler can consume it.
Install
pnpm add @singi-labs/sifa-sdk
# or
npm install @singi-labs/sifa-sdk
# or
bun add @singi-labs/sifa-sdkPeer dependencies: @tanstack/react-query@^5 if you use the /query subpath. The /tokens and /atproto subpaths have no peer deps.
Read-only example: fetch the activity-tier taxonomy
The taxonomy is bundled in the package and resolved without network. Useful as a smoke test.
/**
* Resolve a record's tier without touching the network.
*
* Compiles against the pinned sifa-sdk version on every CI run. If the
* SDK changes a name or type and breaks this file, the docs build fails
* before merge.
*/
import {
ACTIVITY_TIERS,
getActivityTier,
getLexiconEntry,
getActivityTaxonomyVersion,
} from '@singi-labs/sifa-sdk'
const version = getActivityTaxonomyVersion()
console.log(`Activity taxonomy v${version.version} (updated ${version.updated})`)
// Look up tier for a few common record types.
const examples = [
'app.bsky.feed.post',
'app.bsky.feed.like',
'sh.tangled.repo',
'community.lexicon.calendar.rsvp',
] as const
for (const nsid of examples) {
const tier = getActivityTier(nsid)
const entry = getLexiconEntry(nsid)
console.log(`${nsid}: ${tier}${entry?.app ? ` (${entry.app})` : ''}`)
}
// Or iterate every known record type.
const creationLexicons = Object.entries(ACTIVITY_TIERS.lexicons)
.filter(([, entry]) => entry.tier === 'creation')
.map(([nsid]) => nsid)
console.log(`${creationLexicons.length} record types classified as "Made"`)
The exported ACTIVITY_TIERS is what every Sifa app uses to decide whether a record like app.bsky.feed.post shows up on a profile. See the Activity taxonomy reference for the full structure.
Authenticated example: write a position record to a user's PDS
Writing records requires an authenticated @atproto/api agent. The SDK doesn't construct the agent itself: you bring your own (browser-side, you'll use OAuth; server-side, you might use an app password during development).
/**
* Write a new id.sifa.profile.position record to a user's PDS.
*
* The SDK doesn't construct the AT Protocol agent. You bring an
* authenticated agent (from `@atproto/api`, however you got auth) and
* pass it into the SDK's typed wrapper. That keeps the SDK out of the
* platform-specific OAuth/storage maze.
*
* Compiles against the pinned sifa-sdk version on every CI run.
*/
import { AtpAgent } from '@atproto/api'
// Imagine you've already authenticated this agent. In a browser app,
// that's via the AT Protocol OAuth flow. On the server, you might use
// an app password during development. The SDK doesn't care which.
declare const agent: AtpAgent
async function writeCurrentPosition() {
// The SDK exposes a write surface under /atproto. Until that helper
// ships as a single named export, we drive the agent directly and
// validate the record with the SDK's Zod schema.
const positionRecord = {
$type: 'id.sifa.profile.position',
title: 'Senior Engineer',
companyName: 'Singi Labs',
startDate: '2026-03-04',
description: 'Building the Sifa AppView.',
isCurrent: true,
}
const result = await agent.com.atproto.repo.createRecord({
repo: agent.assertDid,
collection: 'id.sifa.profile.position',
record: positionRecord,
})
console.log('Wrote', result.data.uri)
return result.data
}
// Side effect for the typecheck: `writeCurrentPosition` must be
// callable in scope.
void writeCurrentPosition
The wrapper accepts the agent as a parameter so your app stays in control of identity, storage, and session refresh. The SDK provides the typed write surface and the Zod validation; you provide the network.
Where to next
- Concepts: the architecture, where the SDK ends and the AppView begins.
- Activity taxonomy reference: canonical Made/Did classification.
- Brand tokens: colors, typography, icons, and where to find logos.
Looking for user-facing docs instead? Start here.
SDK overview
The Sifa SDK is the TypeScript package that powers sifa-web and the planned sifa-app. Use it to read and write id.sifa.* records, query the AppView, or build your own Sifa-aware client.
Concepts
How the SDK is structured, what each subpath is for, and where the SDK ends and the Sifa AppView begins.