Collaboration Workspace
This example is the “show me what the product can do” composition. It combines the collaboration, media, and interaction packages into one workspace-style backend instead of presenting them as isolated plugins.
Source-backed example app: examples/collaboration-workspace/
What this demonstrates
Section titled “What this demonstrates”- identity plus role-aware collaboration
- forum-style community and room-based chat side by side
- polls and interaction dispatch layered on top of content surfaces
- uploaded assets, custom emoji, link unfurls, and GIF search
- mobile and browser entry points through deep links and fallback redirects
Install
Section titled “Install”bun add @lastshotlabs/slingshot \ @lastshotlabs/slingshot-assets \ @lastshotlabs/slingshot-auth \ @lastshotlabs/slingshot-chat \ @lastshotlabs/slingshot-community \ @lastshotlabs/slingshot-deep-links \ @lastshotlabs/slingshot-embeds \ @lastshotlabs/slingshot-emoji \ @lastshotlabs/slingshot-gifs \ @lastshotlabs/slingshot-interactions \ @lastshotlabs/slingshot-notifications \ @lastshotlabs/slingshot-permissions \ @lastshotlabs/slingshot-pollsFull setup
Section titled “Full setup”import { defineApp } from '@lastshotlabs/slingshot';import { createAssetsPackage } from '@lastshotlabs/slingshot-assets';import { createAuthPlugin } from '@lastshotlabs/slingshot-auth';import { createChatPackage } from '@lastshotlabs/slingshot-chat';import { createCommunityPackage } from '@lastshotlabs/slingshot-community';import { createDeepLinksPlugin } from '@lastshotlabs/slingshot-deep-links';import { createEmbedsPlugin } from '@lastshotlabs/slingshot-embeds';import { createEmojiPackage } from '@lastshotlabs/slingshot-emoji';import { createGifsPlugin } from '@lastshotlabs/slingshot-gifs';import { createInteractionsPackage } from '@lastshotlabs/slingshot-interactions';import { createNotificationsPackage } from '@lastshotlabs/slingshot-notifications';import { createPermissionsPackage } from '@lastshotlabs/slingshot-permissions';import { createPollsPackage } from '@lastshotlabs/slingshot-polls';
export default defineApp({ port: 3000, security: { signing: { secret: process.env.JWT_SECRET! } }, plugins: [ createAuthPlugin({ auth: { roles: ['user', 'moderator', 'admin'], defaultRole: 'user' }, db: { auth: 'memory', sessions: 'memory', oauthState: 'memory' }, }), createEmbedsPlugin({}), createGifsPlugin({ provider: 'tenor', apiKey: process.env.TENOR_API_KEY!, rating: 'pg', }), createDeepLinksPlugin({ fallbackBaseUrl: 'https://app.example.com', fallbackRedirects: { '/join/*': '/workspace/:id', '/share/*': '/thread/:id', }, }), ], packages: [ createNotificationsPackage({ dispatcher: { enabled: false, intervalMs: 30_000, maxPerTick: 500 }, }), createPermissionsPackage(), createCommunityPackage({ authBridge: 'auto', containerCreation: 'user' }), createChatPackage({ storeType: 'memory', permissions: { createRoom: ['user', 'moderator', 'admin'], sendMessage: ['user', 'moderator', 'admin'], }, }), createPollsPackage(), createAssetsPackage({ storage: { adapter: 'memory' }, presignedUrls: true, allowedMimeTypes: ['image/png', 'image/jpeg', 'image/gif', 'image/webp'], image: { allowedOrigins: ['localhost'] }, }), createInteractionsPackage({ handlers: { 'polls:vote:': { kind: 'route', target: '/internal/interactions/poll-vote' }, 'chat:pin:': { kind: 'queue', target: 'jobs:chat.pin', fireAndForget: true }, }, }), createEmojiPackage({}), ],});What you get
Section titled “What you get”| Capability | Surface |
|---|---|
| Community | /community/* for containers, threads, replies, moderation, reports |
| Chat | /chat/* for rooms, messages, membership, pins, receipts |
| Notifications | /notifications/sse for in-app realtime delivery |
| Polls | /polls/* for attached multiple-choice polls |
| Assets | /assets/* for uploaded files and metadata |
| Emoji | /emoji/* for custom emoji records tied to uploaded assets |
| Embeds | /embeds/unfurl for server-side link previews |
| GIFs | /gifs/trending and /gifs/search for composer media search |
| Deep links | /.well-known/* plus fallback browser redirects |
| Interactions | /interactions/dispatch for buttons, menus, and custom action payloads |
How the pieces fit together
Section titled “How the pieces fit together”slingshot-authestablishes the user identity.slingshot-permissionspublishes shared authorization state for chat, emoji, and other packages.authBridge: "auto"on the community plugin adapts auth context intocommunityPrincipalso community routes stay decoupled from auth internals.slingshot-notificationsgives both chat and community a delivery surface for unread updates, replies, mentions, and invitations.slingshot-assetsis the byte-storage foundation for uploads, whileslingshot-emoji,slingshot-embeds, andslingshot-gifsbuild media experiences on top.slingshot-pollsandslingshot-interactionsare the extension points that let content surfaces feel interactive instead of static.
Where to go next
Section titled “Where to go next”- Forum App for the smaller community-only composition
- Auth Setup for the identity baseline
- slingshot-chat for chat-specific config and route behavior
- slingshot-assets for storage, presigned URLs, and image serving