SkillAgentSearch skills...

Appview

No description available

Install / Use

/learn @colibri-social/Appview
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

colibri-appview

[!WARNING] This implementation is almost entirely vibe-coded for the purpose of being able to quickly get started with development of the main application. It will be re-written in the near future to take advantage of Tap and be reworked to include all user data storage as well as any OAuth capabilities, which currently reside within the website's backend. If you are interested in helping with this, start a discussion on this repo!

An ATProto appview for the Colibri social platform, built with Rocket.rs.

Overview

| Feature | Details | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Jetstream consumer | Connects to a Colibri Jetstream WebSocket and ingests all Colibri lexicon records into PostgreSQL in real time, with cursor persistence and automatic reconnect. | | Backfill | On startup, fetches historical records from each known DID's PDS so no data is missed. Triggered again automatically when the appview falls behind. Backfill includes Bluesky profiles (banner_url, handle, description) and actor status/emoji. | | Client subscriptions | Clients connect via WebSocket (/api/subscribe?did=<did>) and subscribe to filtered event streams — messages by channel, community events by AT-URI. Community subscriptions automatically deliver member status and profile updates. Easy to extend with new event types. | | Presence | Clients are marked online on WS connect, offline on disconnect, and away after 5 minutes of heartbeat-only activity. Preferred state (online/away/dnd) is persisted and restored on reconnect. | | WebRTC signaling | Room-based peer-to-peer voice/video signaling over WebSocket (/api/webrtc/signal). | | REST API | Full set of read endpoints for messages, authors, reactions, communities, channels, categories, members, and invite codes. |


Setup

Prerequisites

  • Rust (stable, 1.75+)
  • PostgreSQL 14+

1. Database

createdb colibri

Migrations run automatically on startup via sqlx::migrate!. No manual SQL needed.

2. Environment

cp .env.example .env
# Fill in at minimum DATABASE_URL and INVITE_API_KEY

3. Run

cargo run

The server listens on 0.0.0.0:8000 by default.

Docker

docker compose up --build
# or for development with live reload:
docker compose -f docker-compose.dev.yml up

Environment variables

| Variable | Required | Default | Description | | ---------------- | -------- | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | DATABASE_URL | ✅ | — | PostgreSQL connection string, e.g. postgres://user:pass@localhost:5432/colibri | | INVITE_API_KEY | ✅ | — | Bearer token required for POST /api/invite, DELETE /api/invite/<code>, GET /api/invites, POST /api/message/block, and POST /api/user/state | | ROCKET_ADDRESS | ❌ | 0.0.0.0 | Bind address | | ROCKET_PORT | ❌ | 8000 | Bind port | | JETSTREAM_URL | ❌ | wss://jetstream2.us-east.bsky.network/subscribe?… | Override Jetstream endpoint (e.g. point at a self-hosted instance) | | RUST_LOG | ❌ | colibri_appview=info,rocket=info | Log filter (trace, debug, info, warn, error) |


REST API

All endpoints return JSON. CORS is open (*).

Voice presence

  • Each DID can only be active in one voice channel. Joining a different channel triggers a voice_channel_updated event for the previous room before the new join is emitted, so clients see the previous membership cleared.
  • If a connection sends no non-heartbeat action for more than five minutes, it is marked away and the DID is removed from any active voice call so voice membership stays in sync.

The Jetstream consumer enforces the community's requiresApprovalToJoin flag when indexing messages. Communities with requiresApprovalToJoin = true (default) only accept messages from approved members and the owner; those that set the flag to false allow any DID with a membership declaration to send messages even before approval. If a community flips from open to approval-only while the appview is running, any member lacking an approval record is reverted to pending and a member_pending event is emitted so clients can refresh their UI.

Channels also support an ownerOnly record property (returned as owner_only by the appview). When owner_only is true, only the community owner can create or update messages in that channel.

Messages

GET /api/messages

Paginated message history for a channel, newest first. Each message includes the author profile.

| Parameter | Required | Description | | --------- | -------- | ------------------------------------------------------------------------- | | channel | ✅ | Channel rkey | | limit | ❌ | 1–100, default 50 | | before | ❌ | ISO 8601 timestamp — returns messages older than this (pagination cursor) | | all | ❌ | Fetch all messages from the channel |

curl "http://localhost:8000/api/messages?channel=general&limit=20"
curl "http://localhost:8000/api/messages?channel=general&before=2024-03-01T12:00:00Z"

GET /api/message

Fetch a single message by author and record key.

| Parameter | Required | Description | | --------- | -------- | ----------- | | author | ✅ | Author DID | | rkey | ✅ | Record key |

curl "http://localhost:8000/api/message?author=did:plc:xxx&rkey=3mxxx"

POST /api/message/block 🔒

Block a message, hiding it from all future responses. All connected WebSocket clients are immediately notified via a message_deleted event. Requires Authorization: Bearer <INVITE_API_KEY>.

Returns 204 No Content on success, 404 if the message doesn't exist or is already blocked.

| Parameter | Required | Description | | ------------ | -------- | ------------------ | | author_did | ✅ | Author DID | | rkey | ✅ | Message record key |

curl -X POST "http://localhost:8000/api/message/block?author_did=did:plc:xxx&rkey=3mxxx" \
  -H "Authorization: Bearer $INVITE_API_KEY"

Authors

GET /api/authors

Retrieve a cached author profile. Falls back to a live ATProto fetch if not yet cached.

| Parameter | Required | Description | | --------- | -------- | ----------- | | did | ✅ | Author DID |

curl "http://localhost:8000/api/authors?did=did:plc:xxx"

Response:

{
	"did": "did:plc:xxx",
	"display_name": "Alice",
	"avatar_url": "https://cdn.bsky.app/...",
	"banner_url": "https://cdn.bsky.app/...",
	"description": "Building cool things",
	"handle": "alice.bsky.social",
	"status": "Working on something cool",
	"emoji": "🚀",
	"state": "online"
}

Reactions

GET /api/reactions

Reactions for a single message, grouped by emoji with reactor DIDs.

| Parameter | Required | Description | | --------- | -------- | ------------------- | | message | ✅ | Target message rkey |

GET /api/reactions/channel

All reactions in a channel, keyed by target message rkey.

| Parameter | Required | Description | | --------- | -------- | ------------ | | channel | ✅ | Channel rkey |

Response:

{
	"3mxxx": [{ "emoji": "👍", "count": 3, "reactor_dids": ["did:plc:..."] }],
	"3myyy": [{ "emoji": "❤️", "count": 1, "reactor_dids": ["did:plc:..."] }]
}

Communities

View on GitHub
GitHub Stars15
CategoryDevelopment
Updated44m ago
Forks3

Languages

Rust

Security Score

85/100

Audited on Apr 2, 2026

No findings