From 944ccfc50b3a2a21717c024d9729831e51481890 Mon Sep 17 00:00:00 2001 From: Milosz Filimowski Date: Mon, 30 Jun 2025 13:45:48 +0200 Subject: [PATCH 01/42] restructure docs --- docs/explanation/architecture.mdx | 166 ++++++ docs/explanation/core-concepts.mdx | 240 +++++++++ docs/explanation/room-manager-concept.mdx | 162 ++++++ docs/explanation/room-types.mdx | 176 +++++++ docs/explanation/security-tokens.mdx | 312 ++++++++++++ docs/explanation/what-is-fishjam.mdx | 91 ++++ docs/{ => how-to}/_common/metadata/header.mdx | 0 .../_common/metadata/joining_room.mdx | 0 .../{ => how-to}/_common/metadata/reading.mdx | 0 .../_common/metadata/updating.mdx | 0 .../backend/fastapi-example.mdx} | 0 .../backend/fastify-example.mdx} | 0 docs/how-to/backend/production-deployment.mdx | 479 ++++++++++++++++++ .../backend/server-setup.mdx} | 0 .../features/audio-only-calls.mdx} | 21 +- docs/{ => how-to/features}/livestreaming.mdx | 2 +- docs/how-to/features/room-manager-testing.mdx | 272 ++++++++++ .../_components/configure-permissions.mdx | 0 .../_components/install-package.mdx | 0 .../react-native/assets/ios-new-folder.png | Bin .../react-native/assets/ios-new-group.png | Bin .../react-native/assets/ios-new-target.png | Bin .../react-native/background-streaming.mdx} | 0 docs/{ => how-to}/react-native/connecting.mdx | 0 .../custom-video-sources/index.mdx | 0 .../custom-video-sources/overview.mdx | 0 .../custom-video-sources/vision-camera.mdx | 0 .../react-native/installation.mdx | 0 .../react-native/list-other-peers.mdx} | 0 .../react-native/livestreaming.mdx | 0 .../metadata-and-broadcasting.mdx} | 0 .../react-native/reconnection-handling.mdx} | 0 .../react-native/screensharing.mdx | 0 .../react-native/start-streaming.mdx | 0 docs/how-to/react/_common/metadata/header.mdx | 10 + .../react/_common/metadata/joining_room.mdx | 5 + .../how-to/react/_common/metadata/reading.mdx | 9 + .../react/_common/metadata/updating.mdx | 5 + docs/{ => how-to}/react/connecting.mdx | 0 docs/{ => how-to}/react/custom-sources.mdx | 0 docs/{ => how-to}/react/installation.mdx | 0 .../react/list-other-peers.mdx} | 0 docs/{ => how-to}/react/livestreaming.mdx | 0 docs/{ => how-to}/react/managing-devices.mdx | 0 docs/{ => how-to}/react/metadata.mdx | 0 docs/{ => how-to}/react/start-streaming.mdx | 0 docs/{ => how-to}/react/stream-middleware.mdx | 0 .../troubleshooting/video-codecs.mdx} | 6 +- docs/index.mdx | 135 ++++- docs/introduction.mdx | 63 --- docs/production/_category_.json | 7 - docs/production/examples/_category_.json | 7 - docs/react-native/_category_.json | 8 - docs/react-native/quick-setup.mdx | 193 ------- docs/react/_category_.json | 8 - docs/{ => reference}/glossary.md | 2 +- docs/room-manager.md | 75 --- docs/tutorials/backend-quick-start.mdx | 376 ++++++++++++++ docs/tutorials/react-native-quick-start.mdx | 203 ++++++++ docs/tutorials/react-quick-start.mdx | 272 ++++++++++ docusaurus.config.ts | 6 +- sidebars/docs.ts | 116 ++++- 62 files changed, 3044 insertions(+), 383 deletions(-) create mode 100644 docs/explanation/architecture.mdx create mode 100644 docs/explanation/core-concepts.mdx create mode 100644 docs/explanation/room-manager-concept.mdx create mode 100644 docs/explanation/room-types.mdx create mode 100644 docs/explanation/security-tokens.mdx create mode 100644 docs/explanation/what-is-fishjam.mdx rename docs/{ => how-to}/_common/metadata/header.mdx (100%) rename docs/{ => how-to}/_common/metadata/joining_room.mdx (100%) rename docs/{ => how-to}/_common/metadata/reading.mdx (100%) rename docs/{ => how-to}/_common/metadata/updating.mdx (100%) rename docs/{production/examples/fastapi.mdx => how-to/backend/fastapi-example.mdx} (100%) rename docs/{production/examples/fastify.mdx => how-to/backend/fastify-example.mdx} (100%) create mode 100644 docs/how-to/backend/production-deployment.mdx rename docs/{production/server.mdx => how-to/backend/server-setup.mdx} (100%) rename docs/{audio-calls.mdx => how-to/features/audio-only-calls.mdx} (64%) rename docs/{ => how-to/features}/livestreaming.mdx (99%) create mode 100644 docs/how-to/features/room-manager-testing.mdx rename docs/{ => how-to}/react-native/_components/configure-permissions.mdx (100%) rename docs/{ => how-to}/react-native/_components/install-package.mdx (100%) rename docs/{ => how-to}/react-native/assets/ios-new-folder.png (100%) rename docs/{ => how-to}/react-native/assets/ios-new-group.png (100%) rename docs/{ => how-to}/react-native/assets/ios-new-target.png (100%) rename docs/{react-native/background.mdx => how-to/react-native/background-streaming.mdx} (100%) rename docs/{ => how-to}/react-native/connecting.mdx (100%) rename docs/{ => how-to}/react-native/custom-video-sources/index.mdx (100%) rename docs/{ => how-to}/react-native/custom-video-sources/overview.mdx (100%) rename docs/{ => how-to}/react-native/custom-video-sources/vision-camera.mdx (100%) rename docs/{ => how-to}/react-native/installation.mdx (100%) rename docs/{react-native/list-other.mdx => how-to/react-native/list-other-peers.mdx} (100%) rename docs/{ => how-to}/react-native/livestreaming.mdx (100%) rename docs/{react-native/metadata.mdx => how-to/react-native/metadata-and-broadcasting.mdx} (100%) rename docs/{react-native/reconnect.mdx => how-to/react-native/reconnection-handling.mdx} (100%) rename docs/{ => how-to}/react-native/screensharing.mdx (100%) rename docs/{ => how-to}/react-native/start-streaming.mdx (100%) create mode 100644 docs/how-to/react/_common/metadata/header.mdx create mode 100644 docs/how-to/react/_common/metadata/joining_room.mdx create mode 100644 docs/how-to/react/_common/metadata/reading.mdx create mode 100644 docs/how-to/react/_common/metadata/updating.mdx rename docs/{ => how-to}/react/connecting.mdx (100%) rename docs/{ => how-to}/react/custom-sources.mdx (100%) rename docs/{ => how-to}/react/installation.mdx (100%) rename docs/{react/list-other.mdx => how-to/react/list-other-peers.mdx} (100%) rename docs/{ => how-to}/react/livestreaming.mdx (100%) rename docs/{ => how-to}/react/managing-devices.mdx (100%) rename docs/{ => how-to}/react/metadata.mdx (100%) rename docs/{ => how-to}/react/start-streaming.mdx (100%) rename docs/{ => how-to}/react/stream-middleware.mdx (100%) rename docs/{troubleshooting.mdx => how-to/troubleshooting/video-codecs.mdx} (89%) delete mode 100644 docs/introduction.mdx delete mode 100644 docs/production/_category_.json delete mode 100644 docs/production/examples/_category_.json delete mode 100644 docs/react-native/_category_.json delete mode 100644 docs/react-native/quick-setup.mdx delete mode 100644 docs/react/_category_.json rename docs/{ => reference}/glossary.md (98%) delete mode 100644 docs/room-manager.md create mode 100644 docs/tutorials/backend-quick-start.mdx create mode 100644 docs/tutorials/react-native-quick-start.mdx create mode 100644 docs/tutorials/react-quick-start.mdx diff --git a/docs/explanation/architecture.mdx b/docs/explanation/architecture.mdx new file mode 100644 index 00000000..f79ac85e --- /dev/null +++ b/docs/explanation/architecture.mdx @@ -0,0 +1,166 @@ +--- +type: explanation +--- + +# Fishjam Architecture + +**Explanation** - *Understanding how Fishjam works under the hood* + +This document explains the technical architecture of Fishjam and how data flows through the system. + +## High-level Architecture + +Streaming with Fishjam is simple: you create a room, add peers to it, and start streaming. Below is a high-level overview of how Fishjam works. + +![Fishjam Data Flow](@site/static/img/architecture.svg) + +## Components Overview + +### 1. Your Backend Server +Your application's backend server is responsible for: +- Authenticating users +- Creating rooms using Fishjam Server SDKs +- Generating peer tokens for clients +- Managing room lifecycle and permissions + +### 2. Fishjam Media Server +The Fishjam Media Server is the core infrastructure component that: +- Routes audio and video streams between participants +- Handles WebRTC negotiations and connections +- Manages different room types (full-feature, audio-only, livestream) +- Processes and transcodes media when needed +- Enforces security policies and token validation + +### 3. Client Applications +Client applications (React Native, React/Web) use Fishjam Client SDKs to: +- Connect to rooms using peer tokens +- Send and receive audio/video streams +- Handle device management (cameras, microphones) +- Manage connection state and reconnections + +## Data Flow + +### 1. Room Creation Flow +```mermaid +sequenceDiagram + participant BE as Your Backend + participant FM as Fishjam Media Server + participant Client as Client App + + Client->>BE: Request to join room + BE->>FM: Create room (Server SDK) + FM->>BE: Return room ID + BE->>FM: Create peer (Server SDK) + FM->>BE: Return peer token + BE->>Client: Send peer token + Fishjam URL +``` + +### 2. Media Streaming Flow +```mermaid +sequenceDiagram + participant C1 as Client 1 + participant FM as Fishjam Media Server + participant C2 as Client 2 + + C1->>FM: Connect with peer token + C2->>FM: Connect with peer token + C1->>FM: Send video/audio stream + FM->>C2: Route stream to other peers + C2->>FM: Send video/audio stream + FM->>C1: Route stream to other peers +``` + +## Room Types and Architecture + +### Full-feature Rooms +- **Purpose**: Multi-participant video conferencing +- **Media flow**: Peer-to-peer through media server (SFU architecture) +- **Scaling**: Supports many participants efficiently +- **Features**: Screen sharing, multiple video tracks, audio controls + +### Audio-only Rooms +- **Purpose**: Voice-only communication +- **Media flow**: Audio-only routing with optimized bandwidth +- **Scaling**: Highly efficient, supports more participants +- **Cost**: 75% cheaper than full-feature rooms + +### Livestream Rooms +- **Purpose**: One-to-many broadcasting +- **Media flow**: Single broadcaster to multiple viewers +- **Protocols**: Uses WHEP/WHIP standards for viewers +- **Scaling**: Optimized for high viewer counts + +## Security Architecture + +### Token-based Authentication +1. **Management Tokens**: Secure your backend-to-Fishjam communication +2. **Peer Tokens**: Short-lived tokens for client access to specific rooms +3. **Token Validation**: All client connections validated by media server + +### Network Security +- All media streams are encrypted using WebRTC's built-in encryption +- HTTPS/WSS connections required +- No direct peer-to-peer connections (everything routes through Fishjam) + +## Scaling and Reliability + +### Media Server Scaling +- Automatic scaling based on load +- Geographic distribution for low latency +- Redundancy and failover handling + +### Client Resilience +- Automatic reconnection handling +- Network change detection +- Graceful degradation on poor connections + +## Integration Patterns + +### Development Pattern (Room Manager) +For development and testing: +``` +Client App <-> Room Manager <-> Fishjam Media Server +``` + +### Production Pattern +For production applications: +``` +Client App <-> Your Backend <-> Fishjam Media Server +``` + +## Supported Protocols and Standards + +### WebRTC Standards +- **DTLS-SRTP**: Secure media transport +- **ICE/STUN/TURN**: NAT traversal and connectivity +- **SDP**: Session description and negotiation + +### Streaming Protocols +- **WHEP**: WebRTC-HTTP Egress Protocol (for viewers) +- **WHIP**: WebRTC-HTTP Ingress Protocol (for broadcasters) + +### Codecs Supported +- **Video**: H.264, VP8 +- **Audio**: Opus, G.711 + +## Performance Characteristics + +### Latency +- **P2P-style**: < 100ms between participants +- **Livestream**: < 500ms broadcaster to viewer +- **Geographic optimization**: Edge servers reduce latency + +### Quality +- **Adaptive bitrate**: Automatically adjusts to network conditions +- **Quality controls**: Client-side quality management +- **Hardware acceleration**: Uses device capabilities when available + +## Next Steps + +To understand different room types in detail, see [Room Types Explained](/explanation/room-types). + +To learn about security and token management, see [Security & Token Model](/explanation/security-tokens). + +Ready to implement? Start with our tutorials: +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) \ No newline at end of file diff --git a/docs/explanation/core-concepts.mdx b/docs/explanation/core-concepts.mdx new file mode 100644 index 00000000..6713bcf7 --- /dev/null +++ b/docs/explanation/core-concepts.mdx @@ -0,0 +1,240 @@ +--- +type: explanation +--- + +# Core Concepts + +**Explanation** - *Essential concepts you need to understand to work with Fishjam* + +Understanding these core concepts will help you design and build applications with Fishjam more effectively. + +## Rooms + +### What is a Room? +A **room** is a logical container that groups participants together for multimedia communication. Think of it as a virtual meeting space where peers can join to share audio and video. + +### Room Characteristics +- **Unique identity**: Each room has a unique ID +- **Type-specific**: Room type (full-feature, audio-only, livestream) is set at creation +- **Isolated**: Participants in different rooms cannot interact +- **Temporary**: Rooms exist only while needed, can be deleted when empty + +### Room Lifecycle +1. **Creation**: Backend creates room using Server SDK +2. **Population**: Peers are added to the room +3. **Activity**: Peers connect and communicate +4. **Cleanup**: Room is deleted when no longer needed + +## Peers + +### What is a Peer? +A **peer** represents a single participant in a room. Each peer corresponds to one client connection (e.g., one user's phone or browser). + +### Peer Characteristics +- **Unique within room**: Each peer has a unique ID within their room +- **Associated metadata**: Custom data attached when creating the peer +- **Track ownership**: Peers own the tracks (audio/video streams) they send +- **State management**: Connection status, track states + +### Peer Lifecycle +1. **Creation**: Backend creates peer in a room (gets peer token) +2. **Connection**: Client uses peer token to connect to room +3. **Media sharing**: Peer sends/receives tracks +4. **Disconnection**: Peer leaves room or connection drops +5. **Cleanup**: Peer is removed from room + +## Tracks + +### What is a Track? +A **track** represents a single stream of media data - either audio or video. Each track carries one type of media from one source. + +### Track Types +- **Video tracks**: Camera feed, screen sharing, custom video +- **Audio tracks**: Microphone, system audio, custom audio + +### Track Characteristics +- **Owned by peers**: Each track belongs to one peer +- **Typed**: Video or audio, cannot change type +- **Stateful**: Active/inactive, enabled/disabled +- **Metadata**: Description, source information + +### Track Examples +- Camera from user's phone → Video track +- Microphone from user's computer → Audio track +- Screen sharing → Video track (screen content) +- Shared app audio → Audio track (application sound) + +## Tokens + +### Management Tokens +**Management tokens** are long-lived credentials that authorize your backend to control Fishjam resources. + +#### Characteristics +- **Backend-only**: Never expose to client applications +- **Long-lived**: Remain valid until regenerated +- **Full access**: Can create/delete rooms and peers +- **Environment-specific**: Different tokens for sandbox vs production + +#### Usage +```typescript +const fishjamClient = new FishjamClient({ + fishjamUrl, + managementToken: process.env.MANAGEMENT_TOKEN +}); +``` + +### Peer Tokens +**Peer tokens** are short-lived credentials that allow client applications to join specific rooms. + +#### Characteristics +- **Client-safe**: Safe to send to frontend applications +- **Short-lived**: Expire after reasonable time period +- **Room-specific**: Grant access to one specific room only +- **Peer-specific**: Tied to one peer identity + +#### Generation +```typescript +// Backend generates peer token +const { peer, peerToken } = await fishjamClient.createPeer(roomId, { + metadata: { name: "John Doe" } +}); + +// Send to client +response.json({ peerToken, fishjamUrl }); +``` + +#### Usage +```typescript +// Client uses peer token to connect +await joinRoom({ url: fishjamUrl, peerToken }); +``` + +## Metadata + +### What is Metadata? +**Metadata** is custom data associated with peers that other participants can read. It's set when creating a peer and cannot be changed afterward. + +### Use Cases +- **User information**: Names, avatars, roles +- **Application state**: User preferences, permissions +- **Custom identifiers**: External user IDs, session data + +### Example +```typescript +// Backend sets metadata when creating peer +const { peer, peerToken } = await fishjamClient.createPeer(roomId, { + metadata: { + name: "Alice Johnson", + role: "presenter", + avatar: "https://example.com/avatar.jpg", + userId: "user-123" + } +}); +``` + +```typescript +// Clients can read metadata of all peers +const { remotePeers } = usePeers(); +remotePeers.forEach(peer => { + console.log(peer.metadata.name); // "Alice Johnson" +}); +``` + +## Media Flow Architecture + +### Client-Server-Client Pattern +Fishjam uses a **Selective Forwarding Unit (SFU)** architecture: + +1. **Upload**: Each peer sends their media to Fishjam servers +2. **Processing**: Server processes, adapts quality, applies policies +3. **Distribution**: Server forwards media to other peers in the room +4. **Download**: Each peer receives media from other participants + +### Benefits of SFU Architecture +- **Bandwidth efficiency**: Each client uploads once, server handles distribution +- **Quality adaptation**: Server can adjust quality per recipient +- **Selective forwarding**: Server can choose which streams to forward +- **Scalability**: Adding participants doesn't exponentially increase bandwidth + +## Connection States + +### Peer Connection States +Understanding connection states helps with UI and error handling: + +- **`connecting`**: Attempting to join room +- **`connected`**: Successfully connected and ready +- **`reconnecting`**: Temporarily disconnected, attempting to reconnect +- **`disconnected`**: Permanently disconnected from room + +### Track States +Tracks also have states that affect media flow: + +- **`active`**: Track is sending/receiving media +- **`inactive`**: Track exists but no media flowing +- **`enabled`**: Track is enabled (user choice) +- **`disabled`**: Track is disabled (user choice) + +## Room vs Peer vs Track Hierarchy + +``` +Room (container) +├── Peer 1 (participant) +│ ├── Video Track (camera) +│ ├── Audio Track (microphone) +│ └── Video Track (screen share) +├── Peer 2 (participant) +│ ├── Video Track (camera) +│ └── Audio Track (microphone) +└── Peer 3 (participant) + └── Audio Track (microphone only) +``` + +## Data Flow Example + +Here's a complete example of how these concepts work together: + +### 1. Room Setup (Backend) +```typescript +// Create room +const room = await fishjamClient.createRoom({ roomType: 'full-feature' }); + +// Add peer for Alice +const { peer: alicePeer, peerToken: aliceToken } = + await fishjamClient.createPeer(room.id, { + metadata: { name: "Alice", role: "host" } + }); + +// Add peer for Bob +const { peer: bobPeer, peerToken: bobToken } = + await fishjamClient.createPeer(room.id, { + metadata: { name: "Bob", role: "participant" } + }); +``` + +### 2. Client Connection +```typescript +// Alice's client connects +await joinRoom({ url: fishjamUrl, peerToken: aliceToken }); + +// Bob's client connects +await joinRoom({ url: fishjamUrl, peerToken: bobToken }); +``` + +### 3. Media Sharing +- Alice starts camera → Creates video track +- Alice starts microphone → Creates audio track +- Bob starts microphone → Creates audio track +- Bob receives Alice's video and audio tracks +- Alice receives Bob's audio track + +## Next Steps + +Now that you understand the core concepts: + +- Learn about [Room Types](/explanation/room-types) and when to use each +- Understand [Security & Tokens](/explanation/security-tokens) in detail +- See how it all works in [Fishjam Architecture](/explanation/architecture) + +Ready to implement? Start with: +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) \ No newline at end of file diff --git a/docs/explanation/room-manager-concept.mdx b/docs/explanation/room-manager-concept.mdx new file mode 100644 index 00000000..c4e6ab6e --- /dev/null +++ b/docs/explanation/room-manager-concept.mdx @@ -0,0 +1,162 @@ +--- +type: explanation +--- + +# Room Manager Concept + +**Explanation** - *Understanding what Room Manager is and why it exists* + +Room Manager is a development tool that simplifies getting started with Fishjam by providing a simple backend for testing, eliminating the need to build your own server initially. + +## What is Room Manager? + +Room Manager is an HTTP server that comes with Fishjam's Sandbox environment. It provides basic room creation and peer management functionality without requiring you to set up your own backend infrastructure. + +### Key Characteristics +- **Development-focused**: Designed for initial development and testing +- **No authentication**: Simplified access for quick prototyping +- **HTTP-based**: Simple REST API for room and peer management +- **Sandbox-only**: Only available in Sandbox environments + +## The Problem Room Manager Solves + +When starting with Fishjam development, you typically need: + +1. **Backend server** to create rooms +2. **Authentication system** to manage users +3. **Token management** for secure peer access +4. **API endpoints** for your frontend to call + +This creates a chicken-and-egg problem: to test your frontend, you need a backend, but you might want to focus on frontend development first. + +## Room Manager's Solution + +Room Manager provides a pre-built backend so you can: +- **Start frontend development immediately** +- **Test Fishjam integration** without backend setup +- **Focus on client-side features** first +- **Prototype quickly** with minimal infrastructure + +## Development vs Production Pattern + +### Development Pattern (with Room Manager) +``` +Client App → Room Manager → Fishjam Media Server +``` +- Client directly calls Room Manager API +- No authentication required +- Simple URL-based room creation +- Perfect for prototyping and testing + +### Production Pattern (your backend) +``` +Client App → Your Backend → Fishjam Media Server +``` +- Client calls your authenticated API +- Your backend creates rooms using Server SDKs +- Proper user authentication and authorization +- Full control over room lifecycle and permissions + +## Why Room Manager is NOT for Production + +### Security Limitations +- **No authentication**: Anyone with the URL can create rooms +- **Shared tokens**: Same room/peer names get identical tokens +- **Public access**: No user management or access control +- **No rate limiting**: Potential for abuse + +### Functional Limitations +- **Basic features only**: Limited compared to Server SDKs +- **No customization**: Fixed behavior and responses +- **No webhooks**: No event handling capabilities +- **No advanced room configuration**: Basic room creation only + +### Example Security Issue +``` +// Anyone who knows this URL can join: +https://fishjam.io/api/v1/connect/YOUR_ID/room-manager?roomName=secret&peerName=hacker + +// They get the same token as legitimate users: +{ + "peerToken": "same-token-for-same-names", + "url": "wss://fishjam.io/api/v1/connect/YOUR_ID" +} +``` + +## When to Use Room Manager + +### ✅ Good Use Cases +- **Initial learning** and experimentation +- **Frontend development** before backend is ready +- **Proof of concepts** and demos +- **Quick testing** of Fishjam features +- **Understanding Fishjam concepts** before production planning + +### ❌ Avoid for +- **Production applications** of any kind +- **User-facing demos** with real users +- **Any scenario requiring security** +- **Long-term testing environments** + +## Transition Strategy + +### Phase 1: Learning (Room Manager) +- Use Room Manager to understand Fishjam concepts +- Build and test your frontend components +- Experiment with different room types and features + +### Phase 2: Development (Room Manager + Planning) +- Continue using Room Manager for frontend development +- Plan your production backend architecture +- Design authentication and user management systems + +### Phase 3: Production (Your Backend) +- Implement backend using Server SDKs +- Replace Room Manager calls with your API calls +- Add proper authentication and security measures +- Deploy to production environment + +## The Source Code Advantage + +Room Manager's source code is available as an [example in the js-server-sdk repository](https://github.com/fishjam-cloud/js-server-sdk/tree/main/examples/room-manager). + +### Benefits of Source Access +- **Learning resource**: See how to implement Fishjam server integration +- **Reference implementation**: Example of best practices +- **Customization starting point**: Fork and modify for your needs +- **Architecture understanding**: Learn the patterns used + +## Relationship to Server SDKs + +Room Manager is essentially a simplified application built using Fishjam Server SDKs: + +```typescript +// What Room Manager does internally (simplified) +const fishjamClient = new FishjamClient({ fishjamUrl, managementToken }); + +app.get('/room-manager', async (req, res) => { + const { roomName, peerName, roomType } = req.query; + + // Create or get room + const room = await fishjamClient.createRoom({ roomType }); + + // Create peer + const { peer, peerToken } = await fishjamClient.createPeer(room.id); + + res.json({ peerToken, url: fishjamUrl }); +}); +``` + +This shows you exactly what your production backend needs to do, just with proper authentication and error handling. + +## Next Steps + +To understand how to use Room Manager for development: +- [How to use Room Manager for testing](/how-to/features/room-manager-testing) + +To learn about building your own backend: +- [Backend Quick Start Tutorial](/tutorials/backend-quick-start) +- [How to set up your server](/how-to/backend/server-setup) + +To understand the security model: +- [Security & Token Model](/explanation/security-tokens) \ No newline at end of file diff --git a/docs/explanation/room-types.mdx b/docs/explanation/room-types.mdx new file mode 100644 index 00000000..b6f1a81c --- /dev/null +++ b/docs/explanation/room-types.mdx @@ -0,0 +1,176 @@ +--- +type: explanation +--- + +# Room Types Explained + +**Explanation** - *Understanding different types of rooms and when to use them* + +Fishjam provides three distinct room types, each optimized for different use cases and scenarios. Understanding these room types helps you choose the right approach for your application. + +## Full-feature Rooms (Default) + +### What are Full-feature Rooms? +Full-feature rooms are the default room type designed for multi-participant video conferencing scenarios. They support all Fishjam features and provide the most flexibility. + +### Key Characteristics +- **Multi-participant**: Support for many participants simultaneously +- **Bidirectional media**: All participants can send and receive video/audio +- **Rich features**: Screen sharing, multiple video tracks, audio controls +- **Flexible track management**: Participants can add/remove tracks dynamically + +### Architecture +Full-feature rooms use a Selective Forwarding Unit (SFU) architecture: +- Each participant sends their media to Fishjam Media Server +- Server selectively forwards streams to other participants +- Efficient bandwidth usage compared to mesh networking +- Quality adaptation based on network conditions + +### Best Use Cases +- **Video conferencing applications** (Zoom-like experiences) +- **Virtual meetings** with screen sharing +- **Collaborative workspaces** with multiple media types +- **Interactive webinars** with participant engagement + +### Cost Considerations +Full-feature rooms are priced based on total connection time of all peers. + +## Audio-only Rooms + +### What are Audio-only Rooms? +Audio-only rooms are optimized specifically for voice communication, removing video capabilities to improve performance and reduce costs. + +### Key Characteristics +- **Voice-only communication**: No video tracks allowed +- **Optimized bandwidth**: Reduced network usage +- **Better performance**: Lower CPU and battery usage +- **Higher capacity**: Support for more simultaneous participants + +### Architecture +- Similar to full-feature rooms but audio-only routing +- Optimized audio processing and codec selection +- Reduced server resources per participant +- Enhanced audio quality algorithms + +### Best Use Cases +- **Voice-only conferencing** and calls +- **Podcast recording** with multiple participants +- **Audio chat applications** +- **Large-scale audio events** (town halls, announcements) + +### Cost Benefits +Audio-only rooms come at a **75% discount** compared to full-feature rooms: +- 2 peers for 30 minutes = 60 minutes total time in full-feature room +- Same scenario in audio-only room = 15 minutes equivalent cost + +### Video Behavior in Audio-only Rooms +If you attempt to add video to an audio-only room: +- Video tracks are ignored (not transmitted) +- SDKs log warnings to help with debugging +- Only audio from screen sharing is transmitted +- No errors thrown, graceful degradation + +## Livestream Rooms + +### What are Livestream Rooms? +Livestream rooms are designed for one-to-many broadcasting scenarios where a single broadcaster streams to multiple viewers. + +### Key Characteristics +- **One broadcaster**: Only one peer can send media +- **Many viewers**: Unlimited viewers can watch +- **Optimized for scale**: Efficient distribution architecture +- **Low latency**: Optimized for real-time broadcasting +- **WHEP compatibility**: Standards-based viewer connections + +### Architecture +- **Broadcaster**: Sends video/audio using standard Fishjam client SDKs +- **Viewers**: Connect using WHEP (WebRTC-HTTP Egress Protocol) +- **Media distribution**: Optimized server-side distribution +- **Geographic distribution**: Edge servers for global reach + +### Broadcasting Limitations +- **Single video track**: Only one video stream allowed +- **Single audio track**: Only one audio stream allowed +- **Additional tracks ignored**: Extra tracks are not forwarded to viewers + +### Viewer Experience +- **Token-based access**: Viewers need special viewer tokens +- **Standard compatibility**: Any WHEP-compatible player works +- **Automatic quality**: Adaptive streaming based on viewer connection + +### Best Use Cases +- **Live events** and webinars +- **Streaming platforms** and content distribution +- **Corporate broadcasts** and announcements +- **Educational content** delivery +- **Sports and entertainment** streaming + +### Cost Benefits +Livestream rooms are **20% cheaper** than full-feature rooms for equivalent usage. + +## Choosing the Right Room Type + +### Decision Matrix + +| Use Case | Room Type | Why | +|----------|-----------|-----| +| Video meetings with 2-10 people | Full-feature | Bidirectional video, screen sharing | +| Large video conference (10+ people) | Full-feature | Multi-participant support | +| Voice-only meetings | Audio-only | Cost savings, better performance | +| Podcast recording | Audio-only | Audio focus, multiple participants | +| Webinar (1 presenter, many viewers) | Livestream | One-to-many, cost effective | +| Live event streaming | Livestream | Scalable viewing, optimized distribution | +| Interactive workshop | Full-feature | Participant engagement, screen sharing | + +### Performance Considerations + +#### Network Bandwidth +- **Full-feature**: Highest bandwidth usage +- **Audio-only**: Lowest bandwidth usage +- **Livestream**: Moderate for broadcaster, low for viewers + +#### Server Resources +- **Full-feature**: Highest server resource usage +- **Audio-only**: Lowest server resource usage +- **Livestream**: Optimized for many viewers + +#### Client Performance +- **Full-feature**: Higher CPU/battery usage +- **Audio-only**: Lowest resource usage +- **Livestream**: Low for viewers, normal for broadcaster + +### Migration Between Room Types +Room types are set at creation time and cannot be changed: +- Each room has a fixed type for its entire lifecycle +- To change types, create a new room +- Plan your room type choice carefully + +### Development vs Production +For development, you can create any room type using [Room Manager](/how-to/features/room-manager-testing). + +For production, room types are specified when creating rooms via [Server SDKs](/how-to/backend/server-setup): + +```typescript +// Full-feature room (default) +const fullRoom = await fishjamClient.createRoom(); + +// Audio-only room +const audioRoom = await fishjamClient.createRoom({ roomType: 'audio_only' }); + +// Livestream room +const liveRoom = await fishjamClient.createRoom({ roomType: 'livestream' }); +``` + +## Next Steps + +To understand how to implement each room type: +- [How to create audio-only calls](/how-to/features/audio-only-calls) +- [How to implement livestreaming](/how-to/features/livestreaming) + +To learn about the underlying architecture: +- [Fishjam Architecture](/explanation/architecture) +- [Security & Token Model](/explanation/security-tokens) + +Ready to start building? Check our tutorials: +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) \ No newline at end of file diff --git a/docs/explanation/security-tokens.mdx b/docs/explanation/security-tokens.mdx new file mode 100644 index 00000000..3e3dfb38 --- /dev/null +++ b/docs/explanation/security-tokens.mdx @@ -0,0 +1,312 @@ +--- +type: explanation +--- + +# Security & Token Model + +**Explanation** - *Understanding Fishjam's security architecture and token system* + +Fishjam uses a token-based security model to ensure secure access control while keeping the developer experience simple. + +## Security Architecture Overview + +Fishjam's security is built on a **two-tier token system**: + +1. **Management Tokens**: For backend-to-Fishjam server communication +2. **Peer Tokens**: For client-to-Fishjam server communication + +This separation ensures that sensitive operations remain on your backend while allowing clients secure, limited access to media streaming. + +## Management Tokens + +### Purpose +Management tokens provide your backend server with administrative access to Fishjam resources. They allow creating, managing, and deleting rooms and peers. + +### Characteristics +- **Long-lived**: Valid until manually regenerated +- **High privilege**: Can perform any operation on your Fishjam instance +- **Backend-only**: Never send to client applications +- **Environment-specific**: Different tokens for sandbox and production + +### What Management Tokens Can Do +```typescript +const fishjamClient = new FishjamClient({ fishjamUrl, managementToken }); + +// Full administrative access: +await fishjamClient.createRoom(); // Create rooms +await fishjamClient.deleteRoom(roomId); // Delete rooms +await fishjamClient.createPeer(roomId); // Add peers +await fishjamClient.deletePeer(roomId, peerId); // Remove peers +await fishjamClient.getRooms(); // List all rooms +``` + +### Security Best Practices +- **Environment variables**: Store in secure environment variables +- **Server-side only**: Never include in client-side code +- **Rotation**: Regenerate periodically or when compromised +- **Access control**: Limit backend server access to management tokens + +### Example Secure Storage +```typescript +// ✅ Correct: Server-side environment variable +const managementToken = process.env.FISHJAM_MANAGEMENT_TOKEN; + +// ❌ Wrong: Never in client code +const managementToken = "your-management-token"; // DON'T DO THIS +``` + +## Peer Tokens + +### Purpose +Peer tokens provide client applications with limited, time-bound access to join a specific room as a specific peer. + +### Characteristics +- **Short-lived**: Expire after a reasonable time period +- **Scope-limited**: Access to one specific room only +- **Client-safe**: Safe to send to frontend applications +- **Single-use concept**: Tied to one peer identity + +### What Peer Tokens Can Do +Peer tokens allow clients to: +- Connect to the specific room they were issued for +- Send and receive media streams within that room +- Access peer metadata and room state +- Participate in room activities (audio/video/screen sharing) + +### What Peer Tokens Cannot Do +- Create or delete rooms +- Add or remove other peers +- Access different rooms +- Perform administrative operations +- Access management functions + +### Generation Process +```typescript +// Backend generates peer token (using management token) +const { peer, peerToken } = await fishjamClient.createPeer(roomId, { + metadata: { name: "John Doe", userId: "user-123" } +}); + +// Backend sends peer token to client +res.json({ + peerToken, // Client uses this to connect + fishjamUrl, // Fishjam server URL + roomId: peer.roomId // Room information +}); +``` + +### Client Usage +```typescript +// Client uses peer token to connect (safe to use in frontend) +await joinRoom({ + url: fishjamUrl, + peerToken: peerToken // This is safe in client code +}); +``` + +## Token Lifecycle + +### Management Token Lifecycle +``` +Generate → Store Securely → Use in Backend → Rotate Periodically + ↑ ↓ + ←──────────── Regenerate if Compromised ←────── +``` + +### Peer Token Lifecycle +``` +Backend Request → Create Peer → Generate Token → Send to Client + ↓ +Client Connect → Validate Token → Join Room → Media Streaming + ↓ + Token Expires → Connection Ends +``` + +## Security Benefits + +### Principle of Least Privilege +- **Clients**: Only get access to what they need (one room) +- **Backend**: Has administrative control but stays secure +- **Isolation**: Peers cannot interfere with other rooms or peers + +### Time-bound Access +- **Automatic expiration**: Peer tokens expire automatically +- **Reduced attack window**: Short-lived tokens limit security exposure +- **Session control**: Backend controls how long clients can stay connected + +### No Direct Backend Access +- **Client isolation**: Clients never access your backend credentials +- **Reduced attack surface**: Management tokens never leave your backend +- **Secure delegation**: Clients get just enough access through peer tokens + +## Authentication Patterns + +### Pattern 1: Simple Authentication +```typescript +// Backend endpoint (authenticated by your system) +app.post('/join-room', authenticateUser, async (req, res) => { + const userId = req.user.id; + const { roomName } = req.body; + + // Create room if needed + const room = await getOrCreateRoom(roomName); + + // Create peer with user info + const { peer, peerToken } = await fishjamClient.createPeer(room.id, { + metadata: { + name: req.user.name, + userId: userId, + avatar: req.user.avatar + } + }); + + res.json({ peerToken, fishjamUrl }); +}); +``` + +### Pattern 2: Role-based Access +```typescript +app.post('/join-room', authenticateUser, async (req, res) => { + const user = req.user; + const { roomId } = req.body; + + // Check permissions + if (!canUserJoinRoom(user, roomId)) { + return res.status(403).json({ error: 'Access denied' }); + } + + // Determine role-based metadata + const metadata = { + name: user.name, + role: user.role, // 'host', 'presenter', 'participant' + permissions: getUserPermissions(user, roomId) + }; + + const { peer, peerToken } = await fishjamClient.createPeer(roomId, { metadata }); + res.json({ peerToken, fishjamUrl }); +}); +``` + +## Common Security Pitfalls + +### ❌ Don't: Expose Management Tokens +```typescript +// DON'T: Send management token to client +res.json({ + managementToken: process.env.FISHJAM_MANAGEMENT_TOKEN, // NEVER + peerToken +}); +``` + +### ❌ Don't: Store Tokens in Client Storage +```typescript +// DON'T: Store sensitive tokens in localStorage/sessionStorage +localStorage.setItem('managementToken', token); // NEVER +``` + +### ❌ Don't: Use Peer Tokens for Backend Operations +```typescript +// DON'T: Try to create rooms with peer token +const client = new FishjamClient({ fishjamUrl, managementToken: peerToken }); // WON'T WORK +``` + +### ✅ Do: Validate Users Before Creating Peers +```typescript +// DO: Always authenticate users in your backend +app.post('/join-room', async (req, res) => { + // Authenticate user first + const user = await authenticateRequest(req); + if (!user) { + return res.status(401).json({ error: 'Unauthorized' }); + } + + // Then create peer + const { peer, peerToken } = await fishjamClient.createPeer(roomId, { + metadata: { userId: user.id, name: user.name } + }); + + res.json({ peerToken, fishjamUrl }); +}); +``` + +## Token Rotation and Management + +### Management Token Rotation +```typescript +// Regular rotation schedule +const rotateManagementToken = async () => { + // 1. Generate new token in Fishjam dashboard + // 2. Update environment variables + // 3. Restart application with new token + // 4. Revoke old token +}; +``` + +### Handling Token Expiration +```typescript +// Client-side: Handle peer token expiration +const { peerStatus } = useConnection(); + +useEffect(() => { + if (peerStatus === 'disconnected') { + // Token may have expired, request new one + refreshTokenAndReconnect(); + } +}, [peerStatus]); + +const refreshTokenAndReconnect = async () => { + const response = await fetch('/api/refresh-room-access'); + const { peerToken } = await response.json(); + await joinRoom({ url: fishjamUrl, peerToken }); +}; +``` + +## Security Monitoring + +### What to Monitor +- **Failed authentication attempts**: Multiple failed peer creations +- **Unusual room creation patterns**: Spike in room creation +- **Token usage patterns**: Peer tokens used outside expected timeframes + +### Logging Best Practices +```typescript +// Log security events (but not token values) +app.post('/join-room', async (req, res) => { + try { + const user = await authenticateRequest(req); + + // Log successful peer creation (without token value) + logger.info('Peer created', { + userId: user.id, + roomId, + timestamp: new Date().toISOString(), + // Don't log actual token values + }); + + const { peer, peerToken } = await fishjamClient.createPeer(roomId, { metadata }); + res.json({ peerToken, fishjamUrl }); + + } catch (error) { + // Log security errors + logger.error('Failed peer creation', { + error: error.message, + ip: req.ip, + userAgent: req.get('User-Agent') + }); + res.status(500).json({ error: 'Access denied' }); + } +}); +``` + +## Next Steps + +To implement secure authentication: +- [Backend Quick Start Tutorial](/tutorials/backend-quick-start) +- [How to set up your server](/how-to/backend/server-setup) + +To understand the broader architecture: +- [Fishjam Architecture](/explanation/architecture) +- [Core Concepts](/explanation/core-concepts) + +To learn about Room Manager's security limitations: +- [Room Manager Concept](/explanation/room-manager-concept) \ No newline at end of file diff --git a/docs/explanation/what-is-fishjam.mdx b/docs/explanation/what-is-fishjam.mdx new file mode 100644 index 00000000..677b5e6d --- /dev/null +++ b/docs/explanation/what-is-fishjam.mdx @@ -0,0 +1,91 @@ +--- +type: explanation +--- + +# What is Fishjam? + +**Explanation** - *Understanding the concept and purpose of Fishjam* + +Fishjam is a multimedia streaming toolkit that allows you to build real-time video and audio streaming applications using [WebRTC](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API). +We provide the infrastructure, media server, and client SDKs so you can focus on building your apps. + +**No WebRTC knowledge is required!** + +## The Problem Fishjam Solves + +Building real-time video and audio applications is complex. Developers typically need to: + +- Set up and manage WebRTC infrastructure +- Handle complex peer-to-peer networking +- Manage media servers and scaling +- Deal with different devices and codec compatibility +- Implement secure token-based authentication + +Fishjam abstracts away this complexity, providing a simple API and managed infrastructure. + +## What Fishjam Provides + +Fishjam consists of several components that work together to provide a seamless multimedia streaming experience: + +| Component | Description | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| Developer panel | Developer panel for setting up your own Fishjam Media Server. | +| Fishjam Media Server | A media server that will route your multimedia traffic. We host and manage it for you. You can control it via the developer panel. | +| Fishjam Client SDKs | Toolkit used for multimedia integration on endpoint devices. | +| Fishjam Server SDKs | Toolkit for integrating your backend with Fishjam. We support Python and NodeJS as well as REST API. | +| Room Manager | Simple backend for creating test rooms. You no longer need to bring your own backend to develop frontend apps. | + +## Use Cases + +Fishjam is ideal for: + +### Video Conferencing +Build Zoom-like applications with multiple participants in rooms, screen sharing, and audio/video controls. + +### Livestreaming +Stream live content from one broadcaster to many viewers with low latency, perfect for webinars, live events, or streaming platforms. + +### Audio-only Applications +Create voice-only experiences like audio conferencing, podcasts, or voice chat applications. + +## Key Benefits + +### 🚀 **Fast Development** +Get started quickly with our SDKs and Room Manager for testing - no backend setup required initially. + +### 🔧 **No WebRTC Expertise Needed** +Our SDKs handle all the WebRTC complexity, codec negotiations, and networking. + +### 📱 **Cross-platform** +Works on React Native (iOS/Android), React/Web, and server-side environments. + +### 🛡️ **Secure by Default** +Token-based authentication and secure media routing built-in. + +### 💰 **Cost-effective** +Pay only for what you use, with special pricing for audio-only rooms. + +## How It Differs from Alternatives + +Unlike pure WebRTC solutions, Fishjam provides: +- Managed infrastructure (no server setup required) +- Simple APIs (no WebRTC knowledge needed) +- Built-in scaling and reliability +- Multiple room types optimized for different use cases + +Unlike generic streaming platforms, Fishjam offers: +- Real-time, low-latency communication +- Full control over your application experience +- Developer-friendly APIs and SDKs +- Flexible room management + +## Next Steps + +To understand how Fishjam works technically, see [Fishjam Architecture](/explanation/architecture). + +To learn about the different types of rooms available, see [Room Types Explained](/explanation/room-types). + +Ready to start building? Check out our tutorials: +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [React Quick Start](/tutorials/react-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) \ No newline at end of file diff --git a/docs/_common/metadata/header.mdx b/docs/how-to/_common/metadata/header.mdx similarity index 100% rename from docs/_common/metadata/header.mdx rename to docs/how-to/_common/metadata/header.mdx diff --git a/docs/_common/metadata/joining_room.mdx b/docs/how-to/_common/metadata/joining_room.mdx similarity index 100% rename from docs/_common/metadata/joining_room.mdx rename to docs/how-to/_common/metadata/joining_room.mdx diff --git a/docs/_common/metadata/reading.mdx b/docs/how-to/_common/metadata/reading.mdx similarity index 100% rename from docs/_common/metadata/reading.mdx rename to docs/how-to/_common/metadata/reading.mdx diff --git a/docs/_common/metadata/updating.mdx b/docs/how-to/_common/metadata/updating.mdx similarity index 100% rename from docs/_common/metadata/updating.mdx rename to docs/how-to/_common/metadata/updating.mdx diff --git a/docs/production/examples/fastapi.mdx b/docs/how-to/backend/fastapi-example.mdx similarity index 100% rename from docs/production/examples/fastapi.mdx rename to docs/how-to/backend/fastapi-example.mdx diff --git a/docs/production/examples/fastify.mdx b/docs/how-to/backend/fastify-example.mdx similarity index 100% rename from docs/production/examples/fastify.mdx rename to docs/how-to/backend/fastify-example.mdx diff --git a/docs/how-to/backend/production-deployment.mdx b/docs/how-to/backend/production-deployment.mdx new file mode 100644 index 00000000..1e72964b --- /dev/null +++ b/docs/how-to/backend/production-deployment.mdx @@ -0,0 +1,479 @@ +--- +type: how-to +--- + +# How to Deploy Fishjam to Production + +**How-to Guide** - *Deploy your Fishjam backend safely to production* + +This guide covers the essential steps to move from development (using Room Manager) to a production-ready Fishjam backend deployment. + +## Prerequisites + +- Working Fishjam backend (see [Backend Quick Start](/tutorials/backend-quick-start)) +- Production Fishjam environment (not Sandbox) +- Domain and SSL certificates for your backend +- Production database and infrastructure + +## Step 1: Set up production Fishjam environment + +### Get production credentials + +1. Log in to [Fishjam Dashboard](https://fishjam.io/app) +2. Create or select your **Production** environment (not Sandbox) +3. Copy your production **Fishjam URL** and **Management Token** +4. Note: These are different from your sandbox credentials + +### Environment variables setup + +Create production environment variables: + +```bash +# Production Fishjam credentials +FISHJAM_URL="your-production-fishjam-url" +FISHJAM_MANAGEMENT_TOKEN="your-production-management-token" + +# Your application settings +NODE_ENV="production" +PORT="3000" +DATABASE_URL="your-production-database-url" + +# Security settings +JWT_SECRET="your-secure-jwt-secret" +CORS_ORIGIN="https://yourdomain.com" +``` + +## Step 2: Implement proper authentication + +### Replace Room Manager calls + +Remove any Room Manager dependencies from your client code: + +```typescript +// ❌ Remove: Room Manager calls +const response = await fetch( + `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager?...` +); + +// ✅ Replace with: Your authenticated API +const response = await fetch('/api/join-room', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${userToken}` + }, + body: JSON.stringify({ roomName }) +}); +``` + +### Implement user authentication + +```typescript +import jwt from 'jsonwebtoken'; +import { FishjamClient } from '@fishjam-cloud/js-server-sdk'; + +const fishjamClient = new FishjamClient({ + fishjamUrl: process.env.FISHJAM_URL!, + managementToken: process.env.FISHJAM_MANAGEMENT_TOKEN! +}); + +// Authentication middleware +const authenticateUser = async (req, res, next) => { + try { + const token = req.headers.authorization?.replace('Bearer ', ''); + if (!token) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + req.user = await getUserById(decoded.userId); + next(); + } catch (error) { + res.status(401).json({ error: 'Invalid token' }); + } +}; + +// Protected endpoint for joining rooms +app.post('/api/join-room', authenticateUser, async (req, res) => { + try { + const { roomName } = req.body; + const user = req.user; + + // Create or get room + const room = await getOrCreateRoom(roomName); + + // Verify user has permission to join this room + if (!canUserJoinRoom(user, room)) { + return res.status(403).json({ error: 'Access denied' }); + } + + // Create peer with user metadata + const { peer, peerToken } = await fishjamClient.createPeer(room.id, { + metadata: { + userId: user.id, + name: user.name, + avatar: user.avatar, + role: user.role + } + }); + + res.json({ + peerToken, + fishjamUrl: process.env.FISHJAM_URL + }); + + } catch (error) { + console.error('Join room error:', error); + res.status(500).json({ error: 'Failed to join room' }); + } +}); +``` + +## Step 3: Implement security best practices + +### Rate limiting + +```typescript +import rateLimit from 'express-rate-limit'; + +// Rate limit room creation +const roomLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 10, // Limit each user to 10 room joins per window + message: 'Too many room join attempts, please try again later.', + standardHeaders: true, + legacyHeaders: false, +}); + +app.post('/api/join-room', roomLimiter, authenticateUser, async (req, res) => { + // ... room joining logic +}); +``` + +### Input validation + +```typescript +import { body, validationResult } from 'express-validator'; + +const validateJoinRoom = [ + body('roomName').isString().isLength({ min: 1, max: 100 }).trim(), + body('roomType').optional().isIn(['full-feature', 'audio-only', 'livestream']), +]; + +app.post('/api/join-room', + validateJoinRoom, + authenticateUser, + async (req, res) => { + // Check validation results + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + + // ... proceed with room joining + } +); +``` + +### CORS configuration + +```typescript +import cors from 'cors'; + +const corsOptions = { + origin: process.env.CORS_ORIGIN?.split(',') || ['http://localhost:3000'], + credentials: true, + optionsSuccessStatus: 200 +}; + +app.use(cors(corsOptions)); +``` + +## Step 4: Handle webhooks and events + +### Set up webhook endpoint + +```typescript +import crypto from 'crypto'; + +// Webhook signature verification +const verifyWebhookSignature = (req, res, next) => { + const signature = req.headers['x-fishjam-signature']; + const payload = JSON.stringify(req.body); + + const expectedSignature = crypto + .createHmac('sha256', process.env.WEBHOOK_SECRET) + .update(payload, 'utf8') + .digest('hex'); + + if (signature !== expectedSignature) { + return res.status(401).json({ error: 'Invalid signature' }); + } + + next(); +}; + +// Webhook handler +app.post('/api/webhooks/fishjam', + express.raw({ type: 'application/json' }), + verifyWebhookSignature, + (req, res) => { + const event = req.body; + + switch (event.type) { + case 'peer_connected': + handlePeerConnected(event.data); + break; + case 'peer_disconnected': + handlePeerDisconnected(event.data); + break; + case 'room_empty': + handleRoomEmpty(event.data); + break; + default: + console.log('Unhandled event type:', event.type); + } + + res.status(200).json({ received: true }); + } +); +``` + +### Create rooms with webhooks + +```typescript +const createRoomWithWebhooks = async (roomName, roomType = 'full-feature') => { + const room = await fishjamClient.createRoom({ + roomType, + webhookUrl: `${process.env.BASE_URL}/api/webhooks/fishjam` + }); + + return room; +}; +``` + +## Step 5: Set up monitoring and logging + +### Structured logging + +```typescript +import winston from 'winston'; + +const logger = winston.createLogger({ + level: 'info', + format: winston.format.combine( + winston.format.timestamp(), + winston.format.errors({ stack: true }), + winston.format.json() + ), + transports: [ + new winston.transports.File({ filename: 'error.log', level: 'error' }), + new winston.transports.File({ filename: 'combined.log' }) + ] +}); + +// Use in your endpoints +app.post('/api/join-room', authenticateUser, async (req, res) => { + try { + // ... room joining logic + + logger.info('User joined room', { + userId: req.user.id, + roomName: req.body.roomName, + timestamp: new Date().toISOString() + }); + + } catch (error) { + logger.error('Room join failed', { + userId: req.user?.id, + error: error.message, + stack: error.stack + }); + + res.status(500).json({ error: 'Failed to join room' }); + } +}); +``` + +### Health checks + +```typescript +app.get('/health', async (req, res) => { + try { + // Check Fishjam connectivity + const rooms = await fishjamClient.getRooms(); + + res.json({ + status: 'healthy', + timestamp: new Date().toISOString(), + services: { + fishjam: 'connected', + database: 'connected' // Add your DB check + } + }); + } catch (error) { + res.status(503).json({ + status: 'unhealthy', + error: error.message + }); + } +}); +``` + +## Step 6: Configure HTTPS and domain + +### SSL/TLS setup + +```typescript +import https from 'https'; +import fs from 'fs'; + +// For production, use proper SSL certificates +const options = { + key: fs.readFileSync('path/to/private-key.pem'), + cert: fs.readFileSync('path/to/certificate.pem') +}; + +const server = https.createServer(options, app); +server.listen(443, () => { + console.log('HTTPS Server running on port 443'); +}); +``` + +### Environment-specific configuration + +```typescript +const config = { + development: { + fishjamUrl: process.env.FISHJAM_URL_DEV, + managementToken: process.env.FISHJAM_MANAGEMENT_TOKEN_DEV, + baseUrl: 'http://localhost:3000' + }, + production: { + fishjamUrl: process.env.FISHJAM_URL_PROD, + managementToken: process.env.FISHJAM_MANAGEMENT_TOKEN_PROD, + baseUrl: 'https://yourdomain.com' + } +}; + +const currentConfig = config[process.env.NODE_ENV || 'development']; +``` + +## Step 7: Deploy and monitor + +### Deployment checklist + +- [ ] Environment variables configured +- [ ] SSL certificates installed +- [ ] Database migrations run +- [ ] Webhook endpoints accessible +- [ ] Rate limiting configured +- [ ] Logging configured +- [ ] Health checks working +- [ ] Authentication implemented +- [ ] CORS properly configured + +### Production monitoring + +Set up monitoring for: +- **API response times**: Track join-room endpoint performance +- **Error rates**: Monitor failed room creations +- **Fishjam connectivity**: Ensure media server is reachable +- **Webhook delivery**: Track webhook success/failure rates +- **User activity**: Monitor concurrent users and room usage + +### Example monitoring with Prometheus + +```typescript +import prometheus from 'prom-client'; + +// Metrics +const roomJoinCounter = new prometheus.Counter({ + name: 'fishjam_room_joins_total', + help: 'Total number of room join attempts', + labelNames: ['status'] +}); + +const roomJoinDuration = new prometheus.Histogram({ + name: 'fishjam_room_join_duration_seconds', + help: 'Duration of room join operations' +}); + +// Use in your endpoint +app.post('/api/join-room', authenticateUser, async (req, res) => { + const timer = roomJoinDuration.startTimer(); + + try { + // ... room joining logic + roomJoinCounter.inc({ status: 'success' }); + res.json({ peerToken, fishjamUrl }); + } catch (error) { + roomJoinCounter.inc({ status: 'error' }); + res.status(500).json({ error: 'Failed to join room' }); + } finally { + timer(); + } +}); +``` + +## Common production issues + +### Issue: Token expiration handling + +**Solution**: Implement token refresh logic: + +```typescript +// Client-side token refresh +const refreshRoomAccess = async () => { + const response = await fetch('/api/refresh-room-access', { + method: 'POST', + headers: { 'Authorization': `Bearer ${authToken}` } + }); + + if (response.ok) { + const { peerToken } = await response.json(); + return peerToken; + } + + throw new Error('Failed to refresh room access'); +}; +``` + +### Issue: High load on room creation + +**Solution**: Implement room pooling or caching: + +```typescript +const roomCache = new Map(); + +const getOrCreateRoom = async (roomName) => { + if (roomCache.has(roomName)) { + return roomCache.get(roomName); + } + + const room = await fishjamClient.createRoom(); + roomCache.set(roomName, room); + + // Cache cleanup after room is empty + setTimeout(() => roomCache.delete(roomName), 5 * 60 * 1000); + + return room; +}; +``` + +## Next steps + +After production deployment: + +- Monitor your application performance +- Set up alerting for critical issues +- Plan for scaling based on usage patterns +- Review and update security practices regularly + +For scaling considerations: +- [Understanding Fishjam Architecture](/explanation/architecture) +- [Security best practices](/explanation/security-tokens) + +For specific backend frameworks: +- [FastAPI example](/how-to/backend/fastapi-example) +- [Fastify example](/how-to/backend/fastify-example) \ No newline at end of file diff --git a/docs/production/server.mdx b/docs/how-to/backend/server-setup.mdx similarity index 100% rename from docs/production/server.mdx rename to docs/how-to/backend/server-setup.mdx diff --git a/docs/audio-calls.mdx b/docs/how-to/features/audio-only-calls.mdx similarity index 64% rename from docs/audio-calls.mdx rename to docs/how-to/features/audio-only-calls.mdx index bdac4017..6fc83a72 100644 --- a/docs/audio-calls.mdx +++ b/docs/how-to/features/audio-only-calls.mdx @@ -1,23 +1,24 @@ --- -sidebar_position: 5 +type: how-to --- import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; -# Audio-only Calls +# How to Create Audio-only Calls + +**How-to Guide** - *Set up voice-only communication with cost savings* In many use cases, you only need real-time audio, without any video streaming. If your use case falls into this category, then you can benefit greatly from using `audio_only` rooms in Fishjam. - - - - - - - - +{/* TODO(Tomasz Mazur): uncomment this once pricing page is ready */} +{/* ## Why Should I Care? */} +{/* Audio-only rooms are heavily discounted compared to normal rooms. */} +{/* As described in more detail on the [pricing page](https://fishjam.io/#pricing), Fishjam rooms are priced based on the total connection time of peers in them. */} +{/* Audio-only rooms come at a 75% discount. */} +{/* For example, if you have a normal room with 2 peers connected for 30 minutes, then the total cost of the room will be equal to the cost of 60 minutes. */} +{/* If the same room were audio-only, then the final cost of the room will only be equal to 15 minutes. */} ## How Do I Use It? diff --git a/docs/livestreaming.mdx b/docs/how-to/features/livestreaming.mdx similarity index 99% rename from docs/livestreaming.mdx rename to docs/how-to/features/livestreaming.mdx index fa185873..fafcdfba 100644 --- a/docs/livestreaming.mdx +++ b/docs/how-to/features/livestreaming.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +type: how-to --- import Tabs from "@theme/Tabs"; diff --git a/docs/how-to/features/room-manager-testing.mdx b/docs/how-to/features/room-manager-testing.mdx new file mode 100644 index 00000000..443aef3b --- /dev/null +++ b/docs/how-to/features/room-manager-testing.mdx @@ -0,0 +1,272 @@ +--- +type: how-to +--- + +# How to Use Room Manager for Testing + +**How-to Guide** - *Use Room Manager to test your Fishjam integration without a backend* + +Room Manager is a development tool that lets you create rooms and peers for testing without setting up your own backend server. This guide shows you how to use it effectively. + +## Prerequisites + +- Access to [Fishjam Dashboard](https://fishjam.io/app) +- A Sandbox environment set up + +## Step 1: Get your Room Manager URL + +1. Log in to [Fishjam Dashboard](https://fishjam.io/app) +2. Navigate to your [Sandbox App](https://fishjam.io/app/sandbox) +3. Copy your **Room Manager URL** - it will look like: + ``` + https://fishjam.io/api/v1/connect/YOUR_APP_UUID/room-manager + ``` + +:::note +`YOUR_APP_UUID` is your unique sandbox identifier. Anyone who knows this ID can join your rooms, so keep it secure during development. +::: + +## Step 2: Create a room and get peer tokens + +### Using HTTP GET requests + +The Room Manager API uses simple GET requests. Add query parameters to create rooms and peers: + +``` +https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=foo&peerName=bar&roomType=full-feature +``` + +### Required parameters: +- `roomName` - Name of the room to create/join +- `peerName` - Name for the peer joining the room + +### Optional parameters: +- `roomType` - Type of room to create (defaults to `full-feature`) + +### Room types available: +- `full-feature` - For video/audio conferencing (default) +- `audio-only` - For audio-only conferencing +- `livestream` - For one-to-many video/audio streaming + +## Step 3: Handle the response + +The Room Manager returns a JSON response with connection details: + +```json +{ + "peerToken": "", + "url": "wss://fishjam.io/api/v1/connect/${YOUR_APP_UUID}", + "room": { + "id": "", + "name": "foo" + }, + "peer": { + "id": "", + "name": "bar" + } +} +``` + +## Step 4: Use the tokens in your client app + +### React Native example: +```tsx +import { useEffect, useState } from "react"; +import { FishjamRoom } from "@fishjam-cloud/react-native-client"; + +const roomName = "testRoom"; +const peerName = `user_${Date.now()}`; +const YOUR_APP_UUID = "your-app-uuid-here"; + +export default function TestScreen() { + const [roomData, setRoomData] = useState(null); + + useEffect(() => { + const fetchRoomData = async () => { + try { + const response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=${roomName}&peerName=${peerName}&roomType=full-feature` + ); + const data = await response.json(); + setRoomData(data); + } catch (error) { + console.error('Failed to create room:', error); + } + }; + + fetchRoomData(); + }, []); + + if (!roomData) { + return Creating room...; + } + + return ( + + ); +} +``` + +### React/Web example: +```tsx +import { useState, useEffect } from "react"; +import { FishjamProvider, useConnection } from "@fishjam-cloud/react-client"; + +const YOUR_APP_UUID = "your-app-uuid-here"; + +function VideoCallComponent() { + const { joinRoom } = useConnection(); + const [isConnected, setIsConnected] = useState(false); + + const handleJoinRoom = async () => { + const roomName = "testRoom"; + const peerName = `user_${Date.now()}`; + + try { + const response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=${roomName}&peerName=${peerName}` + ); + const { url, peerToken } = await response.json(); + + await joinRoom({ url, peerToken }); + setIsConnected(true); + } catch (error) { + console.error('Failed to join room:', error); + } + }; + + return ( +
+ {!isConnected && ( + + )} + {isConnected &&

Connected to room!

} +
+ ); +} + +export default function App() { + return ( + + + + ); +} +``` + +## Step 5: Test different room types + +### Testing audio-only rooms: +```typescript +const audioOnlyUrl = `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=audioTest&peerName=user1&roomType=audio-only`; +``` + +### Testing livestream rooms: +```typescript +// For the broadcaster +const broadcasterUrl = `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=liveStream&peerName=broadcaster&roomType=livestream`; + +// For viewers, you need a viewer token (different endpoint) +const viewerTokenUrl = `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager/liveStream/livestream-viewer-token`; +``` + +## Step 6: Handle multiple peers + +To test with multiple participants, create multiple peer tokens with different peer names: + +```typescript +// First peer +const peer1Response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=multiTest&peerName=alice` +); + +// Second peer +const peer2Response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=multiTest&peerName=bob` +); +``` + +Both peers will join the same room (`multiTest`) and can communicate with each other. + +## Common testing patterns + +### Pattern 1: Random room names for isolation +```typescript +const roomName = `test_${Math.random().toString(36).substring(7)}`; +const peerName = `user_${Date.now()}`; +``` + +### Pattern 2: Consistent naming for repeated tests +```typescript +const roomName = "development-room"; +const peerName = `developer_${userIndex}`; +``` + +### Pattern 3: Feature-specific room names +```typescript +const roomName = `screenshare-test-${Date.now()}`; +const roomName = `audio-only-test`; +const roomName = `livestream-demo`; +``` + +## Troubleshooting + +### Issue: Same peer name returns same token +**Problem**: Using the same `roomName` and `peerName` combination returns identical tokens. + +**Solution**: Use unique peer names for each test: +```typescript +const peerName = `test_${Date.now()}_${Math.random().toString(36).substring(7)}`; +``` + +### Issue: Room not found errors +**Problem**: Rooms might not persist between requests. + +**Solution**: Always create rooms fresh for each test session. + +### Issue: Connection failures +**Problem**: Invalid app UUID or network issues. + +**Solution**: +1. Verify your app UUID in the Fishjam Dashboard +2. Check network connectivity +3. Ensure you're using the sandbox environment + +## Security reminder + +:::danger +**Room Manager is not safe for production!** + +- No authentication required +- Anyone with your app UUID can join rooms +- Identical room/peer names get the same tokens +- No rate limiting or abuse protection + +Only use Room Manager for development and testing. +::: + +## Resetting your app + +If you need to reset your Room Manager: + +1. Go to [Fishjam Dashboard](https://fishjam.io/app/sandbox) +2. Click **Settings** +3. Click **Reset App** +4. Get your new app UUID + +This will invalidate all existing tokens and give you a fresh sandbox environment. + +## Next steps + +Once you've tested your integration with Room Manager: + +- [Set up your own backend](/tutorials/backend-quick-start) +- [Learn about Room Manager concepts](/explanation/room-manager-concept) +- [Understand security implications](/explanation/security-tokens) + +For production deployment: +- [How to set up production server](/how-to/backend/server-setup) +- [How to implement proper authentication](/explanation/security-tokens) \ No newline at end of file diff --git a/docs/react-native/_components/configure-permissions.mdx b/docs/how-to/react-native/_components/configure-permissions.mdx similarity index 100% rename from docs/react-native/_components/configure-permissions.mdx rename to docs/how-to/react-native/_components/configure-permissions.mdx diff --git a/docs/react-native/_components/install-package.mdx b/docs/how-to/react-native/_components/install-package.mdx similarity index 100% rename from docs/react-native/_components/install-package.mdx rename to docs/how-to/react-native/_components/install-package.mdx diff --git a/docs/react-native/assets/ios-new-folder.png b/docs/how-to/react-native/assets/ios-new-folder.png similarity index 100% rename from docs/react-native/assets/ios-new-folder.png rename to docs/how-to/react-native/assets/ios-new-folder.png diff --git a/docs/react-native/assets/ios-new-group.png b/docs/how-to/react-native/assets/ios-new-group.png similarity index 100% rename from docs/react-native/assets/ios-new-group.png rename to docs/how-to/react-native/assets/ios-new-group.png diff --git a/docs/react-native/assets/ios-new-target.png b/docs/how-to/react-native/assets/ios-new-target.png similarity index 100% rename from docs/react-native/assets/ios-new-target.png rename to docs/how-to/react-native/assets/ios-new-target.png diff --git a/docs/react-native/background.mdx b/docs/how-to/react-native/background-streaming.mdx similarity index 100% rename from docs/react-native/background.mdx rename to docs/how-to/react-native/background-streaming.mdx diff --git a/docs/react-native/connecting.mdx b/docs/how-to/react-native/connecting.mdx similarity index 100% rename from docs/react-native/connecting.mdx rename to docs/how-to/react-native/connecting.mdx diff --git a/docs/react-native/custom-video-sources/index.mdx b/docs/how-to/react-native/custom-video-sources/index.mdx similarity index 100% rename from docs/react-native/custom-video-sources/index.mdx rename to docs/how-to/react-native/custom-video-sources/index.mdx diff --git a/docs/react-native/custom-video-sources/overview.mdx b/docs/how-to/react-native/custom-video-sources/overview.mdx similarity index 100% rename from docs/react-native/custom-video-sources/overview.mdx rename to docs/how-to/react-native/custom-video-sources/overview.mdx diff --git a/docs/react-native/custom-video-sources/vision-camera.mdx b/docs/how-to/react-native/custom-video-sources/vision-camera.mdx similarity index 100% rename from docs/react-native/custom-video-sources/vision-camera.mdx rename to docs/how-to/react-native/custom-video-sources/vision-camera.mdx diff --git a/docs/react-native/installation.mdx b/docs/how-to/react-native/installation.mdx similarity index 100% rename from docs/react-native/installation.mdx rename to docs/how-to/react-native/installation.mdx diff --git a/docs/react-native/list-other.mdx b/docs/how-to/react-native/list-other-peers.mdx similarity index 100% rename from docs/react-native/list-other.mdx rename to docs/how-to/react-native/list-other-peers.mdx diff --git a/docs/react-native/livestreaming.mdx b/docs/how-to/react-native/livestreaming.mdx similarity index 100% rename from docs/react-native/livestreaming.mdx rename to docs/how-to/react-native/livestreaming.mdx diff --git a/docs/react-native/metadata.mdx b/docs/how-to/react-native/metadata-and-broadcasting.mdx similarity index 100% rename from docs/react-native/metadata.mdx rename to docs/how-to/react-native/metadata-and-broadcasting.mdx diff --git a/docs/react-native/reconnect.mdx b/docs/how-to/react-native/reconnection-handling.mdx similarity index 100% rename from docs/react-native/reconnect.mdx rename to docs/how-to/react-native/reconnection-handling.mdx diff --git a/docs/react-native/screensharing.mdx b/docs/how-to/react-native/screensharing.mdx similarity index 100% rename from docs/react-native/screensharing.mdx rename to docs/how-to/react-native/screensharing.mdx diff --git a/docs/react-native/start-streaming.mdx b/docs/how-to/react-native/start-streaming.mdx similarity index 100% rename from docs/react-native/start-streaming.mdx rename to docs/how-to/react-native/start-streaming.mdx diff --git a/docs/how-to/react/_common/metadata/header.mdx b/docs/how-to/react/_common/metadata/header.mdx new file mode 100644 index 00000000..7f38d1de --- /dev/null +++ b/docs/how-to/react/_common/metadata/header.mdx @@ -0,0 +1,10 @@ +Alongside audio and video, it is possible to send additional metadata with each peer. Metadata is just +JSON that can contain arbitrary information. Its most common use is sending a user name associated with a peer. +However, it can be also used to send the peer's camera type, application information etc. + +:::info + +You can also set metadata on [the server side, when adding user to the room](/production/server#metadata). This metadata is persistent throughout its lifetime and is useful for attaching information that +can't be overwritten by the peer, like information about real user names or basic permission info. + +::: diff --git a/docs/how-to/react/_common/metadata/joining_room.mdx b/docs/how-to/react/_common/metadata/joining_room.mdx new file mode 100644 index 00000000..517a5b30 --- /dev/null +++ b/docs/how-to/react/_common/metadata/joining_room.mdx @@ -0,0 +1,5 @@ +## Setting metadata when joining the room + +The `joinRoom` method from the `useConnection` hook has a `peerMetadata` parameter, that can be used for setting object metadata. + +{props.children} diff --git a/docs/how-to/react/_common/metadata/reading.mdx b/docs/how-to/react/_common/metadata/reading.mdx new file mode 100644 index 00000000..fc1eb216 --- /dev/null +++ b/docs/how-to/react/_common/metadata/reading.mdx @@ -0,0 +1,9 @@ +## Reading metadata + +Peer metadata is available as the `metadata` property for each peer. Therefore, when you list your peers with the `usePeers` hook, you can read +the metadata associated with them. +Note that the `metadata.peer` property contains only the metadata set by the client SDK (as in the examples examples above). +The metadata set on the server side is available as `metadata.server`. +Learn more about server metadata [here](/production/server#metadata). + +{props.children} diff --git a/docs/how-to/react/_common/metadata/updating.mdx b/docs/how-to/react/_common/metadata/updating.mdx new file mode 100644 index 00000000..1a56a0f6 --- /dev/null +++ b/docs/how-to/react/_common/metadata/updating.mdx @@ -0,0 +1,5 @@ +## Updating metadata during connection + +Once you've joined the room, you can update your peer metadata with `updatePeerMetadata` from `useUpdatePeerMetadata`: + +{props.children} diff --git a/docs/react/connecting.mdx b/docs/how-to/react/connecting.mdx similarity index 100% rename from docs/react/connecting.mdx rename to docs/how-to/react/connecting.mdx diff --git a/docs/react/custom-sources.mdx b/docs/how-to/react/custom-sources.mdx similarity index 100% rename from docs/react/custom-sources.mdx rename to docs/how-to/react/custom-sources.mdx diff --git a/docs/react/installation.mdx b/docs/how-to/react/installation.mdx similarity index 100% rename from docs/react/installation.mdx rename to docs/how-to/react/installation.mdx diff --git a/docs/react/list-other.mdx b/docs/how-to/react/list-other-peers.mdx similarity index 100% rename from docs/react/list-other.mdx rename to docs/how-to/react/list-other-peers.mdx diff --git a/docs/react/livestreaming.mdx b/docs/how-to/react/livestreaming.mdx similarity index 100% rename from docs/react/livestreaming.mdx rename to docs/how-to/react/livestreaming.mdx diff --git a/docs/react/managing-devices.mdx b/docs/how-to/react/managing-devices.mdx similarity index 100% rename from docs/react/managing-devices.mdx rename to docs/how-to/react/managing-devices.mdx diff --git a/docs/react/metadata.mdx b/docs/how-to/react/metadata.mdx similarity index 100% rename from docs/react/metadata.mdx rename to docs/how-to/react/metadata.mdx diff --git a/docs/react/start-streaming.mdx b/docs/how-to/react/start-streaming.mdx similarity index 100% rename from docs/react/start-streaming.mdx rename to docs/how-to/react/start-streaming.mdx diff --git a/docs/react/stream-middleware.mdx b/docs/how-to/react/stream-middleware.mdx similarity index 100% rename from docs/react/stream-middleware.mdx rename to docs/how-to/react/stream-middleware.mdx diff --git a/docs/troubleshooting.mdx b/docs/how-to/troubleshooting/video-codecs.mdx similarity index 89% rename from docs/troubleshooting.mdx rename to docs/how-to/troubleshooting/video-codecs.mdx index 9ea8ead3..7b6f43e1 100644 --- a/docs/troubleshooting.mdx +++ b/docs/how-to/troubleshooting/video-codecs.mdx @@ -1,8 +1,10 @@ --- -sidebar_position: 9 +type: how-to --- -# Troubleshooting +# How to Handle Video Codec Issues + +**How-to Guide** - *Solve video codec problems and optimize codec selection* ## Supported Video Codecs diff --git a/docs/index.mdx b/docs/index.mdx index 6d372fea..dd5dcf50 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -5,9 +5,136 @@ sidebar_position: 0 import QuickNavigation from "@site/src/components/QuickNavigation"; import { items } from "@site/src/content/cardItems"; -# Welcome to Fishjam! +# Welcome to Fishjam -Here you will find everything you need to start building your multimedia streaming applications using our service. -Start from the beginning, get right away to setup or get to know our glossary. +Welcome to the Fishjam documentation! Build real-time video and audio streaming applications with confidence using our organized, developer-friendly guides. - +## New to Fishjam? Start here 🚀 + +If you're just getting started, follow our **tutorials** to build your first application: + + + item.title.toLowerCase().includes("tutorial") || + item.title.toLowerCase().includes("start"), + )} +/> + +### Quick Start Paths + +**📱 Mobile Developer?** → [React Native Tutorial](/tutorials/react-native-quick-start) +**🌐 Web Developer?** → [React Tutorial](/tutorials/react-quick-start) +**⚙️ Backend Developer?** → [Backend Tutorial](/tutorials/backend-quick-start) + +## How This Documentation is Organized + +Our documentation follows the [Diátaxis framework](https://diataxis.fr/) to help you find exactly what you need: + +### 📚 **Tutorials** - _Learn by building_ + +Step-by-step guides that teach you the fundamentals by building working applications. + +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [React Quick Start](/tutorials/react-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) + +### 🛠️ **How-to Guides** - _Solve specific problems_ + +Goal-oriented guides that show you how to solve real problems and implement features. + +- **React Native**: [Installation](/how-to/react-native/installation), [Screen Sharing](/how-to/react-native/screensharing), [Background Streaming](/how-to/react-native/background-streaming) +- **React/Web**: [Managing Devices](/how-to/react/managing-devices), [Livestreaming](/how-to/react/livestreaming), [Custom Sources](/how-to/react/custom-sources) +- **Features**: [Audio-only Calls](/how-to/features/audio-only-calls), [Room Manager Testing](/how-to/features/room-manager-testing) +- **Backend**: [Production Deployment](/how-to/backend/production-deployment), [Server Setup](/how-to/backend/server-setup) + +### 📖 **Reference** - _Look up specific information_ + +Technical reference for APIs, parameters, and detailed specifications. + +- [React Native SDK API](/api/mobile) +- [React/Web SDK API](/api/web) +- [Server SDK API](/api/server) +- [Glossary](/reference/glossary) + +### 💡 **Explanation** - _Understand the concepts_ + +Background information that explains how Fishjam works and why it's designed this way. + +- [What is Fishjam?](/explanation/what-is-fishjam) +- [Architecture](/explanation/architecture) +- [Core Concepts](/explanation/core-concepts) +- [Room Types](/explanation/room-types) +- [Security & Tokens](/explanation/security-tokens) + +## Try Fishjam Right Now + +Want to see Fishjam in action immediately? + +- **Live Demo**: Try our [Videoroom app](https://room.fishjam.io/) +- **Example Apps**: Check out [Fishjam Chat examples](https://github.com/fishjam-cloud/mobile-client-sdk/tree/main/examples/fishjam-chat) + +## Get Your Development Environment Ready + +1. **Create account**: [Sign up for Fishjam](https://fishjam.io/app) +2. **Get Sandbox access**: Automatic Sandbox instance with Room Manager +3. **Copy Room Manager URL**: From your developer panel +4. **Pick your platform**: Choose React Native, React, or backend first + +## Common First Questions + +### "Which SDK should I use?" + +- **Building mobile apps?** → React Native SDK +- **Building web apps?** → React/Web SDK +- **Building backends?** → Node.js or Python Server SDK + +### "Do I need my own backend?" + +- **For testing**: No! Use [Room Manager](/how-to/features/room-manager-testing) +- **For production**: Yes, see [Backend Tutorial](/tutorials/backend-quick-start) + +### "What room type do I need?" + +- **Video calls/meetings**: `full-feature` rooms +- **Voice-only calls**: `audio-only` rooms (75% cheaper!) +- **Livestreaming/webinars**: `livestream` rooms + +Learn more in [Room Types Explained](/explanation/room-types). + +### "Is Fishjam secure?" + +Yes! Fishjam uses a secure token-based system. Learn about [Security & Tokens](/explanation/security-tokens). + +## Development vs Production + +### 🧪 **Development Phase** + +- Use [Room Manager](/how-to/features/room-manager-testing) for quick testing +- No backend setup required initially +- Focus on client-side features first + +### 🚀 **Production Phase** + +- Set up your own backend with [Server SDKs](/tutorials/backend-quick-start) +- Implement proper authentication +- Follow [production deployment guide](/how-to/backend/production-deployment) + +## Need Help? + +- **Can't find what you're looking for?** Use the search bar above +- **Want to contribute?** Check our GitHub repositories +- **Need support?** Contact us through the developer panel + +## What's New in This Documentation + +We've restructured our docs to make them more developer-friendly: + +- ✨ **Clear learning paths**: Tutorials get you building quickly +- 🎯 **Problem-focused guides**: Find solutions to specific challenges +- 📚 **Conceptual explanations**: Understand how and why Fishjam works +- 🔍 **Easy reference**: Quick lookup for APIs and specifications + +--- + +**Ready to build?** Start with a [tutorial](/tutorials/react-native-quick-start) or explore [what Fishjam can do](/explanation/what-is-fishjam). diff --git a/docs/introduction.mdx b/docs/introduction.mdx deleted file mode 100644 index fc1562fb..00000000 --- a/docs/introduction.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -sidebar_position: 0 ---- - -import QuickNavigation from "@site/src/components/QuickNavigation"; -import { items } from "@site/src/content/cardItems"; - -# Introduction - -Welcome to the Fishjam documentation! -Here you will find everything you need to start building your multimedia streaming applications using Fishjam. - -## What is Fishjam? - -Fishjam is a multimedia streaming toolkit that allows you to build real-time video and audio streaming applications using [WebRTC](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API). -We provide the infrastructure, media server, and client SDKs so you can focus on building your apps. - -**No WebRTC knowledge is required!** - -## How can I try it out? - -1. To get started with Fishjam, you need to create an account on our [developer panel](https://fishjam.io/app). -2. Once you have an account, Fishjam will assign you a Sandbox instance automatically. Sandbox instances come with [**Room Manager**](/room-manager.md) - a simple backend for creating test rooms. Copy the Room Manager URL from the developer panel. -3. Pick a client SDK that you want to use and follow the Quick Start guide. We provide SDKs for [React Native](/react-native/quick-setup.mdx) and [React](/react/installation.mdx). - - item.title.toLowerCase().includes("setup"))} -/> - -## Do you have any running examples? - -We are maintaining a simple video conferencing app called [Videoroom](https://room.fishjam.io/). -It is a publicly accessible app where you can see Fishjam in action. - -You can access it at [room.fishjam.io](https://room.fishjam.io/) - just pick a room name and peer name, and you can start a video call between any two devices. - -## Are there any examples I can run locally? - -Yes! You can find examples in our GitHub repositories that you can run locally. Examples are usually available under the `examples` directory in the relevant repository. - -The easiest starting point for both web and mobile is Fishjam Chat. It is a simple chat application that uses Fishjam for video and audio streaming. You can find the code here: - -- [Fishjam Chat React Native](https://github.com/fishjam-cloud/mobile-client-sdk/tree/main/examples/fishjam-chat) -- [Fishjam Chat React](https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client/fishjam-chat) - -## What does Fishjam consist of? - -Fishjam consists of several components that work together to provide a seamless multimedia streaming experience. -Below is a list of components that you will need to get started: - -| Component | Description | Link | -| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -| Developer panel | Developer panel for setting up your own Fishjam Media Server. | [fishjam.io/app](https://fishjam.io/app) | -| Fishjam Media Server | A media server that will route your multimedia traffic. We host and manage it for you. You can control it via the developer panel. | — | -| Fishjam Client SDKs | Toolkit used for multimedia integration on endpoint devices. | [React Native](/react-native/quick-setup.mdx), [React](/react/installation.mdx) | -| Fishjam Server SDKs | Toolkit for integrating your backend with Fishjam. We support Python and NodeJS as well as REST API. | [Python, NodeJS, and REST](/production/server.mdx) | -| Room Manager | Simple backend for creating test rooms. You no longer need to bring your own backend to develop frontend apps. | [Repository](https://github.com/fishjam-cloud/js-server-sdk/tree/main/examples/room-manager) | - -## How does it work? - -Streaming with Fishjam is simple. You create a room, add peers to it, and start streaming. Below is a high-level overview of how Fishjam works. - -![Fishjam Data Flow](@site/static/img/architecture.svg) diff --git a/docs/production/_category_.json b/docs/production/_category_.json deleted file mode 100644 index aae1c275..00000000 --- a/docs/production/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Going to production", - "position": 7, - "link": { - "type": "generated-index" - } -} diff --git a/docs/production/examples/_category_.json b/docs/production/examples/_category_.json deleted file mode 100644 index 37ad9f38..00000000 --- a/docs/production/examples/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Examples", - "position": 2, - "link": { - "type": "generated-index" - } -} diff --git a/docs/react-native/_category_.json b/docs/react-native/_category_.json deleted file mode 100644 index a33ed1fd..00000000 --- a/docs/react-native/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "React Native Integration", - "position": 3, - "link": { - "type": "generated-index", - "description": "How to integrate Fishjam into your React Native mobile app." - } -} diff --git a/docs/react-native/quick-setup.mdx b/docs/react-native/quick-setup.mdx deleted file mode 100644 index 60183f6f..00000000 --- a/docs/react-native/quick-setup.mdx +++ /dev/null @@ -1,193 +0,0 @@ ---- -sidebar_position: 0 ---- - -import InstallPackage from "./_components/install-package.mdx"; -import ConfigurePermissions from "./_components/configure-permissions.mdx"; - -# Quick Setup - -This article is a fast track to integrate Fishjam into your React Native application. -It contains all the required steps to start streaming video with Fishjam. -You can also [see a minimal example](#minimal-example) at the end of the article. - -## Prerequisites - -In this part, let's focus on everything you need to prepare to use Fishjam in your project. - -### 1. Install the package - - - -### 2. Build native dependencies - -```bash -npx expo prebuild -``` - -### 3. Configure required app permissions - - - -### 4. Get Room Manager URL - -Log in to [Fishjam Dashboard](https://fishjam.io/app) and get your [Room Manager](/room-manager) URL. - -## Step-by-step instructions - -Now you are good to jump right into your IDE and integrate Fishjam into your app. -In a few simple steps, you will be able to implement a simple video call functionality. - -### 1. Fetch peer token - -Use your Room Manager URL to fetch a peer token to get a new room: - -```ts -const response = await fetch( - `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager/?roomName=${roomName}&peerName=${peerName}`, -); - -const { url, peerToken } = await response.json(); -``` - -### 2. Join Room and start streaming - -:::danger - -If you want to use the camera, you must first request permission. Check -[permission guide](/react-native/installation#step-2-configure-app-permissions) for more information. - -::: - -:::important - -Keep in mind that this won't work on the iOS Simulator, as the Simulator can't access the camera. - -::: - -To start streaming, you have to prepare your camera and join the room: - -```tsx -import { useCallback } from "react"; -import { Button } from "react-native"; -import { useCamera, useConnection } from "@fishjam-cloud/react-native-client"; - -export function StartStreamingButton({ - roomName, - peerName, -}: { - roomName: string; - peerName: string; -}) { - // highlight-next-line - const { prepareCamera } = useCamera(); - // highlight-next-line - const { joinRoom } = useConnection(); - - const startStreaming = useCallback(async () => { - const response = await fetch( - `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager/?roomName=${roomName}&peerName=${peerName}`, - ); - const { url, peerToken } = await response.json(); - - // highlight-next-line - await prepareCamera({ cameraEnabled: true }); - - // highlight-next-line - await joinRoom({ url, peerToken }); - }, [joinRoom, prepareCamera, roomName, peerName]); - - return ; +} +``` + +## Step 3: Display your video + +Show your own video stream: + +```tsx +import { useCamera } from "@fishjam-cloud/react-client"; + +export function MyVideo() { + const { stream } = useCamera(); + + return ( +