Skip to content

Instantly share code, notes, and snippets.

@nileshtrivedi
Created June 13, 2025 06:29
Show Gist options
  • Save nileshtrivedi/367d640f5ae9f6c75bd502e4605b0596 to your computer and use it in GitHub Desktop.
Save nileshtrivedi/367d640f5ae9f6c75bd502e4605b0596 to your computer and use it in GitHub Desktop.
tamnoon single-file demo
# Run this as `elixir app.exs`
Mix.install([
{:tamnoon, "~> 0.1.0"}
])
defmodule TamnoonSample do
end
defmodule TamnoonSample.Router do
use Plug.Router
plug :match
plug :dispatch
get "/" do
homepage_html = """
<!DOCTYPE html>
<html lang="en" data-theme="cupcake">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tamnoon Sample App</title>
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
</head>
<body>
<script>
const wsUrl = "ws://localhost:4000/ws/";
const socket = new WebSocket(wsUrl);
socket.onopen = function(event) {
socket.send(JSON.stringify({method: "get", key: "val"}));
document.getElementById("inc").onclick = () => socket.send(JSON.stringify({
"method": "pub",
"channel": "clients",
"action": {
"method": "nudge",
"key": "val",
"direction": "up"
}
}))
document.getElementById("dec").onclick = () => socket.send(JSON.stringify({
"method": "pub",
"channel": "clients",
"action": {
"method": "nudge",
"key": "val",
"direction": "down"
}
}))
};
socket.onmessage = function(event) {
const field = JSON.parse(event.data);
if ("pub" in field) return;
if ("val" in field) {
document.getElementById("val").innerText = field.val;
}
};
socket.onclose = function(event) {
console.log("WebSocket is closed now.");
};
socket.onerror = function(error) {
console.log("WebSocket error:", error);
};
</script>
<div class="hero bg-base-200 min-h-screen">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 id="val" class="text-5xl font-bold mb-4">0</h1>
<button class="btn btn-primary px-8 mr-4" id="inc">+</button>
<button class="btn btn-primary px-8" id="dec">-</button>
</div>
</div>
</div>
</body>
</html>
"""
send_resp(conn, 200, homepage_html)
end
match _ do
send_resp(conn, 404, "404")
end
end
defmodule TamnoonSample.Methods do
use Tamnoon.Methods
defmethod :nudge do
key = Tamnoon.Methods.get_key(req, state)
val = Map.get(state, key)
new_val = if (req["direction"] == "up"), do: val + 1, else: val - 1
new_state = Map.put(state, key, new_val)
{%{key => new_val}, new_state}
end
end
defmodule TamnoonSample.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
@impl true
def start(_type, _args) do
children = [
{Tamnoon, [[initial_state: %{val: 0}, router: TamnoonSample.Router, methods_module: TamnoonSample.Methods]]}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: TamnoonSample.Supervisor]
Supervisor.start_link(children, opts)
end
end
Application.ensure_all_started(:logger)
{:ok, _pid} = TamnoonSample.Application.start(:normal, [])
# This will block the main process and keep the script running
Process.sleep(:infinity)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment