levix-bot 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/views/login.ejs CHANGED
@@ -7,99 +7,63 @@
7
7
  <link rel="icon" type="image/png" sizes="32x32" href="/brand/icon-32.png" />
8
8
  <link rel="apple-touch-icon" href="/brand/apple-touch-icon.png" />
9
9
  <link rel="stylesheet" href="/dashboard.css" />
10
- <style>
11
- body {
12
- display: grid;
13
- place-items: center;
14
- padding: 24px;
15
- background:
16
- radial-gradient(900px 500px at 15% -10%, rgba(22, 82, 240, 0.22), transparent 60%),
17
- radial-gradient(700px 420px at 90% 110%, rgba(33, 212, 253, 0.16), transparent 60%),
18
- var(--bg);
19
- }
20
-
21
- .login {
22
- width: 100%;
23
- max-width: 380px;
24
- text-align: center;
25
- }
26
-
27
- .login .brand-lockup {
28
- margin-bottom: 22px;
29
- }
30
-
31
- .login .card {
32
- text-align: left;
33
- padding: 24px;
34
- box-shadow: var(--shadow);
35
- }
36
-
37
- .login h1 {
38
- font-size: 1.05rem;
39
- font-weight: 650;
40
- margin-bottom: 4px;
41
- }
42
-
43
- .login p.sub {
44
- color: var(--muted);
45
- font-size: 0.86rem;
46
- margin-bottom: 18px;
47
- }
10
+ </head>
11
+ <body class="gateway-page">
12
+ <main class="gateway-shell">
13
+ <section class="gateway-story" aria-label="About <%= brand.name %>">
14
+ <div class="brand-lockup" aria-label="<%= brand.name %>">
15
+ <img src="/brand/mark.svg" alt="" />
16
+ <span><strong><%= brand.name %></strong><small><%= brand.tagline %></small></span>
17
+ </div>
48
18
 
49
- .login button {
50
- width: 100%;
51
- margin-top: 6px;
52
- padding: 11px;
53
- }
19
+ <div class="gateway-copy">
20
+ <span class="eyebrow">Self-hosted by design</span>
21
+ <h2>The quiet control room behind every chat.</h2>
22
+ <p>Connection, commands, memory, and moderation stay together—on your server and within reach.</p>
23
+ </div>
54
24
 
55
- .error {
56
- margin-top: 12px;
57
- padding: 9px 12px;
58
- border-radius: var(--radius-sm);
59
- background: color-mix(in srgb, var(--danger) 14%, transparent);
60
- border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
61
- color: var(--danger);
62
- font-size: 0.85rem;
63
- text-align: center;
64
- }
25
+ <div class="gateway-mark" aria-hidden="true">
26
+ <span class="gateway-ring"></span>
27
+ <img src="/brand/mark.svg" alt="" />
28
+ </div>
65
29
 
66
- .foot {
67
- margin-top: 20px;
68
- color: var(--faint);
69
- font-size: 0.78rem;
70
- }
71
- </style>
72
- </head>
73
- <body>
74
- <div class="login">
75
- <div class="brand-lockup" aria-label="<%= brand.name %>">
76
- <img src="/brand/mark.svg" alt="" />
77
- <strong><%= brand.name %></strong>
78
- </div>
30
+ <p class="gateway-trust"><span></span> Private workspace · direct control</p>
31
+ </section>
79
32
 
80
- <form class="card" action="/login" method="post">
81
- <h1>Control panel</h1>
82
- <p class="sub">Sign in with your control panel password.</p>
33
+ <section class="gateway-panel">
34
+ <div class="gateway-panel-inner">
35
+ <form class="card auth-card" action="/login" method="post">
36
+ <div class="auth-head">
37
+ <span class="eyebrow">Secure access</span>
38
+ <h1>Welcome back</h1>
39
+ <p class="sub">Sign in to manage your Levix workspace.</p>
40
+ </div>
83
41
 
84
- <label class="field">
85
- <span>Password</span>
86
- <input
87
- type="password"
88
- name="password"
89
- autocomplete="current-password"
90
- autofocus
91
- required
92
- />
93
- </label>
42
+ <label class="field">
43
+ <span>Control panel password</span>
44
+ <input
45
+ type="password"
46
+ name="password"
47
+ autocomplete="current-password"
48
+ placeholder="Enter your password"
49
+ autofocus
50
+ required
51
+ />
52
+ </label>
94
53
 
95
- <button type="submit" class="btn btn-primary">Sign in</button>
54
+ <button type="submit" class="btn btn-primary auth-submit">
55
+ Open workspace
56
+ <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
57
+ </button>
96
58
 
97
- <% if (error) { %>
98
- <div class="error"><%= error %></div>
99
- <% } %>
100
- </form>
59
+ <% if (error) { %>
60
+ <div class="error" role="alert"><%= error %></div>
61
+ <% } %>
62
+ </form>
101
63
 
102
- <div class="foot"><%= brand.name %> - <%= brand.tagline %> · by <%= brand.developer %></div>
103
- </div>
64
+ <div class="foot"><%= brand.name %> by <%= brand.developer %> · <%= brand.studio %></div>
65
+ </div>
66
+ </section>
67
+ </main>
104
68
  </body>
105
69
  </html>
package/views/qr.ejs CHANGED
@@ -7,65 +7,63 @@
7
7
  <link rel="icon" type="image/png" sizes="32x32" href="/brand/icon-32.png" />
8
8
  <link rel="apple-touch-icon" href="/brand/apple-touch-icon.png" />
9
9
  <link rel="stylesheet" href="/dashboard.css" />
10
- <style>
11
- body {
12
- display: grid;
13
- place-items: center;
14
- padding: 24px;
15
- background:
16
- radial-gradient(900px 500px at 15% -10%, rgba(22, 82, 240, 0.2), transparent 60%),
17
- var(--bg);
18
- }
19
- .wrap {
20
- width: 100%;
21
- max-width: 430px;
22
- text-align: center;
23
- }
24
- .wrap .brand-lockup {
25
- margin-bottom: 20px;
26
- }
27
- .wrap .card {
28
- box-shadow: var(--shadow);
29
- }
30
- .foot {
31
- margin-top: 18px;
32
- color: var(--faint);
33
- font-size: 0.78rem;
34
- }
35
- </style>
36
10
  </head>
37
- <body>
38
- <div class="wrap">
39
- <div class="brand-lockup" aria-label="<%= brand.name %>">
40
- <img src="/brand/mark.svg" alt="" />
41
- <strong><%= brand.name %></strong>
42
- </div>
11
+ <body class="gateway-page">
12
+ <main class="gateway-shell">
13
+ <section class="gateway-story" aria-label="About <%= brand.name %>">
14
+ <div class="brand-lockup" aria-label="<%= brand.name %>">
15
+ <img src="/brand/mark.svg" alt="" />
16
+ <span><strong><%= brand.name %></strong><small><%= brand.tagline %></small></span>
17
+ </div>
43
18
 
44
- <div class="card">
45
- <div class="card-head">
46
- <h2>Link a WhatsApp account</h2>
47
- <div class="spacer"></div>
48
- <span class="pill" id="state"><span class="dot"></span>Waiting…</span>
19
+ <div class="gateway-copy">
20
+ <span class="eyebrow">A direct line</span>
21
+ <h2>Bring your assistant online.</h2>
22
+ <p>One scan securely links Levix to the WhatsApp account you choose.</p>
49
23
  </div>
50
24
 
51
- <div class="qr-box">
52
- <div class="qr-frame" id="frame"></div>
53
- <ol class="steps">
54
- <li>Open WhatsApp on the phone the bot should use.</li>
55
- <li>Settings → Linked devices → Link a device.</li>
56
- <li>Point the camera at the code above.</li>
57
- </ol>
58
- <div class="hint">
59
- No code yet? Levix only connects when you ask it to — press
60
- <strong>Start session</strong> on the dashboard's Connection screen.
61
- </div>
25
+ <div class="gateway-mark" aria-hidden="true">
26
+ <span class="gateway-ring"></span>
27
+ <img src="/brand/mark.svg" alt="" />
62
28
  </div>
63
29
 
64
- <a class="btn" href="/">Back to the dashboard</a>
65
- </div>
30
+ <p class="gateway-trust"><span></span> Live pairing status</p>
31
+ </section>
32
+
33
+ <section class="gateway-panel">
34
+ <div class="gateway-panel-inner qr-panel-inner">
35
+ <div class="card auth-card qr-card">
36
+ <div class="card-head qr-card-head">
37
+ <div>
38
+ <span class="eyebrow">Link device</span>
39
+ <h1>Scan with WhatsApp</h1>
40
+ </div>
41
+ <span class="pill" id="state"><span class="dot"></span>Waiting…</span>
42
+ </div>
43
+
44
+ <div class="qr-box">
45
+ <div class="qr-frame" id="frame"></div>
46
+ <ol class="steps">
47
+ <li><span>Open</span> WhatsApp on the phone the bot should use.</li>
48
+ <li><span>Choose</span> Settings → Linked devices → Link a device.</li>
49
+ <li><span>Scan</span> the code shown above.</li>
50
+ </ol>
51
+ <div class="callout compact-callout">
52
+ <span class="callout-icon" aria-hidden="true">i</span>
53
+ <p>No code yet? Press <strong>Start session</strong> on the dashboard's Connection screen.</p>
54
+ </div>
55
+ </div>
66
56
 
67
- <div class="foot"><%= brand.name %> · by <%= brand.developer %></div>
68
- </div>
57
+ <a class="btn qr-back" href="/">
58
+ <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19 12H5M11 6l-6 6 6 6"/></svg>
59
+ Back to dashboard
60
+ </a>
61
+ </div>
62
+
63
+ <div class="foot"><%= brand.name %> by <%= brand.developer %> · <%= brand.studio %></div>
64
+ </div>
65
+ </section>
66
+ </main>
69
67
 
70
68
  <script src="/socket.io.min.js"></script>
71
69
  <script src="/qrcode.min.js"></script>
@@ -114,7 +112,7 @@
114
112
 
115
113
  socket.on("session", (state) => {
116
114
  if (state.state === "connected") {
117
- frame.innerHTML = '<div style="padding:60px 30px;color:#0d1730">Linked ✓</div>';
115
+ frame.innerHTML = '<div class="qr-success">Linked ✓</div>';
118
116
  painted = null;
119
117
  setState("Connected", "on");
120
118
  return;
package/views/setup.ejs CHANGED
@@ -7,116 +7,73 @@
7
7
  <link rel="icon" type="image/png" sizes="32x32" href="/brand/icon-32.png" />
8
8
  <link rel="apple-touch-icon" href="/brand/apple-touch-icon.png" />
9
9
  <link rel="stylesheet" href="/dashboard.css" />
10
- <style>
11
- body {
12
- display: grid;
13
- place-items: center;
14
- padding: 24px;
15
- background:
16
- radial-gradient(900px 500px at 15% -10%, rgba(22, 82, 240, 0.22), transparent 60%),
17
- radial-gradient(700px 420px at 90% 110%, rgba(33, 212, 253, 0.16), transparent 60%),
18
- var(--bg);
19
- }
20
-
21
- .login {
22
- width: 100%;
23
- max-width: 400px;
24
- text-align: center;
25
- }
26
-
27
- .login .brand-lockup {
28
- margin-bottom: 22px;
29
- }
30
-
31
- .login .card {
32
- text-align: left;
33
- padding: 24px;
34
- box-shadow: var(--shadow);
35
- }
36
-
37
- .login h1 {
38
- font-size: 1.05rem;
39
- font-weight: 650;
40
- margin-bottom: 4px;
41
- }
42
-
43
- .login p.sub {
44
- color: var(--muted);
45
- font-size: 0.86rem;
46
- margin-bottom: 18px;
47
- }
48
-
49
- .login button {
50
- width: 100%;
51
- margin-top: 6px;
52
- padding: 11px;
53
- }
54
-
55
- .login .field {
56
- margin-bottom: 12px;
57
- }
58
-
59
- .error {
60
- margin-top: 12px;
61
- padding: 9px 12px;
62
- border-radius: var(--radius-sm);
63
- background: color-mix(in srgb, var(--danger) 14%, transparent);
64
- border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
65
- color: var(--danger);
66
- font-size: 0.85rem;
67
- text-align: center;
68
- }
69
-
70
- .foot {
71
- margin-top: 20px;
72
- color: var(--faint);
73
- font-size: 0.78rem;
74
- }
75
- </style>
76
10
  </head>
77
- <body>
78
- <div class="login">
79
- <div class="brand-lockup" aria-label="<%= brand.name %>">
80
- <img src="/brand/mark.svg" alt="" />
81
- <strong><%= brand.name %></strong>
82
- </div>
83
-
84
- <form class="card" action="/setup" method="post">
85
- <h1>Welcome</h1>
86
- <p class="sub">
87
- Pick a password for the control panel. It is the only thing protecting a
88
- linked WhatsApp account, so make it a real one — at least
89
- <%= minLength %> characters.
90
- </p>
91
-
92
- <% if (needsCode) { %>
93
- <label class="field">
94
- <span>Setup code</span>
95
- <input type="text" name="code" autocomplete="off" autofocus required
96
- placeholder="printed in the bot's terminal" />
97
- </label>
98
- <% } %>
99
-
100
- <label class="field">
101
- <span>Password</span>
102
- <input type="password" name="password" autocomplete="new-password"
103
- minlength="<%= minLength %>" <%= needsCode ? "" : "autofocus" %> required />
104
- </label>
105
-
106
- <label class="field">
107
- <span>Repeat password</span>
108
- <input type="password" name="confirm" autocomplete="new-password"
109
- minlength="<%= minLength %>" required />
110
- </label>
111
-
112
- <button type="submit" class="btn btn-primary">Create and sign in</button>
113
-
114
- <% if (error) { %>
115
- <div class="error"><%= error %></div>
116
- <% } %>
117
- </form>
118
-
119
- <div class="foot"><%= brand.name %> - <%= brand.tagline %> · by <%= brand.developer %></div>
120
- </div>
11
+ <body class="gateway-page">
12
+ <main class="gateway-shell">
13
+ <section class="gateway-story" aria-label="About <%= brand.name %>">
14
+ <div class="brand-lockup" aria-label="<%= brand.name %>">
15
+ <img src="/brand/mark.svg" alt="" />
16
+ <span><strong><%= brand.name %></strong><small><%= brand.tagline %></small></span>
17
+ </div>
18
+
19
+ <div class="gateway-copy">
20
+ <span class="eyebrow">Your first minute</span>
21
+ <h2>Make the workspace yours.</h2>
22
+ <p>Choose one strong password, then manage the assistant from a single private control room.</p>
23
+ </div>
24
+
25
+ <div class="gateway-mark" aria-hidden="true">
26
+ <span class="gateway-ring"></span>
27
+ <img src="/brand/mark.svg" alt="" />
28
+ </div>
29
+
30
+ <p class="gateway-trust"><span></span> One setup · no configuration files</p>
31
+ </section>
32
+
33
+ <section class="gateway-panel">
34
+ <div class="gateway-panel-inner">
35
+ <form class="card auth-card setup-card" action="/setup" method="post">
36
+ <div class="auth-head">
37
+ <span class="eyebrow">Create your workspace</span>
38
+ <h1>Welcome to <%= brand.name %></h1>
39
+ <p class="sub">Protect the linked WhatsApp account with at least <%= minLength %> characters.</p>
40
+ </div>
41
+
42
+ <% if (needsCode) { %>
43
+ <label class="field">
44
+ <span>Setup code</span>
45
+ <input type="text" name="code" autocomplete="off" autofocus required
46
+ placeholder="Printed in the bot's terminal" />
47
+ <small>Confirms you can access the server running Levix.</small>
48
+ </label>
49
+ <% } %>
50
+
51
+ <label class="field">
52
+ <span>Password</span>
53
+ <input type="password" name="password" autocomplete="new-password"
54
+ placeholder="At least <%= minLength %> characters"
55
+ minlength="<%= minLength %>" <%= needsCode ? "" : "autofocus" %> required />
56
+ </label>
57
+
58
+ <label class="field">
59
+ <span>Repeat password</span>
60
+ <input type="password" name="confirm" autocomplete="new-password"
61
+ placeholder="Type it again" minlength="<%= minLength %>" required />
62
+ </label>
63
+
64
+ <button type="submit" class="btn btn-primary auth-submit">
65
+ Create workspace
66
+ <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
67
+ </button>
68
+
69
+ <% if (error) { %>
70
+ <div class="error" role="alert"><%= error %></div>
71
+ <% } %>
72
+ </form>
73
+
74
+ <div class="foot"><%= brand.name %> by <%= brand.developer %> · <%= brand.studio %></div>
75
+ </div>
76
+ </section>
77
+ </main>
121
78
  </body>
122
79
  </html>