Skerry (or Skerry Chat) is the monorepo for the Skerry Collective Hub Chat Platform: a Matrix-based, Discord-like community product for creator collectives.
Skerry provides a complete community chat experience with high-level abstractions over Matrix and Discord:
- Single-Domain Routing: Unified entry via Caddy reverse proxy with path-based routing (
/auth,/v1,/_matrix, etc.). - Identity & Auth: Multi-provider OIDC (Discord, Google, Twitch, Keycloak) plus developer quick-login. Account linking with split-detection interstitial.
- Hub Architecture: Multi-server (space) organization with categories, channels (text, voice, announcement, forum), and role-based permissions (5-tier audience model).
- Rich Messaging: Real-time chat via SSE with polling fallback. Markdown rendering (bold, italic, code blocks, block quotes, lists). Message editing with revision history. File uploads, stickers (PNG/GIF/Lottie), and link embeds (Open Graph + oEmbed).
- Reactions & Threads: Emoji reaction picker with multi-user badges. Quote-replies with Discord snowflake resolution. Threaded conversations with reply counts and thread panel.
- Voice & Video (scaffolded): LiveKit token issuance, pre-join UI, device settings modal, and voice room management. End-to-end audio/video requires further integration testing.
- Direct Messages: DM picker, DM server creation, persistent DM channels in sidebar.
- Discord Bridge: Bi-directional message relay with emoji mirroring, block quote preservation, edit/pin/delete mirroring, and @mention escaping.
- Moderation & Audit: Kick, ban, timeout (via Synapse admin API), warn, strike escalation (3→timeout, 5→kick, 7→ban). Report triage dashboard. Full audit log with role-based snapshots.
- PWA & Notifications: Dynamic per-server manifest. Service worker with push notifications via VAPID auto-generated keypair. @mention push delivery.
- Server Discovery: Server invites with configurable role assignment and join policies (open, approval, invite-only). Search modal for messages.
- Theming: Light/dark theme per user, with theme-aware overlay components (drawers, popovers). SVG icon system via lucide-react.
- Full Dockerization: Docker Compose stack (Caddy, Synapse, LiveKit, PostgreSQL, control plane) with one-command deployment.
- Landing Page: Deployed at
secarelupus.github.io/Skerry/via GitHub Actions Pages.
.
├── apps/ # Monorepo applications
│ ├── control-plane/ # Fastify policy gate, auth, and provisioning API
│ └── web/ # Next.js web client
├── packages/ # Shared logic
│ └── shared/ # Shared types, constants, and domain contracts
├── docs/ # Documentation (reports, landing page assets)
├── scripts/ # Utility scripts (bootstrap, backup, cleanup)
├── assets/ # Static brand assets and media
├── docker/ # Service-specific configs (Caddy, Synapse)
├── docker-compose.yml # Full stack orchestration
├── docker-compose-test.yml # Isolated E2E test environment
└── AGENTS.md # AI collaborator instructions and project scope
When running via Docker Compose, services communicate using service names as hostnames:
| Service | Internal URL | Purpose |
|---|---|---|
| Caddy | Port 80/443 | Public entry point & path-based routing |
| Web UI | web:3000 |
Frontend Next.js application |
| Control Plane | control-plane:4000 |
Fastify API & provisioning gateway |
| Matrix | synapse:8008 |
Matrix homeserver (Synapse) |
| LiveKit | livekit:7880 |
Real-time voice/video signaling |
| Database | postgres:5432 |
Persistence layer (41 migrations) |
Download the latest deploy kit from the releases page:
tar -xzf skerry-deploy-v0.1.0-alpha.tar.gz
cd deploy
cp .env.example .env
# Edit .env with your domain and OAuth credentials
chmod +x scripts/bootstrap-hub.sh
./scripts/bootstrap-hub.shpnpm install
cp .env.example .env
# Edit .env with your secrets/domain
docker compose up -d- Web UI:
http://localhost(or your configuredBASE_DOMAIN) - API Health:
http://localhost/health
For a production-ready deployment on a fresh Linux instance:
chmod +x scripts/bootstrap-hub.sh
./scripts/bootstrap-hub.shThis generates unique secrets, pulls images, runs migrations, and starts the entire stack.
Docker images are published to GitHub Container Registry (GHCR) on manual release, not on push to main.
-
Publish: Run the Publish Docker Images workflow via GitHub Actions →
workflow_dispatchwith a version tag (e.g.v0.1.0-alpha). This:- Creates the git tag on main
- Builds and pushes three images to
ghcr.io/secarelupus/:skerry-control-plane:{version}skerry-web:{version}skerry-sticker-renderer:{version}
- Uploads the deploy kit as a workflow artifact
-
Deploy: Download the deploy kit from the workflow artifacts, update
SKERRY_VERSIONin.env, then:docker compose pull docker compose up -d
For local development running services individually:
- Start Infrastructure:
docker compose up -d postgres synapse livekit coturn caddy - Run Apps:
pnpm dev
- Generate signing key:
bash docker/synapse/setup-synapse.sh - Admin Access Token: Needed for
SYNAPSE_ACCESS_TOKENin.env. Create an admin user via the Synapse admin API or use an existing administrative account.
- Discord App: Create a Discord application at the developer portal.
- OIDC: Configure redirect URIs to
https://<domain>/auth/callback/discord. - Bot: Add a bot to your application and provide
DISCORD_BRIDGE_BOT_TOKENin.env.
Powered by LiveKit. The docker-compose.yml includes a LiveKit server and a coturn instance for TURN/STUN. Ensure LIVEKIT_API_KEY and LIVEKIT_API_SECRET are configured.
The project maintains a rigorous testing suite across the "Golden Path" of community interactions.
- Typecheck:
pnpm typecheck(all 3 packages) - Unit & Integration:
pnpm test - End-to-End (Playwright): 33 specs covering authentication, community orchestration, messaging, moderation, accessibility, voice channels, and visual regression
pnpm test:env:up # Start isolated E2E environment pnpm test:e2e:run # Run full suite pnpm test:env:down # Tear down
Skerry Hubs can trust each other for cross-hub browsing without secondary logins.
- Exchange Secrets: Hub admins exchange a 32+ character shared secret.
- Add Trust: Use the Admin API or Dashboard:
curl -X POST http://localhost:4000/v1/admin/federation/trust \ -H "Authorization: Bearer ***" \ -d '{"hubUrl": "https://remote-hub.com", "sharedSecret": "...", "trustLevel": "member"}'
- Identity Resolution: Remote users are assigned a local
fed_proxy ID and can view public spaces as authenticated guests.
To prevent Docker storage and build cache from consuming excessive disk space:
- Manual Cleanup:
pnpm run cleanup - Automatic: Runs before every
pnpm run build(prunes build cache and dangling images)
