add runner tab
Seto Elkahfi committed
Jun 11, 2025 at 16:12 UTC
d1e6ec4975b8bf2d388af037371f853658ce4779
2 files changed
+89
-28
app/components/TabbedRunner.tsx
new
+87
@@ -0,0 +1,87 @@
1
+"use client"
2
+
3
+import { JSX, useState } from "react";
4
+
5
+const runnerSnippets = {
6
+ NodeJS: `$ smb
7
+✔ Valid config
8
+✔ NodeJs 🟩 runner detected
9
+✔ Valid project
10
+✔ Valid deployment setup
11
+☱ Deploying > Use key path: ~/.ssh/id_11@smbcloud
12
+☱ Deploying > Building the app ✔
13
+☲ Deploying > App restart ✔
14
+☱ Deploying > App is running ✔
15
+✔ Deployment complete.`,
16
+ Ruby: `$ smb
17
+✔ Valid config
18
+✔ Ruby 🟥 runner detected (coming soon)
19
+✔ Valid project
20
+✔ Valid deployment setup
21
+☱ Deploying > Use key path: ~/.ssh/id_11@smbcloud
22
+☱ Deploying > Building the app ✔
23
+☲ Deploying > App restart ✔
24
+☱ Deploying > App is running ✔
25
+✔ Deployment complete.`,
26
+ Swift: `$ smb
27
+✔ Valid config
28
+✔ Swift 🟧 runner detected (coming soon)
29
+✔ Valid project
30
+✔ Valid deployment setup
31
+☱ Deploying > Use key path: ~/.ssh/id_11@smbcloud
32
+☱ Deploying > Building the app ✔
33
+☲ Deploying > App restart ✔
34
+☱ Deploying > App is running ✔
35
+✔ Deployment complete.`
36
+};
37
+
38
+export default function TabbedRunner() {
39
+ const [tab, setTab] = useState<keyof typeof runnerSnippets>('NodeJS');
40
+ const tabs: { key: keyof typeof runnerSnippets; label: string }[] = [
41
+ { key: 'NodeJS', label: 'NodeJS' },
42
+ { key: 'Ruby', label: 'Ruby (coming soon)' },
43
+ { key: 'Swift', label: 'Swift (coming soon)' }
44
+ ];
45
+ return (
46
+ <div>
47
+ <div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
48
+ {tabs.map(t => (
49
+ <button
50
+ key={t.key}
51
+ onClick={() => setTab(t.key)}
52
+ style={{
53
+ border: 'none',
54
+ background: tab === t.key ? '#222' : '#eee',
55
+ color: tab === t.key ? '#fff' : '#222',
56
+ padding: '4px 12px',
57
+ borderRadius: 4,
58
+ cursor: 'pointer',
59
+ fontWeight: tab === t.key ? 'bold' : 'normal'
60
+ }}
61
+ >
62
+ {t.label}
63
+ </button>
64
+ ))}
65
+ </div>
66
+ <pre>
67
+ {
68
+ runnerSnippets[tab]
69
+ .split('\n')
70
+ .map((line, idx) => (
71
+ <span key={idx}>
72
+ {line.split('✔').reduce((acc, part, i, arr) => {
73
+ if (i === arr.length - 1) return [...acc, part];
74
+ return [
75
+ ...acc,
76
+ part,
77
+ <span key={`check-${i}`} style={{ color: 'green' }}>✔</span>
78
+ ];
79
+ }, [] as (string | JSX.Element)[])}
80
+ {'\n'}
81
+ </span>
82
+ ))
83
+ }
84
+ </pre>
85
+ </div>
86
+ );
87
+}
app/page.tsx
+2
-28
@@ -2,7 +2,7 @@ import { allPosts } from "@/.contentlayer/generated";
2
import Link from "next/link";
3
import { genPageMetadata } from "./seo";
4
import siteMetadata from '@/content/siteMetadata'
5
-import { JSX } from "react";
5
+import TabbedRunner from "./components/TabbedRunner";
6
7
export const metadata = genPageMetadata({ title: `${siteMetadata.title}` })
8
@@ -13,33 +13,7 @@ export default function Home() {
13
<div className="prose dark:prose-invert">
14
<h1>smbCloud</h1>
15
<p className="text-lg">Deploy your NextJS app with one command: </p>
16
- <pre>
17
- {
18
- `$ smb
19
-✔ Valid config
20
-✔ Valid project
21
-✔ Valid deployment setup
22
-☱ Deploying > Use key path: ~/.ssh/id_11@smbcloud
23
-☱ Deploying > Building the app ✔
24
-☲ Deploying > App restart ✔
25
-☱ Deploying > App is running ✔
26
-✔ Deployment complete.`
27
- .split('\n')
28
- .map((line, idx) => (
29
- <span key={idx}>
30
- {line.split('✔').reduce((acc, part, i, arr) => {
31
- if (i === arr.length - 1) return [...acc, part];
32
- return [
33
- ...acc,
34
- part,
35
- <span key={`check-${i}`} style={{ color: 'green' }}>✔</span>
36
- ];
37
- }, [] as (string | JSX.Element)[])}
38
- {'\n'}
39
- </span>
40
- ))
41
- }
42
- </pre>
16
+ <TabbedRunner />
17
<hr />
18
<h2>Resources</h2>
19
{publishedPosts.map((post) => (