Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

distribution.tsx

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

distribution.tsxBlame756 lines · 1 contributor
11c3ab6ccanty labs1import type { FC } from "hono/jsx";
2
3export interface DistributionViewProps {
4 user?: any;
5}
6
7const agents = [
8 { name: "migration-pilot — schema change agent", initials: "MP", bg: "#41707e", installs: "3.1k installs" },
9 { name: "a11y-guard — accessibility gate", initials: "AG", bg: "#4353c9", installs: "2.4k installs" },
10 { name: "perf-sentry — bundle & latency budget", initials: "PS", bg: "#b45309", installs: "1.8k installs" },
11 { name: "license-warden — dependency compliance", initials: "LW", bg: "#16181d", installs: "1.2k installs" },
12];
13
14export const DistributionView: FC<DistributionViewProps> = (props) => {
15 const { user } = props;
16
17 return (
18 <>
19 <style dangerouslySetInnerHTML={{ __html: css }} />
20 <div class="di-root">
21
22 <header class="di-header">
23 <a href="/" class="di-logo">
24 <span class="di-logo-mark" />
25 gluecron
26 </a>
27 <span class="di-header-sep">/</span>
28 <span class="di-header-crumb">Everywhere you work</span>
29 <div class="di-header-right">
30 {user ? (
31 <a href="/dashboard" class="di-btn-primary">Dashboard</a>
32 ) : (
33 <a href="/login" class="di-btn-primary">Sign in</a>
34 )}
35 </div>
36 </header>
37
38 <main class="di-main">
39
40 <div class="di-hero">
41 <div class="di-eyebrow">Distribution · five channels, one platform</div>
42 <h1 class="di-hero-title">Gluecron lives where you already work.</h1>
43 <p class="di-hero-desc">Editor, terminal, README, chat, marketplace — the web app is just one door of five.</p>
44 </div>
45
46 <div class="di-cards">
47
48 {/* Card 1 — IDE */}
49 <div class="di-card">
50 <div class="di-card-copy">
51 <div class="di-eyebrow">01 · The IDE invasion</div>
52 <h2 class="di-card-title">A full Gluecron client in your editor sidebar.</h2>
53 <p class="di-card-desc">PR live sessions, AI commit messages, issue tracking, agent supervision — VS Code and JetBrains extensions with zero context switching. The browser becomes optional.</p>
54 <a href="/ide-multiplayer" class="di-card-link">See a live editor session →</a>
55 </div>
56 <div class="di-preview di-preview-light di-preview-ide">
57 <div class="di-code-comment">// VS Code · Gluecron sidebar</div>
58 <div class="di-ide-row">
59 <span class="di-dot di-dot-amber di-dot-pulse" />
60 <span class="di-ide-text">PR №218 — repair in progress</span>
61 </div>
62 <div class="di-ide-row">
63 <span class="di-dot di-dot-green" />
64 <span class="di-ide-text">3 issues assigned to you</span>
65 </div>
66 <div class="di-ide-row">
67 <span class="di-dot di-dot-indigo" />
68 <span class="di-ide-text">&#x270e; commit message drafted — accept?</span>
69 </div>
70 </div>
71 </div>
72
73 {/* Card 2 — CLI */}
74 <div class="di-card">
75 <div class="di-card-copy">
76 <div class="di-eyebrow">02 · Command-line dominance</div>
77 <h2 class="di-card-title">The whole platform from your shell.</h2>
78 <p class="di-card-desc">One single-file binary. Clone, watch gates stream live, trigger deploys, supervise agents — Gluecron feels like part of the operating system, not a distant web app.</p>
79 <a href="/repos" class="di-card-link">Get the CLI →</a>
80 </div>
81 <div class="di-preview di-preview-dark">
82 <div class="di-term-line"><span class="di-term-prompt">$</span> gluecron watch</div>
83 <div class="di-term-line di-term-dim">&#x23E7; feat/auth-header · pushed 4s ago</div>
84 <div class="di-term-line">
85 <span class="di-term-green">&#x2713;</span> gate: security ·{" "}
86 <span class="di-term-green">&#x2713;</span> gate: types
87 </div>
88 <div class="di-term-line">
89 <span class="di-term-amber">&#x25CF;</span> gate: tests — running in sandbox…
90 </div>
91 <div class="di-term-line">
92 <span class="di-term-green">&#x2713;</span> sonnet-5 review — approved
93 </div>
94 </div>
95 </div>
96
97 {/* Card 3 — Badges */}
98 <div class="di-card">
99 <div class="di-card-copy">
100 <div class="di-eyebrow">03 · Public proof &amp; viral loops</div>
101 <h2 class="di-card-title">Every public README becomes a billboard.</h2>
102 <p class="di-card-desc">Live health scores, green rates, and self-repair stats embed as dynamic badges. Every repo that shows one is a working demo of the platform — proof, not marketing.</p>
103 <a href="/trust" class="di-card-link">See the live numbers behind them →</a>
104 </div>
105 <div class="di-preview di-preview-light di-preview-badges">
106 <div class="di-badges-filename">README.md</div>
107 <div class="di-badge-strip">
108 <span class="di-badge">
109 <span class="di-badge-key">health</span>
110 <span class="di-badge-val di-badge-green">A · 91</span>
111 </span>
112 <span class="di-badge">
113 <span class="di-badge-key">gates</span>
114 <span class="di-badge-val di-badge-green">green 30d</span>
115 </span>
116 <span class="di-badge">
117 <span class="di-badge-key">self-repair</span>
118 <span class="di-badge-val di-badge-indigo">93.5%</span>
119 </span>
120 <span class="di-badge">
121 <span class="di-badge-key">reviewed by</span>
122 <span class="di-badge-val di-badge-dark">sonnet 5</span>
123 </span>
124 </div>
125 <div class="di-badges-meta">live · updates on every push · one line of markdown</div>
126 </div>
127 </div>
128
129 {/* Card 4 — ChatOps */}
130 <div class="di-card">
131 <div class="di-card-copy">
132 <div class="di-eyebrow">04 · ChatOps</div>
133 <h2 class="di-card-title">Inside the team's nervous system.</h2>
134 <p class="di-card-desc">Slack and Discord integrations push the moments that matter — a repaired build, an agent PR awaiting approval — and take action right from the thread. Approve without leaving chat.</p>
135 <a href="/daily-brief" class="di-card-link">See the daily brief it feeds →</a>
136 </div>
137 <div class="di-preview di-preview-light di-preview-chat">
138 <div class="di-chat-msg">
139 <span class="di-chat-avatar">GC</span>
140 <div class="di-chat-body">
141 <div class="di-chat-header">
142 <strong>gluecron</strong>
143 <span class="di-chat-meta">APP · #eng-core</span>
144 </div>
145 <div class="di-chat-text">
146 &#x2705; Repair converged on <strong>gluecron №218</strong> — gates green, waiting on one approval.
147 </div>
148 <div class="di-chat-actions">
149 <span class="di-chat-btn-primary">Approve &amp; merge</span>
150 <span class="di-chat-btn-secondary">Open diff</span>
151 </div>
152 </div>
153 </div>
154 </div>
155 </div>
156
157 {/* Card 5 — Marketplace */}
158 <div class="di-card">
159 <div class="di-card-copy">
160 <div class="di-eyebrow">05 · The agent marketplace</div>
161 <h2 class="di-card-title">An ecosystem that builds itself.</h2>
162 <p class="di-card-desc">Scoped bot identities and developer apps let anyone ship specialized agents on the platform — every install runs under the same gates, audit trail, and reversibility guarantee as ours.</p>
163 <a href="/trust" class="di-card-link">The trust rules every agent obeys →</a>
164 </div>
165 <div class="di-preview di-preview-light di-preview-marketplace">
166 {agents.map((a) => (
167 <div class="di-agent-row" key={a.name}>
168 <span class="di-agent-avatar" style={`background:${a.bg}`}>{a.initials}</span>
169 <span class="di-agent-name">{a.name}</span>
170 <span class="di-agent-installs">{a.installs}</span>
171 </div>
172 ))}
173 </div>
174 </div>
175
176 </div>
177 </main>
178 </div>
179 <script dangerouslySetInnerHTML={{ __html: js }} />
180 </>
181 );
182};
183
184export default DistributionView;
185
186const js = `
187(function() {
188 // Animate CLI terminal lines sequentially on scroll into view
189 var termLines = document.querySelectorAll('.di-preview-dark .di-term-line');
190 if (termLines.length) {
191 termLines.forEach(function(el, i) {
192 el.style.opacity = '0';
193 el.style.transform = 'translateX(-6px)';
194 el.style.transition = 'opacity 0.28s ease, transform 0.28s ease';
195 });
196 var termAnimated = false;
197 function animateTerminal() {
198 if (termAnimated) return;
199 termAnimated = true;
200 termLines.forEach(function(el, i) {
201 setTimeout(function() {
202 el.style.opacity = '1';
203 el.style.transform = 'translateX(0)';
204 }, i * 140);
205 });
206 }
207 var observer = new IntersectionObserver(function(entries) {
208 entries.forEach(function(entry) {
209 if (entry.isIntersecting) animateTerminal();
210 });
211 }, { threshold: 0.3 });
212 var termCard = document.querySelector('.di-preview-dark');
213 if (termCard) observer.observe(termCard);
214 }
215
216 // Badge hover effect — slight lift
217 var badges = document.querySelectorAll('.di-badge');
218 badges.forEach(function(b) {
219 b.addEventListener('mouseenter', function() {
220 b.style.transform = 'translateY(-1px)';
221 b.style.transition = 'transform 0.15s ease';
222 });
223 b.addEventListener('mouseleave', function() {
224 b.style.transform = '';
225 });
226 });
227
228 // Chat action buttons — mock interactivity
229 var approveBtn = document.querySelector('.di-chat-btn-primary');
230 if (approveBtn) {
231 approveBtn.addEventListener('click', function() {
232 var original = approveBtn.textContent;
233 approveBtn.textContent = 'Merged!';
234 approveBtn.style.background = '#1e7f5c';
235 setTimeout(function() {
236 approveBtn.textContent = original;
237 approveBtn.style.background = '';
238 }, 2000);
239 });
240 }
241
242 // Agent marketplace rows — stagger fade in on scroll
243 var agentRows = document.querySelectorAll('.di-agent-row');
244 if (agentRows.length) {
245 agentRows.forEach(function(el) {
246 el.style.opacity = '0';
247 el.style.transform = 'translateY(6px)';
248 el.style.transition = 'opacity 0.26s ease, transform 0.26s ease';
249 });
250 var agentObserver = new IntersectionObserver(function(entries) {
251 entries.forEach(function(entry) {
252 if (entry.isIntersecting) {
253 agentRows.forEach(function(el, i) {
254 setTimeout(function() {
255 el.style.opacity = '1';
256 el.style.transform = 'translateY(0)';
257 }, i * 80);
258 });
259 agentObserver.disconnect();
260 }
261 });
262 }, { threshold: 0.2 });
263 var mp = document.querySelector('.di-preview-marketplace');
264 if (mp) agentObserver.observe(mp);
265 }
266})();
267`;
268
269const css = `
270@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;450;500;600;700&family=Inter+Tight:wght@500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');
271
272@keyframes gcPulse {
273 0%, 100% { opacity: 1; }
274 50% { opacity: 0.35; }
275}
276
277*, *::before, *::after {
278 box-sizing: border-box;
279}
280
281.di-root {
282 font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
283 font-size: 14px;
284 line-height: 1.55;
285 letter-spacing: -0.008em;
286 color: #16181d;
287 background: #fcfcfd;
288 min-height: 100vh;
289 display: flex;
290 flex-direction: column;
291 -webkit-font-smoothing: antialiased;
292 text-rendering: optimizeLegibility;
293}
294
295/* ── Header ── */
296.di-header {
297 height: 56px;
298 border-bottom: 1px solid rgba(22,24,29,0.07);
299 background: #fcfcfd;
300 display: flex;
301 align-items: center;
302 padding: 0 28px;
303 gap: 20px;
304 position: sticky;
305 top: 0;
306 z-index: 50;
307}
308
309.di-logo {
310 display: inline-flex;
311 align-items: center;
312 gap: 9px;
313 font-family: 'Inter Tight', sans-serif;
314 font-weight: 600;
315 font-size: 15px;
316 letter-spacing: -0.02em;
317 color: #16181d;
318 text-decoration: none;
319}
320
321.di-logo-mark {
322 width: 16px;
323 height: 16px;
324 border-radius: 5px;
325 background: #4353c9;
326 display: inline-block;
327 flex-shrink: 0;
328}
329
330.di-header-sep {
331 color: #c4c6cf;
332 user-select: none;
333}
334
335.di-header-crumb {
336 font-size: 13px;
337 color: #16181d;
338 font-weight: 500;
339}
340
341.di-header-right {
342 margin-left: auto;
343}
344
345.di-btn-primary {
346 padding: 8px 15px;
347 border-radius: 8px;
348 font-size: 13px;
349 font-weight: 600;
350 background: #16181d;
351 color: #fff;
352 text-decoration: none;
353 white-space: nowrap;
354 display: inline-block;
355 letter-spacing: -0.008em;
356}
357
358.di-btn-primary:hover {
359 background: #2a2d36;
360}
361
362/* ── Main ── */
363.di-main {
364 flex: 1;
365 max-width: 1180px;
366 width: 100%;
367 margin: 0 auto;
368 padding: 52px 32px 88px;
369}
370
371/* ── Hero ── */
372.di-hero {
373 max-width: 660px;
374 margin-bottom: 44px;
375}
376
377.di-eyebrow {
378 font-family: 'JetBrains Mono', monospace;
379 font-size: 11px;
380 letter-spacing: 0.12em;
381 text-transform: uppercase;
382 color: #8a8d99;
383 margin-bottom: 10px;
384}
385
386.di-hero-title {
387 font-family: 'Inter Tight', sans-serif;
388 font-size: 30px;
389 font-weight: 600;
390 letter-spacing: -0.026em;
391 line-height: 1.12;
392 margin: 0 0 10px;
393 color: #111318;
394}
395
396.di-hero-desc {
397 font-size: 14.5px;
398 color: #6b7080;
399 margin: 0;
400 line-height: 1.6;
401}
402
403/* ── Cards list ── */
404.di-cards {
405 display: flex;
406 flex-direction: column;
407 gap: 18px;
408}
409
410/* ── Individual card ── */
411.di-card {
412 display: grid;
413 grid-template-columns: minmax(0,1fr) minmax(0,1.1fr);
414 gap: 44px;
415 align-items: center;
416 border: 1px solid rgba(22,24,29,0.08);
417 border-radius: 18px;
418 background: #ffffff;
419 padding: 38px 42px;
420 transition: border-color 0.18s ease;
421}
422
423.di-card:hover {
424 border-color: rgba(22,24,29,0.14);
425}
426
427/* ── Card copy ── */
428.di-card-copy .di-eyebrow {
429 margin-bottom: 10px;
430}
431
432.di-card-title {
433 font-family: 'Inter Tight', sans-serif;
434 font-size: 22px;
435 font-weight: 600;
436 letter-spacing: -0.02em;
437 margin: 0 0 10px;
438 color: #111318;
439 line-height: 1.2;
440}
441
442.di-card-desc {
443 font-size: 13.5px;
444 color: #6b7080;
445 margin: 0 0 14px;
446 line-height: 1.65;
447}
448
449.di-card-link {
450 font-size: 13px;
451 font-weight: 600;
452 color: #4353c9;
453 text-decoration: none;
454}
455
456.di-card-link:hover {
457 text-decoration: underline;
458}
459
460/* ── Preview panels (shared) ── */
461.di-preview {
462 border-radius: 12px;
463 padding: 18px 20px;
464}
465
466.di-preview-light {
467 border: 1px solid rgba(22,24,29,0.07);
468 background: #fcfcfd;
469}
470
471/* ── IDE preview ── */
472.di-preview-ide {
473 font-family: 'JetBrains Mono', monospace;
474 font-size: 12px;
475 line-height: 1.9;
476}
477
478.di-code-comment {
479 color: #8a8d99;
480}
481
482.di-ide-row {
483 display: flex;
484 align-items: center;
485 gap: 9px;
486}
487
488.di-ide-text {
489 color: #16181d;
490}
491
492.di-dot {
493 width: 6px;
494 height: 6px;
495 border-radius: 50%;
496 flex-shrink: 0;
497 display: inline-block;
498}
499
500.di-dot-amber { background: #b45309; }
501.di-dot-green { background: #1e7f5c; }
502.di-dot-indigo { background: #4353c9; }
503.di-dot-pulse { animation: gcPulse 1.4s ease-in-out infinite; }
504
505/* ── CLI / Terminal preview ── */
506.di-preview-dark {
507 border: 1px solid rgba(22,24,29,0.9);
508 border-radius: 12px;
509 background: #0f1116;
510 padding: 18px 20px;
511 font-family: 'JetBrains Mono', monospace;
512 font-size: 12px;
513 line-height: 1.9;
514 color: #d6d8e0;
515}
516
517.di-term-line {
518 display: block;
519}
520
521.di-term-dim {
522 color: #8a8d99;
523}
524
525.di-term-prompt { color: #5f8fa0; }
526.di-term-green { color: #2fbf83; }
527.di-term-amber { color: #e0a35a; }
528
529/* ── Badges preview ── */
530.di-preview-badges {}
531
532.di-badges-filename {
533 font-family: 'JetBrains Mono', monospace;
534 font-size: 11px;
535 color: #8a8d99;
536 margin-bottom: 12px;
537}
538
539.di-badge-strip {
540 display: flex;
541 gap: 8px;
542 flex-wrap: wrap;
543}
544
545.di-badge {
546 display: inline-flex;
547 font-size: 11px;
548 font-weight: 600;
549 border-radius: 5px;
550 overflow: hidden;
551 border: 1px solid rgba(22,24,29,0.10);
552 cursor: default;
553 user-select: none;
554}
555
556.di-badge-key {
557 background: #3a3d45;
558 color: #fff;
559 padding: 4px 8px;
560}
561
562.di-badge-val {
563 padding: 4px 8px;
564 color: #fff;
565}
566
567.di-badge-green { background: #1e7f5c; }
568.di-badge-indigo { background: #4353c9; }
569.di-badge-dark { background: #16181d; }
570
571.di-badges-meta {
572 font-family: 'JetBrains Mono', monospace;
573 font-size: 10.5px;
574 color: #8a8d99;
575 margin-top: 12px;
576}
577
578/* ── ChatOps preview ── */
579.di-preview-chat {
580 display: flex;
581 flex-direction: column;
582 gap: 10px;
583}
584
585.di-chat-msg {
586 display: flex;
587 gap: 10px;
588 align-items: flex-start;
589}
590
591.di-chat-avatar {
592 width: 26px;
593 height: 26px;
594 border-radius: 7px;
595 background: #4353c9;
596 color: #fff;
597 font-size: 9px;
598 font-weight: 700;
599 display: inline-flex;
600 align-items: center;
601 justify-content: center;
602 flex-shrink: 0;
603 font-family: 'Inter', sans-serif;
604}
605
606.di-chat-body {
607 flex: 1;
608}
609
610.di-chat-header {
611 font-size: 12.5px;
612 color: #16181d;
613}
614
615.di-chat-meta {
616 color: #8a8d99;
617 font-size: 11px;
618 margin-left: 4px;
619}
620
621.di-chat-text {
622 font-size: 12.5px;
623 color: #3a3d45;
624 margin-top: 2px;
625 line-height: 1.55;
626}
627
628.di-chat-actions {
629 display: flex;
630 gap: 6px;
631 margin-top: 8px;
632}
633
634.di-chat-btn-primary {
635 font-size: 11px;
636 font-weight: 600;
637 padding: 4px 12px;
638 border-radius: 6px;
639 background: #16181d;
640 color: #fff;
641 cursor: pointer;
642 user-select: none;
643 transition: background 0.18s ease;
644 display: inline-block;
645}
646
647.di-chat-btn-primary:hover {
648 background: #2a2d36;
649}
650
651.di-chat-btn-secondary {
652 font-size: 11px;
653 font-weight: 600;
654 padding: 4px 12px;
655 border-radius: 6px;
656 border: 1px solid rgba(22,24,29,0.14);
657 color: #16181d;
658 cursor: pointer;
659 user-select: none;
660 background: transparent;
661 display: inline-block;
662 transition: border-color 0.18s ease;
663}
664
665.di-chat-btn-secondary:hover {
666 border-color: rgba(22,24,29,0.28);
667}
668
669/* ── Marketplace preview ── */
670.di-preview-marketplace {
671 display: flex;
672 flex-direction: column;
673 gap: 8px;
674}
675
676.di-agent-row {
677 display: flex;
678 align-items: center;
679 gap: 10px;
680 padding: 8px 10px;
681 border: 1px solid rgba(22,24,29,0.06);
682 border-radius: 9px;
683 background: #ffffff;
684 transition: border-color 0.15s ease, box-shadow 0.15s ease;
685}
686
687.di-agent-row:hover {
688 border-color: rgba(22,24,29,0.13);
689 box-shadow: 0 1px 4px rgba(22,24,29,0.06);
690}
691
692.di-agent-avatar {
693 width: 24px;
694 height: 24px;
695 border-radius: 7px;
696 color: #fff;
697 font-size: 9px;
698 font-weight: 700;
699 display: inline-flex;
700 align-items: center;
701 justify-content: center;
702 flex-shrink: 0;
703 font-family: 'Inter', sans-serif;
704}
705
706.di-agent-name {
707 font-size: 12.5px;
708 font-weight: 500;
709 color: #16181d;
710 flex: 1;
711 min-width: 0;
712 overflow: hidden;
713 text-overflow: ellipsis;
714 white-space: nowrap;
715}
716
717.di-agent-installs {
718 font-size: 11px;
719 color: #8a8d99;
720 font-family: 'JetBrains Mono', monospace;
721 flex-shrink: 0;
722 margin-left: auto;
723}
724
725/* ── Responsive ── */
726@media (max-width: 860px) {
727 .di-card {
728 grid-template-columns: 1fr;
729 gap: 24px;
730 padding: 28px 24px;
731 }
732
733 .di-main {
734 padding: 36px 20px 64px;
735 }
736
737 .di-hero-title {
738 font-size: 24px;
739 }
740}
741
742@media (max-width: 560px) {
743 .di-header {
744 padding: 0 16px;
745 gap: 12px;
746 }
747
748 .di-header-crumb {
749 display: none;
750 }
751
752 .di-badge-strip {
753 gap: 6px;
754 }
755}
756`;