sendword 0.8.7

Simple HTTP webhook to command runner sidecar. Frontend for managing hooks, JSON state for config portability, SQLite for execution history and logs.
Documentation
<!doctype html>
<html lang="en" data-mode="dark">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{% block title %}sendword{% endblock %}</title>
  <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='2' y='6' width='28' height='20' rx='3' fill='%230c0a09' stroke='%23f59e0b' stroke-width='2'/%3E%3Cpath d='M2 8l14 10 14-10' fill='none' stroke='%23f59e0b' stroke-width='2' stroke-linecap='round'/%3E%3Ccircle cx='26' cy='8' r='5' fill='%23ef4444'/%3E%3C/svg%3E">
  <link rel="stylesheet" href="/static/css/wavefunk.css">
  <style>
    :root { --accent: #e06c75; --accent-ink: #000000; }
    [data-mode="light"] { --accent: #d20f39; --accent-ink: #ffffff; }
  </style>

  <script src="https://unpkg.com/htmx.org@2.0.4" defer></script>
  <script src="https://unpkg.com/htmx-ext-sse@2.2.2/sse.js" defer></script>
  <script src="/static/js/sendword.js" defer></script>
</head>
<body class="wf-app density-dense" hx-boost="true">

<div class="wf-shell">

  <aside class="wf-sidebar">
    <div class="wf-brand">
      <svg viewBox="0 0 32 32" aria-hidden="true" style="width: 22px; height: 22px;"><rect x="2" y="6" width="28" height="20" rx="3" fill="#0c0a09" stroke="#ffffff" stroke-width="2"/><path d="M2 8l14 10 14-10" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/><circle cx="26" cy="8" r="5" fill="#e06c75"/></svg>
      <span class="wf-brand-name">SENDWORD</span>
    </div>
    <nav class="wf-nav-list">
      <div class="wf-nav-section">HOOKS</div>
      <a class="wf-nav-item{{ ' is-active' if nav_active == 'dashboard' }}" href="/">&#x25B8; Hooks</a>
      <a class="wf-nav-item{{ ' is-active' if nav_active == 'approvals' }}" href="/approvals">&#x25B8; Approvals</a>
      <div class="wf-nav-section">TOOLS</div>
      <a class="wf-nav-item{{ ' is-active' if nav_active == 'scripts' }}" href="/scripts">&#x25B8; Scripts</a>
      <div class="wf-nav-section">ADMIN</div>
      <a class="wf-nav-item{{ ' is-active' if nav_active == 'admin' }}" href="/admin/users">&#x25B8; Users</a>
    </nav>
    <div class="wf-pop-anchor" style="display: block;">
      <button class="wf-user" data-popover-toggle>
        <div class="wf-avatar accent">{{ username | first | upper }}</div>
        <div class="wf-user-id">
          <div class="wf-user-name">{{ username }}</div>
        </div>
        <span class="wf-user-caret">&#x25B4;</span>
      </button>
      <div class="wf-popover" data-side="top" style="left: 8px; right: 8px;">
        <div class="wf-popover-head">{{ username | upper }}</div>
        <div class="wf-menu">
          <a class="wf-menu-item" href="/settings">Account settings</a>
          <div class="wf-menu-sep"></div>
          <form method="post" action="/logout" style="margin: 0;">
            <button type="submit" class="wf-menu-item danger" style="width: 100; text-align: left; background: none; border: none; cursor: pointer; font: inherit; color: inherit; padding: inherit;">Log out</button>
          </form>
        </div>
      </div>
    </div>
  </aside>

  <div class="wf-main">
    <header class="wf-topbar">
      {% block crumbs %}
      <div class="wf-crumbs">
        <span aria-current="page">SENDWORD</span>
      </div>
      {% endblock %}
      <div class="wf-grow"></div>
      {% block actions %}{% endblock %}
    </header>

    <main class="wf-scroll">
      {% if success %}<div class="wf-alert ok"><div class="wf-alert-bar"></div><div>{{ success }}</div></div>{% endif %}
      {% if error %}<div class="wf-alert err"><div class="wf-alert-bar"></div><div>{{ error }}</div></div>{% endif %}
      {% block content %}{% endblock %}
    </main>

    <div class="wf-statusbar wf-hair">
      <span>SENDWORD</span>
      <span class="wf-grow"></span>
      <span>V1.0</span>
    </div>
  </div>

</div>

<div class="wf-toast-host" id="toast-host"></div>

</body>
</html>