Build Faster with Production-Ready Components
Skip the boilerplate and focus on your app's unique features. Our battle-tested packages power many Flutter applications in production, giving you reliable AT Protocol and Bluesky integration from day one. Get comprehensive API coverage with atproto
, bluesky
, and bluesky_text
for advanced text processing.
Write Confident Code with Complete Type Safety
Eliminate runtime crashes before they happen. Every package is 100% null safe, leveraging Dart's robust type system to catch errors at compile time. Your app will never crash from null pointer exceptions, giving you confidence in production deployments.
Integrate Effortlessly into Your Flutter Workflow
Start building immediately with Flutter-native design patterns. Our packages follow Dart conventions you already know, enabling seamless integration without learning curves. Build powerful AT Protocol features even without deep protocol knowledge – we handle the complexity for you.
Deploy with Confidence Using Proven Stability
Ship reliable apps backed by comprehensive testing. Every release passes extensive unit and integration tests covering real-world scenarios. Our packages deliver consistent, high-quality performance that your users can depend on.
Complete AT Protocol Integration
Build AT Protocol and Bluesky applications with our comprehensive SDK featuring atproto and bluesky packages.
The atproto package covers the complete com.atproto.*
specification, while bluesky
extends this foundation with full app.bsky.*
support.
Focus on your app logic instead of protocol complexity. You don't need to understand XRPC
internals or handle low-level communication – our packages abstract these details while maintaining full functionality.
Every API call is fully type-safe and completely null safe, enabling you to integrate seamlessly and confidently
into any Dart or Flutter project.
Includes our comprehensive moderation API for implementing Bluesky content moderation
without requiring deep knowledge of labeling systems.
//! Moderation Stuffs
final preferences = await bsky.actor.getPreferences();
final moderationPrefs = preferences.data.getModerationPrefs();
final labelDefs = await bsky.labeler.getLabelDefinitions(moderationPrefs);
final labelerHeaders = mod.getLabelerHeaders(moderationPrefs);
final moderationOpts = mod.ModerationOpts(
userDid: bsky.session!.did,
prefs: moderationPrefs,
labelDefs: labelDefs,
);
final timeline = await bsky.feed.getTimeline($headers: labelerHeaders);
for (final feed in timeline.data.feed) {
final record = FeedPostRecord.fromJson(feed.post.record);
final text = record.text.toLowerCase();
if (text.contains('bluesky')) {
await bsky.feed.like.create(
subject: RepoStrongRef(cid: feed.post.cid, uri: feed.post.uri),
);
}
final postModeration = mod.moderatePost(
mod.ModerationSubjectPost.postView(data: feed.post),
moderationOpts,
);
if (postModeration.getUI(mod.ModerationBehaviorContext.contentView).blur) {
// nsfw...?
}
}
Real-Time Data Streaming
Stream live AT Protocol events effortlessly with our Firehose API
integration in atproto and bluesky.
Monitor real-time activity across any Personal Data Server (PDS) to build analytics dashboards,
content moderation tools, or automated bots that respond to network events.
For Bluesky applications, leverage the specialized RepoCommitAdaptor
to filter and process
only the events you care about. This targeted approach dramatically reduces processing overhead
and accelerates development of real-time features.
final bsky = Bluesky.anonymous();
final subscription = await bsky.atproto.sync.subscribeRepos();
await for (final event in subscription.data.stream) {
final repos = const firehose.SyncSubscribeReposAdaptor().execute(event);
if (repos.isCommit) {
const firehose.RepoCommitHandler(
onCreateFeedPost: print,
onUpdateActorProfile: print,
onDeleteGraphFollow: print,
).execute(repos.commit!);
}
}
Intelligent Error Recovery
Handle network instability gracefully with automatic retry logic built into atproto and bluesky.
Our packages intelligently detect and recover from temporary failures without manual intervention.
Network interruptions like TimeoutException
are handled transparently,
along with server errors returning 5xx
status codes. Your app stays responsive
even when the network doesn't cooperate.
The retry mechanism implements industry-standard Exponential Backoff with Jitter, balancing quick recovery
with server-friendly request patterns that won't overwhelm struggling endpoints.
final retryConfig = RetryConfig(
maxAttempts: 10,
jitter: Jitter(maxInSeconds: 5, minInSeconds: 3),
onExecute: (event) => print(
'Retry after ${event.intervalInSeconds} seconds...'
'[${event.retryCount} times]',
),
);
final session = await createSession(
identifier: 'shinyakato.dev',
password: 'xxxxxxxx',
retryConfig: retryConfig,
);
final bsky = Bluesky.fromSession(session.data, retryConfig: retryConfig);
// Do retry if there are communication errors, etc
final timeline = await bsky.feed.getTimeline();
Rich Text Made Simple
Transform plain text into rich Bluesky posts effortlessly with bluesky_text.
Automatically detect and format mentions, links, hashtags, and markdown syntax
while generating the required facets
JSON structure behind the scenes.
Combine bluesky_text with bluesky to publish rich content without wrestling
with complex text processing or facet generation. Focus on your content
while we handle the technical formatting requirements.
Essential for any Bluesky application that handles user-generated content.
bluesky_text eliminates the complexity of rich text processing in social applications.
import 'package:bluesky/app_bsky_richtext_facet.dart';
import 'package:bluesky/bluesky.dart';
import 'package:bluesky/atproto.dart';
import 'package:bluesky_text/bluesky_text.dart';
Future<void> main(List<String> args) async {
final session = await createSession(
identifier: 'shinyakato.dev',
password: 'xxxxxxxx',
);
final bsky = Bluesky.fromSession(session.data);
final text = BlueskyText(
'Hello, I am @shinyakato.dev! '
'wdyt about [this link](https://atprotodart.com)?',
linkConfig: const LinkConfig(excludeProtocol: true, enableShortening: true),
).format();
final facets = await text.entities.toFacets();
final strongRef = await bsky.feed.post.create(
text: text.value,
facets: facets.map(RichtextFacet.fromJson).toList(),
);
}