A Drupal module that publishes content to the AT Protocol (Bluesky and standard.site) via native OAuth authentication.
When you publish a node in Drupal, ATmosphere creates both a Bluesky post (app.bsky.feed.post) and a standard.site document (site.standard.document) on your Personal Data Server (PDS) in a single atomic operation.
- OAuth 2.1 authentication with PKCE, DPoP (Demonstration of Proof-of-Possession), and PAR (Pushed Authorization Requests)
- Automatic publishing of configured content types on node create/update/delete
- Atomic writes - Bluesky post and standard.site document created in a single
applyWritescall - Rich text facets - links, @mentions (resolved to DIDs), and #hashtags extracted automatically
- Image support - cover images and thumbnails uploaded as blobs with size validation
- Site publication sync - site name/slogan changes propagate to your
site.standard.publicationrecord - Backfill - batch-publish existing content via an AJAX UI
- Content preview - append
?atprototo any node URL to inspect the AT Protocol records - Extensible content parsing via
hook_atmosphere_content_parser
- Drupal 10.3+ or Drupal 11
- PHP 8.2+
- PHP extensions:
openssl,sodium - Composer dependency:
web-token/jwt-library^4.1
composer require drupal/atmosphere
drush en atmosphere- Navigate to Administration > Configuration > Web services > ATmosphere (
/admin/config/services/atmosphere) - Enter your AT Protocol handle (e.g.
yourname.bsky.socialor a custom domain handle) - Complete the OAuth authorization flow - you'll be redirected to your authorization server to grant access
- Configure which content types to publish and whether to auto-publish on node creation
If you use your Drupal site's domain as your AT Protocol handle, ATmosphere serves the /.well-known/atproto-did endpoint automatically for handle verification.
ATmosphere creates a site.standard.publication record representing your site. The /.well-known/site.standard.publication endpoint is served automatically for discovery.
When a node is created or updated:
- The module queues the node for processing
- A Document Transformer builds a
site.standard.documentrecord (title, URL, excerpt, cover image, full text, tags, timestamps) - A Post Transformer builds an
app.bsky.feed.postrecord (text truncated to 300 graphemes, link/mention/hashtag facets, embed card or thumbnail) - Both records are written atomically to your PDS via a DPoP-signed API request
- The resulting AT-URIs and CIDs are stored back on the node for future updates/deletes
- OAuth tokens are encrypted at rest using libsodium (key derived from Drupal's
hash_salt) - All API requests are signed with DPoP proofs (ES256)
- DPoP nonces are tracked and automatically retried
- PKCE is used for the authorization code flow
| Setting | Description | Default |
|---|---|---|
| Auto-publish | Automatically publish nodes when created | true |
| Content types | Which node types to sync | article |
| Permission | Description |
|---|---|
| Administer ATmosphere | Connect/disconnect account, configure settings |
| Preview AT Protocol records | View ?atproto JSON preview on node pages |
Publishing happens asynchronously via Drupal's queue system. Records are processed during cron runs. To process manually:
drush queue:run atmosphere_publish
drush queue:run atmosphere_update
drush queue:run atmosphere_delete
drush queue:run atmosphere_sync_publicationTo publish existing content that was created before ATmosphere was installed:
- Go to the ATmosphere settings page
- Click the Backfill button
- The module will batch-process all published nodes of your configured content types that haven't been synced yet
Append ?atproto to any published node URL to inspect the AT Protocol JSON that would be sent to your PDS:
https://yoursite.com/node/42?atproto
Requires the Preview AT Protocol records permission and an active connection. Only works for node types in your configured syncable list.
The response shows the site.standard.document record as it would be written. Note that the preview renders the document transformer only — the Bluesky post transformer is not included.
All publish/update/delete operations are logged to the atmosphere channel. View them at Administration > Reports > Recent log messages (filter by type atmosphere), or via Drush:
drush watchdog:show --type=atmosphereQueue failures are logged as errors and the item is requeued for retry.
Process queues immediately without waiting for cron:
drush queue:run atmosphere_publish
drush queue:run atmosphere_update
drush queue:run atmosphere_delete
drush queue:run atmosphere_sync_publicationThe connection state (DID, handle, PDS, token expiry) is stored in Drupal's State API under the key atmosphere.connection. You can inspect it with:
drush php-eval "print_r(\Drupal::state()->get('atmosphere.connection'));"Tokens are encrypted — you'll see ciphertext, not raw token values.
Source repository: affinitybridge/drupal-atmosphere
GPL-2.0-or-later