Skip to main content

Trusted Complete Suite for AT Protocol and Bluesky

The packages provided by atproto.dart are used in many Dart and Flutter applications and have a proven track record of stability. atproto.dart maximizes the productivity of your AT Protocol and Bluesky-related Flutter app development with API-related packages such as atproto and bluesky, and bluesky_text which supports powerful Bluesky text analysis.

100% Sound Null Safety

All packages provided by atproto.dart are 100% Null Safe. This is ensured by the robust Dart language specification. This means that the package provided by atproto.dart will never raise null-related exceptions during program execution, such as the well-known NullPointerException.

Seamless Integration with Flutter App

All packages provided by atproto.dart are designed in the Dart language and follow the common commitments of the Dart and Flutter worlds, allowing for easy and seamless integration into Flutter apps. The atproto.dart packages allow you to implement the functionality of services as you wish, even if you are not familiar with the core AT Protocol and Bluesky things.

Robust Safety and Stability

All packages provided by atproto.dart are very well tested and very stable. All packages in atproto.dart are released after passing scenario tests that take into account various cases from numerous unit tests. atproto.dart always delivers consistent and high-quality solutions to your application.

Stable and Powerful SDK

The atproto.dart provides powerful SDK for AT Protocol and Bluesky, atproto and bluesky. atproto supports the com.atproto.* family of Lexicons, and bluesky supports the app.bsky.* while inheriting atproto.

atproto and bluesky are very well designed, type safe and very easy to use. You do not need to be very aware of XRPC and other underlying technologies used in AT Protocol because these packages also encapsulate the difficult communication process.

All operations in atproto and bluesky are type secured. It is also 100% Null Safe and can be easily and safely integrated into your Dart/Flutter app.

In addition, we provide a strong, official label-based moderation API that allows you to integrate Bluesky's moderation into your Flutter app without needing in-depth knowledge of moderation when you develop your Flutter app.

final timeline = await bsky.feed.getTimeline(
limit: 25,
);

final preferences = await bsky.actor.getPreferences();
for (final feed in timeline.data.feed) {
final text = feed.post.record.text.toLowerCase();

if (text.contains('bluesky')) {
await bsky.feed.like(
cid: feed.post.cid,
uri: feed.post.uri,
);
}

final postModeration = mod.moderatePost(
mod.ModerationSubjectPost.post(data: feed.post),
mod.getModerationOptions(
userDid: 'did:web:shinyakato.dev',
preferences: preferences.data.preferences,
),
);

if (postModeration.content.isBlur) {
// nsfw...?
}
}

Powerful Firehose API

Supports a very easy way to use the Firehose API with atproto and bluesky. The Firehose API can retrieve events occurring in real time on services provided by a particular PDS in AT Protocol. Using the Firehose API, you can take statistics using real-time data and create BOTs.

If you use bluesky, you can use the even more powerful RepoCommitAdaptor to extract only specific events that occur in Bluesky Social. This powerful feature will accelerate your development many times over.

final bsky = Bluesky.anonymous();
final subscription = await bsky.sync.subscribeRepos();

final repoCommitAdaptor = RepoCommitAdaptor(
onCreatePost: (data) {
print(data.uri);
print(data.record);
},
onDeleteFollow: (data) {
print(data.uri);
},
);

await for (final event in subscription.data.stream) {
event.when(
commit: repoCommitAdaptor.execute,
handle: print,
migrate: print,
tombstone: print,
info: print,
unknown: print,
);
}

Advanced Built-In Retry

atproto and bluesky have built-in functions to automatically detect temporary server errors or network failures and do retry.

Retry for network failures are SocketException, which occurs when a line is interrupted, and TimeoutException, which occurs when the server does not return a response within a certain period of time. And retry on server error is applicable when a status code in the 5xx is returned from the ATP server.

The retry algorithm uses an advanced Exponential BackOff And Jitter. It provides an extremely powerful retry function that also takes into account the load on the destination server.

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();

Don't Be Afraid of RichText

bluesky_text is a very powerful and easy way to apply RichText to text you post to Bluesky. bluesky_text automatically detects all tokens of mentions, hyperlinks, tags and even markdown links in the text! And bluesky_text even generates facets as JSON.

By using bluesky_text together with bluesky when posting to Bluesky, you can safely post RichText-applied text without having to worry about difficult processing.

bluesky_text is a brilliant solution to the text problem in Bluesky. If you are developing a Bluesky-related Flutter app, bluesky_text is a must-have!

import 'package:bluesky/bluesky.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(
text: text.value,
facets: facets.map(Facet.fromJson).toList(),
);
}