Skip to content

Livestreaming App

image.png

  • HTTP Spec
    • Signup

      • POST /api/v1/signup
      • Body
      {
      "email": "user@example.com",
      "password": "string", // should be hashed on server-side
      "username": "john_doe"
      }

      Response

      • Status Code 201
      {
      "message": "User created successfully",
      "userId": "abc123",
      "email": "user@example.com"
      }
      • Status Code 400 - Invalid Input (e.g., missing fields, invalid email format)
      • Status Code 409 - Conflict (e.g., email already taken)
    • Signin

      • POST /api/v1/signin
      • Body
      {
      "email": "user@example.com",
      "password": "string"
      }

      Response

      • Status Code 200
      {
      "token": "jwt_token_here",
      "userId": "abc123"
      }
      • Status Code 401 - Unauthorized (invalid credentials)
      • Status Code 400 - Bad Request (missing fields)
    • Create a new live session (auth)

      • POST /api/v1/session
      • Body
      {
      "title": "Full Stack cohort class #1"
      }

      Response

      • Status Code 200
      {
      "sessionId": "lsk-qlw-dka" // needs to follow this format (a-z characters in three sets separated by -
      }
      • Status Code 401 - Unauthorized
      • Status Code 500 - Server error
    • Get all live sessions (auth)

      • GET /api/v1/sessions
      • Response
      • Status Code 200
      [
      {
      "sessionId": "lsk-qlw-dka",
      "title": "Full Stack cohort class #1",
      "startTime": "2024-12-01T12:00:00Z",
      "status": "active"
      },
      {
      "sessionId": "abc-xyz-123",
      "title": "Backend Masterclass",
      "status": "inactive"
      }
      ]
      • Status Code 401 - Unauthorized
    • Start a live session (auth)

      • POST /api/v1/session/:sessionId/start
      • Response
      • Status Code 200
      {
      "message": "Session started successfully"
      }
      • Status Code 404 - Not Found (session doesn’t exist)
      • Status Code 400 - Bad Request (already started)
      • Status Code 401 - Unauthorized
    • End a live session (auth)

      • POST /api/v1/session/:sessionId/end
      • Response
      • Status Code 200
      {
      "message": "Session ended successfully"
      }
      • Status Code 404 - Not Found (session doesn’t exist)
      • Status Code 400 - Bad Request (session not started)
    • Add a PDF to the list of slides (auth)

      The PDF needs to be decomposed to images, images need to be sent to an object store, then all slides need to be added one after the other

      • POST /api/v1/session/:sessionId/slides/pdf
      • Body
      • Form data with the file key “file” (PDF)

      Response

      • Status Code 200
      {
      "message": "PDF added successfully",
      // should return a complete list of slides and how they look right now, not just the currently added slides
      "slides": [{
      type: "image",
      payload: {
      imageUrl: "https://google.com/image.png"
      }
      }, {
      type: "image",
      payload: {
      imageUrl: "https://google.com/image2.png"
      }
      }]
      }
      • Status Code 400 - Invalid file type (only PDF allowed)
      • Status Code 500 - Server error
    • Add an image to the list of slides (auth)

      • POST /api/v1/session/:sessionId/slides/image
      • Body
      • Form data with the file key “file” (jpeg/png)

      Response

      • Status Code 200
      {
      "message": "Image added successfully",
      "slides": [{
      type: "image",
      payload: {
      imageUrl: "https://google.com/image.png"
      }
      }, {
      type: "image",
      payload: {
      imageUrl: "https://google.com/image2.png"
      }
      }] // should return a complete list of slides
      }
      • Status Code 400 - Invalid file type (only Image allowed)
      • Status Code 500 - Server error
    • Add a new empty slide (auth)

      • POST /api/v1/session/:sessionId/slides
      • Response
      • Status Code 200
      {
      "message": "Empty slide added successfully",
      "slides": [{
      type: "image",
      payload: {
      imageUrl: "https://google.com/image.png"
      }
      }, {
      type: "image",
      payload: {
      imageUrl: "https://google.com/image2.png"
      }
      }, {
      type: "slide",
      }] // should return a complete list of slides
      }
      • Status Code 404 - Not Found (session doesn’t exist)
      • Status Code 400 - Invalid session state
    • Delete a slide (auth)

      • DELETE /api/v1/session/:sessionId/slide/:slideId
      • Response
      • Status Code 200
      {
      "message": "Slide deleted successfully"
      }
      • Status Code 404 - Not Found (session or slide doesn’t exist)
    • Get the current state of the room (auth)

      When the user visits the livestream for the first time, they will see this

      {
      "slides": [
      {id: "slide123", type: "image", url: "http://google.com/image.png"},
      {id: "slide123", type: "image", url: "http://google.com/image.png"},
      {id: "slide123", type: "image", url: "http://google.com/image.png"},
      {id: "slide123", type: "image", url: "http://google.com/image.png"},
      {id: "slide123", type: "image", url: "http://google.com/image.png"}
      ],
      "strokes": [{
      "x": 100,
      "y": 150,
      "color": "#ff0000",
      "size": 2
      }, {
      "x": 150,
      "y": 180,
      "color": "#ff0000",
      "size": 2
      }]
      }

WebSocket Spec

Sending Side

  • Add a Stroke to the Current Slide (Auth, Admin Only)

    {
    "sessionId": "lsk-qlw-dka",
    "type": "STROKE",
    "payload": {
    "x": 100,
    "y": 150,
    "color": "#ff0000",
    "size": 2
    }
    }
  • Clear the Current Slide (Remove All Strokes, Auth, Admin Only)

    {
    "sessionId": "lsk-qlw-dka",
    "type": "CLEAR_SLIDE"
    }
  • Chat Messages (Admin and Users)

    {
    "sessionId": "lsk-qlw-dka",
    "type": "CHAT_MESSAGE",
    "payload": {
    "message": "Hi there"
    }
    }
  • Join a Room as Admin

    {
    "type": "SUBSCRIBE_ADMIN",
    "payload": {
    "roomId": "123123"
    }
    }
  • Join a Room as User

    {
    "type": "SUBSCRIBE",
    "payload": {
    "roomId": "123123"
    }
    }
  • Disable/Enable Chat (Auth, Admin)

    {
    "type": "CHAT_ENABLE",
    "payload": {
    "enabled": true | false
    }
    }

Receiving Side

  • Slide/Contents Changed

    {
    "type": "SLIDE_CHANGED",
    "payload": {
    "type": "image" | "slide",
    "url": "https://google.com/a.png"
    }
    }
  • Chat Received

    {
    "type": "CHAT_MESSAGE",
    "payload": {
    "message": "hi there",
    "username": "kirat",
    "image": "https://avatars.website.com/kirat.png"
    }
    }
  • Stroke Event Received

    {
    "sessionId": "lsk-qlw-dka",
    "type": "STROKE",
    "payload": {
    "x": 100,
    "y": 150,
    "color": "#ff0000",
    "size": 2
    }
    }
  • Clear Slide Event Received

    {
    "sessionId": "lsk-qlw-dka",
    "type": "CLEAR_SLIDE"
    }

Authentication

HTTP

Authentication should happen via an authorization header:

"authorization": "Bearer jwt_token"

WebSocket

The URL to connect should include the token as a query parameter:

ws://localhost:3001?token=jwt_token