create-claudeportal 0.1.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.
Files changed (39) hide show
  1. package/bin/cli.js +37 -0
  2. package/dist/assets/index-BBU5K5iA.js +132 -0
  3. package/dist/assets/index-fNmv07eE.css +1 -0
  4. package/dist/index.html +13 -0
  5. package/index.html +12 -0
  6. package/mockups/01-chat-conversation-v2.html +803 -0
  7. package/mockups/01-chat-conversation.html +592 -0
  8. package/mockups/02-activity-feed.html +648 -0
  9. package/mockups/03-focused-workspace.html +680 -0
  10. package/mockups/04-documents-mode.html +1556 -0
  11. package/package.json +54 -0
  12. package/server/index.js +140 -0
  13. package/server/lib/detect-tools.js +93 -0
  14. package/server/lib/file-scanner.js +46 -0
  15. package/server/lib/file-watcher.js +45 -0
  16. package/server/lib/fix-npm-prefix.js +61 -0
  17. package/server/lib/folder-scanner.js +43 -0
  18. package/server/lib/install-tools.js +122 -0
  19. package/server/lib/platform.js +18 -0
  20. package/server/lib/sse-manager.js +36 -0
  21. package/server/lib/terminal.js +95 -0
  22. package/server/lib/validate-folder-path.js +17 -0
  23. package/server/lib/validate-path.js +13 -0
  24. package/server/routes/detect.js +64 -0
  25. package/server/routes/doc-events.js +94 -0
  26. package/server/routes/events.js +37 -0
  27. package/server/routes/folder.js +195 -0
  28. package/server/routes/github.js +21 -0
  29. package/server/routes/health.js +16 -0
  30. package/server/routes/install.js +102 -0
  31. package/server/routes/project.js +18 -0
  32. package/server/routes/scaffold.js +45 -0
  33. package/skills-lock.json +15 -0
  34. package/tsconfig.app.json +17 -0
  35. package/tsconfig.node.json +11 -0
  36. package/tsconfig.tsbuildinfo +1 -0
  37. package/ui/app.js +747 -0
  38. package/ui/index.html +272 -0
  39. package/ui/styles.css +788 -0
package/ui/styles.css ADDED
@@ -0,0 +1,788 @@
1
+ /* ============================================
2
+ GREENHOUSE SETUP WIZARD
3
+ ============================================ */
4
+
5
+ :root {
6
+ --color-bg: #faf9f7;
7
+ --color-surface: #ffffff;
8
+ --color-text: #1a1a2e;
9
+ --color-text-muted: #6b7280;
10
+ --color-green: #22c55e;
11
+ --color-green-light: #dcfce7;
12
+ --color-red: #ef4444;
13
+ --color-red-light: #fef2f2;
14
+ --color-orange: #f59e0b;
15
+ --color-orange-light: #fffbeb;
16
+ --color-border: #e5e7eb;
17
+ --color-primary: #22c55e;
18
+ --color-primary-hover: #16a34a;
19
+ --terminal-bg: #1a1a2e;
20
+ --radius: 12px;
21
+ --radius-sm: 8px;
22
+ }
23
+
24
+ * {
25
+ margin: 0;
26
+ padding: 0;
27
+ box-sizing: border-box;
28
+ }
29
+
30
+ body {
31
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
32
+ background: var(--color-bg);
33
+ color: var(--color-text);
34
+ line-height: 1.6;
35
+ min-height: 100vh;
36
+ }
37
+
38
+ /* ============================================
39
+ SCREENS
40
+ ============================================ */
41
+
42
+ .screen {
43
+ display: none;
44
+ min-height: 100vh;
45
+ }
46
+
47
+ .screen.active {
48
+ display: flex;
49
+ }
50
+
51
+ .screen-inner {
52
+ max-width: 600px;
53
+ width: 100%;
54
+ margin: 0 auto;
55
+ padding: 3rem 1.5rem;
56
+ }
57
+
58
+ .logo {
59
+ font-size: 2.5rem;
60
+ margin-bottom: 0.5rem;
61
+ }
62
+
63
+ .logo-small {
64
+ font-size: 1.25rem;
65
+ }
66
+
67
+ h1 {
68
+ font-size: 1.75rem;
69
+ font-weight: 700;
70
+ margin-bottom: 0.25rem;
71
+ }
72
+
73
+ .subtitle {
74
+ color: var(--color-text-muted);
75
+ margin-bottom: 2rem;
76
+ }
77
+
78
+ /* ============================================
79
+ TOOL LIST
80
+ ============================================ */
81
+
82
+ .tools-list {
83
+ display: flex;
84
+ flex-direction: column;
85
+ gap: 0.5rem;
86
+ margin-bottom: 2rem;
87
+ }
88
+
89
+ .tool-item {
90
+ display: flex;
91
+ align-items: center;
92
+ gap: 0.75rem;
93
+ padding: 0.875rem 1rem;
94
+ background: var(--color-surface);
95
+ border: 1px solid var(--color-border);
96
+ border-radius: var(--radius-sm);
97
+ transition: all 0.2s;
98
+ }
99
+
100
+ .tool-item.installed {
101
+ border-color: var(--color-green-light);
102
+ background: var(--color-green-light);
103
+ }
104
+
105
+ .tool-item.missing {
106
+ border-color: var(--color-border);
107
+ }
108
+
109
+ .tool-item.installing {
110
+ border-color: var(--color-orange);
111
+ background: var(--color-orange-light);
112
+ }
113
+
114
+ .tool-item.error {
115
+ border-color: var(--color-red);
116
+ background: var(--color-red-light);
117
+ }
118
+
119
+ .tool-status {
120
+ font-size: 1.1rem;
121
+ width: 1.5rem;
122
+ text-align: center;
123
+ flex-shrink: 0;
124
+ }
125
+
126
+ .tool-name {
127
+ font-weight: 500;
128
+ flex-grow: 1;
129
+ }
130
+
131
+ .tool-version {
132
+ color: var(--color-text-muted);
133
+ font-size: 0.85rem;
134
+ font-family: 'SF Mono', 'Fira Code', monospace;
135
+ }
136
+
137
+ .tool-action {
138
+ margin-left: auto;
139
+ }
140
+
141
+ @keyframes spin {
142
+ to { transform: rotate(360deg); }
143
+ }
144
+
145
+ .spinner {
146
+ display: inline-block;
147
+ width: 1.1rem;
148
+ height: 1.1rem;
149
+ border: 2px solid var(--color-border);
150
+ border-top-color: var(--color-primary);
151
+ border-radius: 50%;
152
+ animation: spin 0.6s linear infinite;
153
+ }
154
+
155
+ /* ============================================
156
+ BUTTONS
157
+ ============================================ */
158
+
159
+ .actions {
160
+ display: flex;
161
+ gap: 0.75rem;
162
+ margin-top: 1.5rem;
163
+ }
164
+
165
+ .btn {
166
+ display: inline-flex;
167
+ align-items: center;
168
+ justify-content: center;
169
+ gap: 0.5rem;
170
+ padding: 0.75rem 1.5rem;
171
+ border: none;
172
+ border-radius: var(--radius-sm);
173
+ font-size: 1rem;
174
+ font-weight: 600;
175
+ cursor: pointer;
176
+ transition: all 0.15s;
177
+ }
178
+
179
+ .btn:disabled {
180
+ opacity: 0.5;
181
+ cursor: not-allowed;
182
+ }
183
+
184
+ .btn-primary {
185
+ background: var(--color-primary);
186
+ color: white;
187
+ }
188
+
189
+ .btn-primary:hover:not(:disabled) {
190
+ background: var(--color-primary-hover);
191
+ }
192
+
193
+ .btn-secondary {
194
+ background: var(--color-surface);
195
+ color: var(--color-text);
196
+ border: 1px solid var(--color-border);
197
+ }
198
+
199
+ .btn-secondary:hover:not(:disabled) {
200
+ border-color: var(--color-text-muted);
201
+ }
202
+
203
+ .btn-ghost {
204
+ background: transparent;
205
+ color: var(--color-text-muted);
206
+ }
207
+
208
+ .btn-ghost:hover:not(:disabled) {
209
+ color: var(--color-text);
210
+ }
211
+
212
+ .btn-small {
213
+ padding: 0.5rem 1rem;
214
+ font-size: 0.875rem;
215
+ }
216
+
217
+ .btn-block {
218
+ width: 100%;
219
+ }
220
+
221
+ .btn-icon {
222
+ background: none;
223
+ border: 1px solid rgba(255, 255, 255, 0.2);
224
+ color: rgba(255, 255, 255, 0.7);
225
+ width: 2rem;
226
+ height: 2rem;
227
+ display: flex;
228
+ align-items: center;
229
+ justify-content: center;
230
+ border-radius: 6px;
231
+ cursor: pointer;
232
+ font-size: 1rem;
233
+ transition: all 0.15s;
234
+ }
235
+
236
+ .btn-icon:hover {
237
+ background: rgba(255, 255, 255, 0.1);
238
+ color: white;
239
+ }
240
+
241
+ /* ============================================
242
+ ERROR RECOVERY
243
+ ============================================ */
244
+
245
+ .error-recovery {
246
+ margin-top: 1.5rem;
247
+ }
248
+
249
+ .error-card {
250
+ background: var(--color-red-light);
251
+ border: 1px solid var(--color-red);
252
+ border-radius: var(--radius);
253
+ padding: 1.5rem;
254
+ }
255
+
256
+ .error-card h3 {
257
+ color: var(--color-red);
258
+ margin-bottom: 0.5rem;
259
+ }
260
+
261
+ .error-help {
262
+ margin: 1rem 0;
263
+ font-size: 0.9rem;
264
+ }
265
+
266
+ .error-help ul, .error-help ol {
267
+ padding-left: 1.25rem;
268
+ margin: 0.5rem 0;
269
+ }
270
+
271
+ .error-actions {
272
+ display: flex;
273
+ gap: 0.75rem;
274
+ margin: 1rem 0;
275
+ }
276
+
277
+ .error-details {
278
+ margin-top: 1rem;
279
+ font-size: 0.8rem;
280
+ }
281
+
282
+ .error-details summary {
283
+ cursor: pointer;
284
+ color: var(--color-text-muted);
285
+ }
286
+
287
+ .error-details pre {
288
+ margin-top: 0.5rem;
289
+ padding: 0.75rem;
290
+ background: var(--color-text);
291
+ color: #e0e0e0;
292
+ border-radius: var(--radius-sm);
293
+ overflow-x: auto;
294
+ font-size: 0.75rem;
295
+ font-family: 'SF Mono', 'Fira Code', monospace;
296
+ }
297
+
298
+ /* ============================================
299
+ SETUP SCREEN (combined tool check + intent)
300
+ ============================================ */
301
+
302
+ .intent-input-group {
303
+ display: flex;
304
+ gap: 0.75rem;
305
+ margin-bottom: 1.5rem;
306
+ }
307
+
308
+ .intent-input-group input {
309
+ flex: 1;
310
+ padding: 0.875rem 1rem;
311
+ border: 2px solid var(--color-border);
312
+ border-radius: var(--radius-sm);
313
+ font-size: 1rem;
314
+ font-family: inherit;
315
+ transition: border-color 0.2s;
316
+ }
317
+
318
+ .intent-input-group input:focus {
319
+ outline: none;
320
+ border-color: var(--color-primary);
321
+ box-shadow: 0 0 0 3px var(--color-green-light);
322
+ }
323
+
324
+ .intent-examples {
325
+ display: flex;
326
+ flex-wrap: wrap;
327
+ gap: 0.5rem;
328
+ align-items: center;
329
+ margin-bottom: 2rem;
330
+ }
331
+
332
+ .examples-label {
333
+ font-size: 0.8rem;
334
+ color: var(--color-text-muted);
335
+ }
336
+
337
+ .example-btn {
338
+ padding: 0.25rem 0.75rem;
339
+ border: 1px solid var(--color-border);
340
+ border-radius: 100px;
341
+ background: var(--color-surface);
342
+ font-size: 0.8rem;
343
+ font-family: inherit;
344
+ color: var(--color-text-muted);
345
+ cursor: pointer;
346
+ transition: all 0.15s;
347
+ }
348
+
349
+ .example-btn:hover {
350
+ border-color: var(--color-primary);
351
+ color: var(--color-text);
352
+ }
353
+
354
+ /* ============================================
355
+ PATH SELECTION
356
+ ============================================ */
357
+
358
+ .path-options {
359
+ display: flex;
360
+ flex-direction: column;
361
+ gap: 0.75rem;
362
+ margin-bottom: 2rem;
363
+ }
364
+
365
+ .path-card {
366
+ display: flex;
367
+ align-items: center;
368
+ gap: 1rem;
369
+ padding: 1.25rem 1.5rem;
370
+ background: var(--color-surface);
371
+ border: 2px solid var(--color-border);
372
+ border-radius: var(--radius);
373
+ cursor: pointer;
374
+ text-align: left;
375
+ font-family: inherit;
376
+ transition: all 0.15s;
377
+ }
378
+
379
+ .path-card:hover {
380
+ border-color: var(--color-primary);
381
+ box-shadow: 0 2px 8px rgba(34, 197, 94, 0.1);
382
+ }
383
+
384
+ .path-icon {
385
+ font-size: 1.75rem;
386
+ flex-shrink: 0;
387
+ }
388
+
389
+ .path-title {
390
+ display: block;
391
+ font-size: 1.1rem;
392
+ font-weight: 600;
393
+ color: var(--color-text);
394
+ }
395
+
396
+ .path-desc {
397
+ display: block;
398
+ font-size: 0.85rem;
399
+ color: var(--color-text-muted);
400
+ margin-top: 0.15rem;
401
+ }
402
+
403
+ .btn-back {
404
+ background: none;
405
+ border: none;
406
+ color: var(--color-text-muted);
407
+ font-size: 0.9rem;
408
+ cursor: pointer;
409
+ padding: 0;
410
+ margin-bottom: 1rem;
411
+ font-family: inherit;
412
+ }
413
+
414
+ .btn-back:hover {
415
+ color: var(--color-text);
416
+ }
417
+
418
+ .path-hint {
419
+ font-size: 0.8rem;
420
+ color: var(--color-text-muted);
421
+ margin-top: 0.75rem;
422
+ }
423
+
424
+ .drive-shortcuts {
425
+ margin-top: 1.5rem;
426
+ padding-top: 1.5rem;
427
+ border-top: 1px solid var(--color-border);
428
+ }
429
+
430
+ .drive-list {
431
+ display: flex;
432
+ flex-wrap: wrap;
433
+ gap: 0.5rem;
434
+ margin-top: 0.75rem;
435
+ }
436
+
437
+ .drive-btn {
438
+ display: inline-flex;
439
+ align-items: center;
440
+ gap: 0.4rem;
441
+ padding: 0.5rem 1rem;
442
+ border: 1px solid var(--color-border);
443
+ border-radius: var(--radius-sm);
444
+ background: var(--color-surface);
445
+ font-size: 0.85rem;
446
+ font-family: inherit;
447
+ color: var(--color-text);
448
+ cursor: pointer;
449
+ transition: all 0.15s;
450
+ }
451
+
452
+ .drive-btn:hover {
453
+ border-color: var(--color-primary);
454
+ background: var(--color-green-light);
455
+ }
456
+
457
+ .drive-icon {
458
+ font-size: 1.1rem;
459
+ }
460
+
461
+ .step-heading {
462
+ font-size: 1.25rem;
463
+ font-weight: 700;
464
+ margin-bottom: 0.25rem;
465
+ margin-top: 0.5rem;
466
+ }
467
+
468
+ .tools-status {
469
+ padding-top: 1.5rem;
470
+ border-top: 1px solid var(--color-border);
471
+ }
472
+
473
+ .tools-list-inline {
474
+ display: flex;
475
+ flex-wrap: wrap;
476
+ gap: 1rem;
477
+ font-size: 0.85rem;
478
+ }
479
+
480
+ .tool-check {
481
+ display: inline-flex;
482
+ align-items: center;
483
+ gap: 0.35rem;
484
+ color: var(--color-text-muted);
485
+ }
486
+
487
+ .tool-install {
488
+ display: inline-flex;
489
+ align-items: center;
490
+ }
491
+
492
+ .spinner-small {
493
+ display: inline-block;
494
+ width: 0.85rem;
495
+ height: 0.85rem;
496
+ border: 2px solid var(--color-border);
497
+ border-top-color: var(--color-primary);
498
+ border-radius: 50%;
499
+ animation: spin 0.6s linear infinite;
500
+ }
501
+
502
+ /* ============================================
503
+ SCREEN 3: BUILD
504
+ ============================================ */
505
+
506
+ .build-layout {
507
+ display: flex;
508
+ height: 100vh;
509
+ width: 100%;
510
+ }
511
+
512
+ .build-sidebar {
513
+ width: 300px;
514
+ flex-shrink: 0;
515
+ background: white;
516
+ border-right: 1px solid var(--color-border);
517
+ overflow-y: auto;
518
+ display: flex;
519
+ flex-direction: column;
520
+ }
521
+
522
+ .build-header {
523
+ display: flex;
524
+ align-items: center;
525
+ gap: 8px;
526
+ padding: 16px;
527
+ font-weight: 700;
528
+ font-size: 16px;
529
+ border-bottom: 1px solid var(--color-border);
530
+ }
531
+
532
+ .sidebar-section {
533
+ padding: 16px;
534
+ border-bottom: 1px solid var(--color-border);
535
+ }
536
+
537
+ .sidebar-section h4 {
538
+ font-size: 11px;
539
+ text-transform: uppercase;
540
+ letter-spacing: 1px;
541
+ color: var(--color-text-muted);
542
+ margin: 0 0 12px 0;
543
+ font-weight: 600;
544
+ }
545
+
546
+ .sidebar-section a {
547
+ display: block;
548
+ color: var(--color-green);
549
+ text-decoration: none;
550
+ font-size: 13px;
551
+ padding: 4px 0;
552
+ }
553
+
554
+ .sidebar-section a:hover {
555
+ text-decoration: underline;
556
+ }
557
+
558
+ .project-path {
559
+ font-family: 'SF Mono', 'Fira Code', monospace;
560
+ font-size: 13px;
561
+ color: var(--color-text-muted);
562
+ margin: 0 0 8px 0;
563
+ word-break: break-all;
564
+ }
565
+
566
+ .project-actions {
567
+ display: flex;
568
+ flex-direction: column;
569
+ gap: 6px;
570
+ }
571
+
572
+ .repo-list {
573
+ background: white;
574
+ border: 1px solid var(--color-border);
575
+ border-radius: 8px;
576
+ max-height: 200px;
577
+ overflow-y: auto;
578
+ margin-top: 8px;
579
+ }
580
+
581
+ .repo-list-header {
582
+ display: flex;
583
+ justify-content: space-between;
584
+ align-items: center;
585
+ padding: 8px 12px;
586
+ border-bottom: 1px solid var(--color-border);
587
+ font-weight: 600;
588
+ font-size: 13px;
589
+ }
590
+
591
+ .repo-item {
592
+ display: block;
593
+ width: 100%;
594
+ text-align: left;
595
+ padding: 8px 12px;
596
+ border: none;
597
+ background: none;
598
+ cursor: pointer;
599
+ font-size: 13px;
600
+ font-family: inherit;
601
+ }
602
+
603
+ .repo-item:hover {
604
+ background: var(--color-bg);
605
+ }
606
+
607
+ .prompt-group {
608
+ margin-bottom: 4px;
609
+ }
610
+
611
+ .prompt-group summary {
612
+ font-weight: 600;
613
+ font-size: 13px;
614
+ cursor: pointer;
615
+ padding: 6px 0;
616
+ list-style-position: inside;
617
+ color: var(--color-text);
618
+ }
619
+
620
+ .prompt-group summary:hover {
621
+ color: var(--color-green);
622
+ }
623
+
624
+ .prompt-list {
625
+ display: flex;
626
+ flex-direction: column;
627
+ gap: 4px;
628
+ padding: 4px 0 8px;
629
+ }
630
+
631
+ .prompt-btn {
632
+ display: block;
633
+ width: 100%;
634
+ text-align: left;
635
+ padding: 8px 10px;
636
+ border: 1px solid var(--color-border);
637
+ border-radius: 6px;
638
+ background: white;
639
+ cursor: pointer;
640
+ font-size: 12px;
641
+ font-family: inherit;
642
+ color: var(--color-text);
643
+ transition: background 0.2s;
644
+ }
645
+
646
+ .prompt-btn:hover {
647
+ background: var(--color-bg);
648
+ }
649
+
650
+ .prompt-btn.prompt-sent {
651
+ background: rgba(74, 222, 128, 0.2);
652
+ }
653
+
654
+
655
+ /* Terminal area */
656
+ .build-terminal {
657
+ flex: 1;
658
+ display: flex;
659
+ flex-direction: column;
660
+ background: #1a1a2e;
661
+ min-width: 0;
662
+ }
663
+
664
+ .terminal-toolbar {
665
+ display: flex;
666
+ align-items: center;
667
+ justify-content: space-between;
668
+ padding: 8px 16px;
669
+ background: #12121f;
670
+ border-bottom: 1px solid #2a2a3e;
671
+ }
672
+
673
+ .terminal-title {
674
+ font-size: 13px;
675
+ color: #888;
676
+ font-weight: 500;
677
+ }
678
+
679
+ .terminal-controls {
680
+ display: flex;
681
+ gap: 4px;
682
+ }
683
+
684
+ #terminal-container {
685
+ flex: 1;
686
+ padding: 8px;
687
+ overflow: hidden;
688
+ }
689
+
690
+ #terminal-fallback {
691
+ flex: 1;
692
+ display: flex;
693
+ flex-direction: column;
694
+ align-items: center;
695
+ justify-content: center;
696
+ gap: 12px;
697
+ color: #888;
698
+ }
699
+
700
+ /* Live Preview */
701
+ .build-preview {
702
+ display: flex;
703
+ flex-direction: column;
704
+ background: white;
705
+ flex: 0 0 35%;
706
+ border-left: 1px solid #2a2a3e;
707
+ }
708
+
709
+ .build-preview.hidden {
710
+ display: none;
711
+ }
712
+
713
+ .preview-toolbar {
714
+ display: flex;
715
+ align-items: center;
716
+ justify-content: space-between;
717
+ padding: 8px 16px;
718
+ background: #12121f;
719
+ border-bottom: 1px solid #2a2a3e;
720
+ }
721
+
722
+ .preview-url {
723
+ font-size: 13px;
724
+ color: #888;
725
+ font-family: 'SF Mono', monospace;
726
+ }
727
+
728
+ .preview-container {
729
+ flex: 1;
730
+ position: relative;
731
+ }
732
+
733
+ .preview-placeholder {
734
+ display: flex;
735
+ flex-direction: column;
736
+ align-items: center;
737
+ justify-content: center;
738
+ height: 100%;
739
+ gap: 12px;
740
+ color: var(--color-text-muted);
741
+ }
742
+
743
+ #preview-iframe {
744
+ width: 100%;
745
+ height: 100%;
746
+ border: none;
747
+ }
748
+
749
+ /* Sidebar hidden state */
750
+ .build-sidebar.hidden {
751
+ display: none;
752
+ }
753
+
754
+ /* Collapsed sidebar toggle tab */
755
+ .sidebar-toggle-tab {
756
+ position: absolute;
757
+ left: 0;
758
+ top: 50%;
759
+ transform: translateY(-50%);
760
+ width: 24px;
761
+ height: 48px;
762
+ background: white;
763
+ border: 1px solid var(--color-border);
764
+ border-left: none;
765
+ border-radius: 0 6px 6px 0;
766
+ cursor: pointer;
767
+ display: flex;
768
+ align-items: center;
769
+ justify-content: center;
770
+ font-size: 12px;
771
+ color: var(--color-text-muted);
772
+ z-index: 10;
773
+ transition: background 0.15s;
774
+ }
775
+
776
+ .sidebar-toggle-tab:hover {
777
+ background: var(--color-bg);
778
+ color: var(--color-text);
779
+ }
780
+
781
+ .sidebar-toggle-tab.hidden {
782
+ display: none;
783
+ }
784
+
785
+ .text-muted {
786
+ color: var(--color-text-muted);
787
+ font-size: 0.8rem;
788
+ }