Skip to content
No description, website, or topics provided.
JavaScript Elixir Other
Branch: master
Clone or download

Latest commit

chrismccord Merge pull request #48 from whatyouhide/updates
Update Elixir to ~> 1.6 and update dependencies
Latest commit 7fb1d3d Feb 20, 2018


Type Name Latest commit message Commit time
Failed to load latest commit information.
lib cleanup Dec 1, 2016
priv/static Update Elixir to ~> 1.6 and update dependencies Feb 20, 2018
test Upgrade to 0.10 Mar 11, 2015
web cleanup Dec 1, 2016
.gitignore Upgrade to 0.10 Mar 11, 2015
Procfile Add Procfile Mar 11, 2015 Update Elixir to ~> 1.6 and update dependencies Feb 20, 2018
brunch-config.js chore(mix.exs): update to Phoenix 1.1.4 Feb 10, 2016
elixir_buildpack.config Add buildpack back Mar 11, 2015
mix.exs Update Elixir to ~> 1.6 and update dependencies Feb 20, 2018
package.json Update Elixir to ~> 1.6 and update dependencies Feb 20, 2018

Simple Chat Example

Built with the Phoenix Framework

To start your new Phoenix application you have to:

  1. Clone this repo, then cd to the new directory
  2. Install dependencies with mix deps.get
  3. (optional) Install npm dependencies to customize the ES6 js/Sass npm install
  4. Start Phoenix router with mix phx.server

Now you can visit localhost:4000 from your browser.

Live Demo

Example Code


import {Socket, LongPoller} from "phoenix"

class App {

  static init(){
    let socket = new Socket("/socket", {
      logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) })

    socket.connect({user_id: "123"})
    var $status    = $("#status")
    var $messages  = $("#messages")
    var $input     = $("#message-input")
    var $username  = $("#username")

    socket.onOpen( ev => console.log("OPEN", ev) )
    socket.onError( ev => console.log("ERROR", ev) )
    socket.onClose( e => console.log("CLOSE", e))

    var chan ="rooms:lobby", {})
    chan.join().receive("ignore", () => console.log("auth error"))
               .receive("ok", () => console.log("join ok"))
               .after(10000, () => console.log("Connection interruption"))
    chan.onError(e => console.log("something went wrong", e))
    chan.onClose(e => console.log("channel closed", e))

    $"keypress").on("keypress", e => {
      if (e.keyCode == 13) {
        chan.push("new:msg", {user: $username.val(), body: $input.val()})

    chan.on("new:msg", msg => {
      scrollTo(0, document.body.scrollHeight)

    chan.on("user:entered", msg => {
      var username = this.sanitize(msg.user || "anonymous")
      $messages.append(`<br/><i>[${username} entered]</i>`)

  static sanitize(html){ return $("<div/>").text(html).html() }

  static messageTemplate(msg){
    let username = this.sanitize(msg.user || "anonymous")
    let body     = this.sanitize(msg.body)

    return(`<p><a href='#'>[${username}]</a>&nbsp; ${body}</p>`)


$( () => App.init() )

export default App


# lib/chat/endpoint.ex
defmodule Chat.Endpoint do
  use Phoenix.Endpoint

  socket "/socket", Chat.UserSocket


# web/channels/user_socket.ex
defmodule Chat.UserSocket do
  use Phoenix.Socket

  channel "rooms:*", Chat.RoomChannel

  transport :websocket, Phoenix.Transports.WebSocket
  transport :longpoll, Phoenix.Transports.LongPoll


defmodule Chat.RoomChannel do
  use Phoenix.Channel
  require Logger

  def join("rooms:lobby", message, socket) do
    Process.flag(:trap_exit, true)
    :timer.send_interval(5000, :ping)
    send(self, {:after_join, message})

    {:ok, socket}

  def join("rooms:" <> _private_subtopic, _message, _socket) do
    {:error, %{reason: "unauthorized"}}

  def handle_info({:after_join, msg}, socket) do
    broadcast! socket, "user:entered", %{user: msg["user"]}
    push socket, "join", %{status: "connected"}
    {:noreply, socket}
  def handle_info(:ping, socket) do
    push socket, "new:msg", %{user: "SYSTEM", body: "ping"}
    {:noreply, socket}

  def terminate(reason, _socket) do
    Logger.debug"> leave #{inspect reason}"

  def handle_in("new:msg", msg, socket) do
    broadcast! socket, "new:msg", %{user: msg["user"], body: msg["body"]}
    {:reply, {:ok, %{msg: msg["body"]}}, assign(socket, :user, msg["user"])}
You can’t perform that action at this time.