vyuh 0.2.11

Vyuh web framework for Axum and SQLx with handler-first APIs
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="color-scheme" content="light">
  <title>Vyuh - Rust Application Framework</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500&family=JetBrains+Mono:wght@400;600&family=Manrope:wght@400;500;600&display=swap" rel="stylesheet">
  <link rel="icon" href="../public/img/favicon.svg">
  <link rel="stylesheet" href="../public/css/vyuh.css">
</head>
<body>
  <header class="landing-header">
    <nav class="container-xxl landing-nav d-flex align-items-center justify-content-between gap-4">
      <a class="landing-brand" href="#top" aria-label="Vyuh home">
        <img src="../public/img/vyuh-logo-transparent.png" alt="">
        <span>vyuh</span>
      </a>

      <div class="landing-nav-links d-flex align-items-center gap-4">
        <a href="../../../docs/book/book/index.html">Docs</a>
        <a href="#code">Examples</a>
        <a href="#console">Console</a>
        <a href="#stack">Stack</a>
        <a href="https://github.com/vyuh-rs/vyuh">GitHub</a>
      </div>

      <div class="d-flex align-items-center gap-2">
        <a class="vyuh-icon-button" href="https://github.com/vyuh-rs/vyuh" aria-label="Vyuh on GitHub">
          <svg aria-hidden="true" viewBox="0 0 24 24" width="22" height="22">
            <path fill="currentColor" d="M12 .5a12 12 0 0 0-3.79 23.39c.6.11.82-.26.82-.58v-2.04c-3.34.73-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.09-.75.08-.73.08-.73 1.2.08 1.84 1.24 1.84 1.24 1.07 1.83 2.8 1.3 3.49.99.11-.78.42-1.3.76-1.6-2.66-.3-5.46-1.33-5.46-5.93 0-1.31.47-2.38 1.24-3.22-.12-.3-.54-1.52.12-3.18 0 0 1-.32 3.3 1.23A11.47 11.47 0 0 1 12 4.3c1.02.01 2.05.14 3.01.41 2.29-1.55 3.29-1.23 3.29-1.23.66 1.66.25 2.88.12 3.18.77.84 1.23 1.91 1.23 3.22 0 4.61-2.8 5.62-5.48 5.92.43.37.81 1.1.81 2.22v3.29c0 .32.22.7.83.58A12 12 0 0 0 12 .5Z"></path>
          </svg>
        </a>
        <a class="vyuh-button vyuh-button-primary d-none d-sm-inline-flex" href="#start">Get Started</a>
      </div>
    </nav>
  </header>

  <main id="top">
    <section class="landing-hero">
      <div class="container-xxl landing-hero-inner">
        <div class="landing-hero-grid">
          <article class="landing-hero-main">
            <strong class="vyuh-kicker">Rust application framework</strong>
            <h1 class="vyuh-display mt-3">Handler-first.<br>Runtime-aware.<br><span>Application-ready.</span></h1>
            <p class="vyuh-copy landing-hero-copy mt-4 mb-0">Build typed Rust APIs, background work, cron, channels, commands, services, OpenAPI, and console visibility from one coherent application model.</p>

            <div class="landing-action-row mt-4">
              <a class="vyuh-button vyuh-button-primary" href="#start">Get Started</a>
              <a class="vyuh-button vyuh-button-secondary" href="https://github.com/vyuh-rs/vyuh">GitHub</a>
            </div>
          </article>

          <figure class="landing-hero-art">
            <img src="../public/img/landing/vyuh-equation-hero-exact.svg" alt="The Vyuh equation showing handlers, services, and assets forming bundles, then sites, OpenAPI, and console">
          </figure>
        </div>

        <section id="philosophy" class="landing-philosophy" aria-labelledby="philosophy-title">
          <h2 id="philosophy-title" class="visually-hidden">Vyuh proof points</h2>
          <ol class="landing-philosophy-strip">
            <li class="landing-philosophy-item">
              <span class="landing-philosophy-mark landing-tone-ember" aria-hidden="true">⚡</span>
              <article>
                <h3>Rust-native</h3>
                <p>Typed async handlers with explicit data and error boundaries.</p>
              </article>
            </li>
            <li class="landing-philosophy-item">
              <span class="landing-philosophy-mark landing-tone-moss" aria-hidden="true">&lt;/&gt;</span>
              <article>
                <h3>Handler-first</h3>
                <p>Typed inputs, validation, and responses stay together.</p>
              </article>
            </li>
            <li class="landing-philosophy-item">
              <span class="landing-philosophy-mark landing-tone-saffron" aria-hidden="true">↔</span>
              <article>
                <h3>Runtime paths</h3>
                <p>Routes, tasks, cron, channels, commands, and services share a model.</p>
              </article>
            </li>
            <li class="landing-philosophy-item">
              <span class="landing-philosophy-mark landing-tone-ember" aria-hidden="true">{}</span>
              <article>
                <h3>OpenAPI</h3>
                <p>Schemas and docs come from registered handlers.</p>
              </article>
            </li>
            <li class="landing-philosophy-item">
              <span class="landing-philosophy-mark landing-tone-moss" aria-hidden="true">◎</span>
              <article>
                <h3>Console</h3>
                <p>Operations, config, runtime health, and tasks are inspectable.</p>
              </article>
            </li>
            <li class="landing-philosophy-item">
              <span class="landing-philosophy-mark landing-tone-saffron" aria-hidden="true">⬢</span>
              <article>
                <h3>Bundles</h3>
                <p>Application features compose without scattered registries.</p>
              </article>
            </li>
          </ol>
        </section>
      </div>
    </section>

    <section id="console" class="container-xxl landing-section landing-console-section" aria-labelledby="console-title">
      <div class="landing-console-shell">
        <header class="landing-console-copy">
          <strong class="vyuh-kicker">Console</strong>
          <h2 id="console-title" class="vyuh-section-title mt-2">If Vyuh can run it, Vyuh can describe it.</h2>
          <p class="vyuh-copy mt-3 mb-0">Routes, tasks, signals, emitters, services, schemas, OpenAPI, runtime config, and system health are registered into one inspectable surface.</p>
          <p id="console-inference" class="landing-console-inference">See the whole application shape without stitching together separate dashboards for routes, workers, docs, and services.</p>
          <div class="landing-console-actions" aria-label="Console image controls">
            <button class="landing-console-control is-active" type="button" data-console-slide="0">Overview</button>
            <button class="landing-console-control" type="button" data-console-slide="1">Operations</button>
            <button class="landing-console-control" type="button" data-console-slide="2">Tasks</button>
            <button class="landing-console-control" type="button" data-console-slide="3">OpenAPI</button>
            <button class="landing-console-control" type="button" data-console-slide="4">Runtime</button>
          </div>
        </header>

        <div class="landing-console-deck" aria-live="polite">
          <figure class="landing-console-slide is-active" data-inference="See the whole application shape without stitching together separate dashboards for routes, workers, docs, and services.">
            <img src="../public/img/console/overview.png" alt="Vyuh console overview with runtime totals and recent activity">
            <figcaption>Overview: every registered runtime surface in one place.</figcaption>
          </figure>
          <figure class="landing-console-slide" data-inference="Route docs carry method, auth, middleware, request, and response metadata from the registered handler.">
            <img src="../public/img/console/operations.png" alt="Vyuh console operations browser with route metadata">
            <figcaption>Operations: routes, auth, middleware, and schema metadata together.</figcaption>
          </figure>
          <figure class="landing-console-slide" data-inference="Background work is not invisible: task state, retry, suspension, and payload details are part of the console model.">
            <img src="../public/img/console/tasks.png" alt="Vyuh console task list with states and retry information">
            <figcaption>Tasks: inspect state, retries, suspension, and payload transitions.</figcaption>
          </figure>
          <figure class="landing-console-slide" data-inference="OpenAPI is generated from runtime registration, including schema, auth, and middleware context.">
            <img src="../public/img/console/openapi.png" alt="Vyuh console OpenAPI explorer">
            <figcaption>OpenAPI: generated from the same typed surfaces the app runs.</figcaption>
          </figure>
          <figure class="landing-console-slide" data-inference="Runtime configuration and health stay visible without exposing secrets or turning logs into the only source of truth.">
            <img src="../public/img/console/runtime.png" alt="Vyuh console runtime and system information">
            <figcaption>Runtime: system information, health, backend, and console configuration.</figcaption>
          </figure>
        </div>
      </div>
    </section>

    <section id="code" class="container-xxl landing-section">
      <header class="landing-section-head">
        <strong class="vyuh-kicker">Runtime paths</strong>
        <h2 class="vyuh-section-title mt-2">One handler model. Many runtime paths.</h2>
        <p class="vyuh-copy mt-3 mb-0">Vyuh treats application behavior as typed handlers, not scattered subsystems. The same signatures, data model, errors, auth, validation, and observability apply across them.</p>
        <div class="landing-rule" aria-hidden="true"></div>
      </header>

      <div class="landing-runtime-code">
        <nav class="landing-runtime-tabs" aria-label="Runtime path examples">
          <button class="landing-code-tab is-active" type="button" data-key="routes">Routes</button>
          <button class="landing-code-tab" type="button" data-key="tasks">Tasks</button>
          <button class="landing-code-tab" type="button" data-key="signals">Signals</button>
          <button class="landing-code-tab" type="button" data-key="emitters">Emitters</button>
          <button class="landing-code-tab" type="button" data-key="commands">Commands</button>
          <button class="landing-code-tab" type="button" data-key="channels">Channels</button>
          <button class="landing-code-tab" type="button" data-key="services">Services</button>
        </nav>

        <aside class="landing-runtime-panel">
          <article class="landing-runtime-copy">
            <strong id="code-eyebrow" class="vyuh-kicker">Routes</strong>
            <h3 id="code-title" class="vyuh-section-title mt-2">Handler-first APIs without hiding the Rust.</h3>
            <p id="code-copy" class="vyuh-copy mt-3 mb-0">Keep validation, permissions, and typed request handling visible where the behavior actually happens.</p>
            <ul class="landing-code-points">
              <li><span class="landing-code-bullet" aria-hidden="true">●</span><span id="code-point-a">Less boilerplate, more clarity</span></li>
              <li><span class="landing-code-bullet" aria-hidden="true">●</span><span id="code-point-b">Compiler-verified request handling</span></li>
              <li><span class="landing-code-bullet" aria-hidden="true">●</span><span id="code-point-c">Built for long-term maintainability</span></li>
            </ul>
          </article>
        </aside>

        <article class="vyuh-code-window">
          <header class="landing-code-toolbar">
            <span class="landing-dot landing-dot-danger" aria-hidden="true"></span>
            <span class="landing-dot landing-dot-warning" aria-hidden="true"></span>
            <span class="landing-dot landing-dot-success" aria-hidden="true"></span>
            <span id="code-file" class="landing-code-file">src/routes/users.rs</span>
          </header>

          <div class="landing-code-body">
            <pre><code id="code-snippet"></code></pre>
          </div>
        </article>
      </div>
    </section>

    <section id="tasks" class="container-xxl landing-section landing-section-tight">
      <article class="landing-capability landing-capability-tasks">
        <header class="landing-capability-copy">
          <strong class="vyuh-kicker">Tasks</strong>
          <h2 class="vyuh-section-title mt-2">Durable background work, without a second application.</h2>
          <p class="vyuh-copy mt-3 mb-0">Run emails, imports, reports, retries, approvals, and polling as typed handlers registered beside your APIs.</p>
          <p class="landing-capability-proof">Tasks can sleep, suspend, resume, retry, fail, and store typed results while staying visible in the console.</p>
        </header>

        <div class="landing-capability-visual" aria-label="Task capabilities">
          <div class="landing-capability-facts">
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M5 12h14M12 5v14"></path></svg>
              </span>
              <h3>Typed input</h3>
              <p>Submit Data&lt;T&gt; by task type and reuse route-style data.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M8 6v6l4 3M20 12a8 8 0 1 1-16 0 8 8 0 0 1 16 0Z"></path></svg>
              </span>
              <h3>Continuation state</h3>
              <p>Sleep or suspend work without keeping a Rust future alive.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M7 7h9a4 4 0 0 1 0 8H8"></path><path d="M10 11 7 15l3 4"></path></svg>
              </span>
              <h3>Explicit retry</h3>
              <p>Return retry state when work should run again later.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 6h16v12H4z"></path><path d="M7 10h4M7 14h7"></path></svg>
              </span>
              <h3>Console visible</h3>
              <p>Inspect state, payloads, retries, results, and failures.</p>
            </article>
          </div>
        </div>
      </article>
    </section>

    <section id="emitters" class="container-xxl landing-section landing-section-tight">
      <article class="landing-capability landing-capability-emitters landing-capability-flip">
        <header class="landing-capability-copy">
          <strong class="vyuh-kicker">Emitters</strong>
          <h2 class="vyuh-section-title mt-2">Schedules and triggers become typed runtime inputs.</h2>
          <p class="vyuh-copy mt-3 mb-0">Run cron, intervals, polling, retries, and external notifications as registered typed emitters.</p>
          <p class="landing-capability-proof">Emitters keep trigger logic close to the bundle and hand off to tasks, signals, or channels.</p>
        </header>

        <div class="landing-capability-visual" aria-label="Emitter capabilities">
          <div class="landing-capability-facts">
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 9h16M8 5v4M16 5v4M6 5h12v15H6z"></path></svg>
              </span>
              <h3>Cron and intervals</h3>
              <p>Register recurring work as named runtime behavior.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M12 4v16M5 12h14"></path></svg>
              </span>
              <h3>Typed emissions</h3>
              <p>Produce typed data for tasks, signals, channels, or services.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 7l8-4 8 4-8 4-8-4Z"></path><path d="m4 12 8 4 8-4"></path></svg>
              </span>
              <h3>Bundle-owned</h3>
              <p>Keep schedules beside the feature that owns them.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 6h16v12H4z"></path><path d="M8 10h8M8 14h5"></path></svg>
              </span>
              <h3>Console visible</h3>
              <p>Inspect registered emitters from the same console.</p>
            </article>
          </div>
        </div>
      </article>
    </section>

    <section id="channels" class="container-xxl landing-section landing-section-tight">
      <article class="landing-capability landing-capability-channels">
        <header class="landing-capability-copy">
          <strong class="vyuh-kicker">Channels</strong>
          <h2 class="vyuh-section-title mt-2">Live application streams, without a second realtime stack.</h2>
          <p class="vyuh-copy mt-3 mb-0">Publish typed events to browsers, services, and subscribers through channels beside routes and tasks.</p>
          <p class="landing-capability-proof">Channels make pub/sub and SSE-style delivery part of the explicit application model.</p>
        </header>

        <div class="landing-capability-visual" aria-label="Channel capabilities">
          <div class="landing-capability-facts">
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 7l8-4 8 4-8 4-8-4Z"></path><path d="m4 12 8 4 8-4"></path></svg>
              </span>
              <h3>Typed messages</h3>
              <p>Keep live payloads in the same typed data model.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 5h16v14H4z"></path><path d="M8 9h8M8 13h5"></path></svg>
              </span>
              <h3>Subscriber routes</h3>
              <p>Expose streams through the same routing surface.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M12 5v14M12 12H5M12 12h7"></path><path d="M5 9v6M19 9v6"></path></svg>
              </span>
              <h3>Fan-out targets</h3>
              <p>Connect signals, tasks, emitters, and external clients.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M3 12s3-6 9-6 9 6 9 6-3 6-9 6-9-6-9-6Z"></path><path d="M12 9a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z"></path></svg>
              </span>
              <h3>Runtime visibility</h3>
              <p>Keep channels discoverable beside every runtime path.</p>
            </article>
          </div>
        </div>
      </article>
    </section>

    <section id="openapi" class="container-xxl landing-section landing-section-tight">
      <article class="landing-capability landing-capability-openapi landing-capability-flip">
        <header class="landing-capability-copy">
          <strong class="vyuh-kicker">OpenAPI</strong>
          <h2 class="vyuh-section-title mt-2">Docs generated from the runtime model.</h2>
          <p class="vyuh-copy mt-3 mb-0">Generate OpenAPI from handlers, schemas, auth, permissions, and middleware registered in the app.</p>
          <p class="landing-capability-proof">Override generated docs through macros or direct APIs when contracts need extra precision.</p>
        </header>

        <div class="landing-capability-visual" aria-label="Vyuh OpenAPI capabilities">
          <div class="landing-capability-facts">
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M5 4h14v16H5z"></path><path d="M8 8h8M8 12h5"></path></svg>
              </span>
              <h3>Automatic by default</h3>
              <p>Routes, inputs, outputs, and schemas feed the document.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 20h4l11-11-4-4L4 16v4Z"></path></svg>
              </span>
              <h3>Override when needed</h3>
              <p>Use macros or direct APIs for exact operations.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M7 11V8a5 5 0 0 1 10 0v3"></path><path d="M5 11h14v9H5z"></path></svg>
              </span>
              <h3>Security included</h3>
              <p>Model API key and JWT schemes beside route metadata.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h16"></path></svg>
              </span>
              <h3>Runtime context</h3>
              <p>Surface permissions and middleware in generated docs.</p>
            </article>
          </div>
        </div>
      </article>
    </section>

    <section id="bundles" class="container-xxl landing-section landing-section-tight">
      <article class="landing-capability landing-capability-bundles">
        <header class="landing-capability-copy">
          <strong class="vyuh-kicker">Bundles</strong>
          <h2 class="vyuh-section-title mt-2">One feature. One bundle. Every runtime surface.</h2>
          <p class="vyuh-copy mt-3 mb-0">Package handlers, assets, templates, docs, and runtime surfaces near the feature code.</p>
          <p class="landing-capability-proof">Bundles can be imported from crates, prefixed, layered, validated, and mounted.</p>
        </header>

        <div class="landing-capability-visual landing-bundle-visual" aria-label="Bundle composition model">
          <div class="landing-capability-facts">
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 7l8-4 8 4-8 4-8-4Z"></path><path d="m4 12 8 4 8-4"></path></svg>
              </span>
              <h3>Feature-owned</h3>
              <p>Keep handlers, docs, assets, and surfaces together.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M8 12h8M12 8v8"></path><path d="M4 4h16v16H4z"></path></svg>
              </span>
              <h3>Composable</h3>
              <p>Merge, prefix, tag, layer, and validate before startup.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 5h16v14H4z"></path><path d="M7 9h5M7 13h8"></path></svg>
              </span>
              <h3>Delivery included</h3>
              <p>Carry assets, templates, services, and migrations.</p>
            </article>
            <article class="landing-capability-fact">
              <span class="landing-fact-icon" aria-hidden="true">
                <svg viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h16"></path></svg>
              </span>
              <h3>Modular</h3>
              <p>Import from another crate without losing APIs or assets.</p>
            </article>
          </div>
        </div>
      </article>
    </section>

    <section id="stack" class="container-xxl landing-section landing-section-tight">
      <article class="vyuh-card landing-stack-card">
        <header class="landing-section-head">
          <strong class="vyuh-kicker">Foundation</strong>
          <h2 class="vyuh-section-title mt-2">Built on the best of Rust.</h2>
        </header>

        <div class="landing-stack-grid">
          <section class="landing-stack-item">
            <span class="landing-stack-logo landing-tone-ember">axum</span>
            <h3>HTTP</h3>
            <p>Web framework</p>
          </section>
          <section class="landing-stack-item">
            <span class="landing-stack-logo landing-tone-moss">SQLx</span>
            <h3>Persistence</h3>
            <p>Async SQL toolkit</p>
          </section>
          <section class="landing-stack-item">
            <span class="landing-stack-logo landing-tone-saffron">tokio</span>
            <h3>Runtime</h3>
            <p>Async runtime</p>
          </section>
          <section class="landing-stack-item">
            <span class="landing-stack-logo landing-tone-moss">serde</span>
            <h3>Data</h3>
            <p>Serialization</p>
          </section>
          <section class="landing-stack-item">
            <span class="landing-stack-logo landing-tone-ember">minijinja</span>
            <h3>Views</h3>
            <p>Templates</p>
          </section>
          <section class="landing-stack-item">
            <span class="landing-stack-logo landing-tone-moss">schemars</span>
            <h3>Schemas</h3>
            <p>JSON Schema</p>
          </section>
        </div>
      </article>
    </section>

    <section id="start" class="container-xxl">
      <div class="landing-cta">
        <div class="landing-cta-inner">
          <div>
            <h2 class="vyuh-section-title">Ready to build something structured and powerful?</h2>
            <p class="vyuh-copy mt-3 mb-0">Start with a framework that keeps your project organized from the first route to the last background task.</p>
          </div>
          <div class="landing-cta-actions">
            <a class="vyuh-button landing-button-ink" href="../../../docs/book/book/index.html">Get Started</a>
            <a class="vyuh-button vyuh-button-secondary" href="https://github.com/vyuh-rs/vyuh">Star on GitHub</a>
          </div>
        </div>
      </div>
    </section>
  </main>

  <script src="../public/js/landing.js"></script>
</body>
</html>