pipey 0.2.1

A lightweight HTTP-to-WebSocket event delivery service.
Documentation
{% extends "base.html" %}
{% block title %}Pipey | Docs{% endblock %}

{% block styles %}
<style>
.docs-content h2{
    font-size:19px;
    font-weight:700;
    margin-bottom:12px;
    display:flex;
    align-items:center;
    gap:10px;
}
.docs-content h2 .icon{
    width:30px; height:30px;
    border-radius:9px;
    background:var(--accent-soft);
    color:var(--accent);
    display:flex; align-items:center; justify-content:center;
    font-size:13px;
}
.docs-content h3{ font-size:12.5px; margin:18px 0 8px; color:var(--muted-2); text-transform:uppercase; letter-spacing:.05em; font-weight:700; }
.docs-content p{ color:var(--muted); }

.method-tag{
    display:inline-block;
    font-family:var(--font-mono);
    font-size:11px;
    font-weight:700;
    padding:4px 10px;
    border-radius:999px;
    margin-right:8px;
}
.method-get{ background:var(--live-soft); color:var(--live); }
.method-post{ background:var(--accent-soft); color:var(--accent-dark); }

.status-row{
    display:flex;
    align-items:center;
    gap:10px;
    margin:18px 0 8px;
}
.status-dot{ width:8px; height:8px; border-radius:50%; }
.status-ok{ background:var(--live); }
.status-warn{ background:var(--warn); }
.status-err{ background:var(--error); }

.steps{ list-style:none; counter-reset:step; }
.steps li{
    counter-increment:step;
    position:relative;
    padding-left:36px;
    margin-bottom:14px;
    color:var(--muted);
}
.steps li::before{
    content:counter(step);
    position:absolute;
    left:0;
    width:24px; height:24px;
    border-radius:50%;
    background:var(--accent-soft);
    color:var(--accent-dark);
    display:flex; align-items:center; justify-content:center;
    font-family:var(--font-mono);
    font-size:11px;
    font-weight:700;
}
</style>
{% endblock %}

{% block content %}

<div style="margin-bottom:28px;">
    <div class="eyebrow">Reference</div>
    <h1 style="font-size:32px; font-weight:700;">Documentation</h1>
    <p style="color:var(--muted);max-width:60ch;">
        Pipey is a lightweight HTTP → WebSocket event delivery service.
    </p>
</div>

<div class="docs-content">

<div class="card" id="connect">
<h2><span class="icon"><i class="fa-solid fa-plug"></i></span>Open a WebSocket</h2>
<p>Connect a client using its <code>user_id</code>.</p>
<div style="margin-top:6px;"><span class="method-tag method-get">GET</span><code>/api/v1/ws/pipey?user_id=&lt;uuid&gt;</code></div>

<h3>Example</h3>
<pre><code id="ws-example"></code></pre>
</div>

<div class="card" id="publish">
<h2><span class="icon"><i class="fa-solid fa-paper-plane"></i></span>Publish an event</h2>
<p>Send an event to a connected user.</p>

<div style="margin-top:6px;"><span class="method-tag method-post">POST</span><code>/api/v1/pipey/publish</code></div>

<h3>Request body</h3>
<pre><code>{
  "recipient": "550e8400-e29b-41d4-a716-446655440000",
  "payload": {
    "message": "Hello Pipey!"
  }
}</code></pre>
</div>

<div class="card" id="responses">
<h2><span class="icon"><i class="fa-solid fa-list-check"></i></span>Responses</h2>

<div class="status-row"><span class="status-dot status-ok"></span><strong>200 OK</strong></div>
<pre><code>{
  "success": true,
  "message": "Event published"
}</code></pre>

<div class="status-row"><span class="status-dot status-warn"></span><strong>404 Not Found</strong></div>
<pre><code>{
  "success": false,
  "message": "Recipient is offline"
}</code></pre>

<div class="status-row"><span class="status-dot status-err"></span><strong>500 Internal Server Error</strong></div>
<pre><code>{
  "success": false,
  "message": "Failed to publish event"
}</code></pre>
</div>

<div class="card" id="js-example">
<h2><span class="icon"><i class="fa-brands fa-js"></i></span>JavaScript</h2>
<pre><code id="js-code"></code></pre>
</div>

<div class="card" id="curl-example">
<h2><span class="icon"><i class="fa-solid fa-terminal"></i></span>cURL</h2>
<pre><code id="curl-code"></code></pre>
</div>

<div class="card" id="how-it-works">
<h2><span class="icon"><i class="fa-solid fa-diagram-project"></i></span>How it works</h2>
<ol class="steps">
<li>Open a WebSocket connection.</li>
<li>Pipey subscribes the connection.</li>
<li>Publish via HTTP.</li>
<li>Pipey delivers the event instantly if the user is online.</li>
</ol>
</div>

</div>

{% endblock %}

{% block scripts %}
<script>
const wsScheme = location.protocol === "https:" ? "wss" : "ws";
const httpScheme = location.protocol.replace(":", "");
const host = location.host;

const wsUrl = `${wsScheme}://${host}/api/v1/ws/pipey?user_id=550e8400-e29b-41d4-a716-446655440000`;
const publishUrl = `${httpScheme}://${host}/api/v1/pipey/publish`;

document.getElementById("ws-example").textContent = wsUrl;

document.getElementById("js-code").textContent =
`const socket = new WebSocket("${wsUrl}");

socket.onmessage = ({ data }) => {
  console.log(JSON.parse(data));
};`;

document.getElementById("curl-code").textContent =
`curl -X POST ${publishUrl} \\
  -H "Content-Type: application/json" \\
  -d '{
    "recipient":"550e8400-e29b-41d4-a716-446655440000",
    "payload":{
      "message":"Hello from Pipey!"
    }
  }'`;
</script>
{% endblock %}