Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol.
wisp.place
1import {
2 Card,
3 CardContent,
4 CardDescription,
5 CardHeader,
6 CardTitle,
7} from "@public/components/ui/card";
8import { Badge } from "@public/components/ui/badge";
9import { ExternalLink } from "lucide-react";
10import { CodeBlock } from "@public/components/ui/code-block";
11
12export function CLITab() {
13 return (
14 <div className="space-y-4 min-h-[400px]">
15 <Card>
16 <CardHeader>
17 <div className="flex items-center gap-2 mb-2">
18 <CardTitle>Wisp CLI Tool</CardTitle>
19 <Badge variant="secondary" className="text-xs">
20 v0.2.0
21 </Badge>
22 <Badge variant="outline" className="text-xs">
23 Alpha
24 </Badge>
25 </div>
26 <CardDescription>
27 Deploy static sites directly from your terminal
28 </CardDescription>
29 </CardHeader>
30 <CardContent className="space-y-6">
31 <div className="prose prose-sm max-w-none dark:prose-invert">
32 <p className="text-sm text-muted-foreground">
33 The Wisp CLI is a command-line tool for deploying static websites
34 directly to your AT Protocol account. Authenticate with app
35 password or OAuth and deploy from CI/CD pipelines.
36 </p>
37 </div>
38
39 <div className="space-y-3">
40 <h3 className="text-sm font-semibold">Features</h3>
41 <ul className="text-sm text-muted-foreground space-y-2 list-disc list-inside">
42 <li>
43 <strong>Deploy:</strong> Push static sites directly from your
44 terminal
45 </li>
46 <li>
47 <strong>Pull:</strong> Download sites from the PDS for
48 development or backup
49 </li>
50 <li>
51 <strong>Serve:</strong> Run a local server with real-time
52 firehose updates
53 </li>
54 </ul>
55 </div>
56
57 <div className="space-y-3">
58 <h3 className="text-sm font-semibold">Download v0.2.0</h3>
59 <div className="grid gap-2">
60 <div className="p-3 bg-muted/50 hover:bg-muted rounded-lg transition-colors border border-border">
61 <a
62 href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-darwin"
63 target="_blank"
64 rel="noopener noreferrer"
65 className="flex items-center justify-between mb-2"
66 >
67 <span className="font-mono text-sm">
68 macOS (Apple Silicon)
69 </span>
70 <ExternalLink className="w-4 h-4 text-muted-foreground" />
71 </a>
72 <div className="text-xs text-muted-foreground">
73 <span className="font-mono">
74 SHA-1: 9281454860f2eb07b39b80f7a9cc8e9bdcff491b
75 </span>
76 </div>
77 </div>
78 <div className="p-3 bg-muted/50 hover:bg-muted rounded-lg transition-colors border border-border">
79 <a
80 href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-linux"
81 target="_blank"
82 rel="noopener noreferrer"
83 className="flex items-center justify-between mb-2"
84 >
85 <span className="font-mono text-sm">Linux (ARM64)</span>
86 <ExternalLink className="w-4 h-4 text-muted-foreground" />
87 </a>
88 <div className="text-xs text-muted-foreground">
89 <span className="font-mono">
90 SHA-1: d460863150c4c162b7e7e3801a67746da3aaf9d9
91 </span>
92 </div>
93 </div>
94 <div className="p-3 bg-muted/50 hover:bg-muted rounded-lg transition-colors border border-border">
95 <a
96 href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux"
97 target="_blank"
98 rel="noopener noreferrer"
99 className="flex items-center justify-between mb-2"
100 >
101 <span className="font-mono text-sm">Linux (x86_64)</span>
102 <ExternalLink className="w-4 h-4 text-muted-foreground" />
103 </a>
104 <div className="text-xs text-muted-foreground">
105 <span className="font-mono">
106 SHA-1: 94968abed20422df826b78c38cb506dd4b1b5885
107 </span>
108 </div>
109 </div>
110 <div className="p-3 bg-muted/50 hover:bg-muted rounded-lg transition-colors border border-border">
111 <a
112 href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-windows.exe"
113 target="_blank"
114 rel="noopener noreferrer"
115 className="flex items-center justify-between mb-2"
116 >
117 <span className="font-mono text-sm">Windows (x86_64)</span>
118 <ExternalLink className="w-4 h-4 text-muted-foreground" />
119 </a>
120 <div className="text-xs text-muted-foreground">
121 <span className="font-mono">
122 SHA-1: 45293e47da38b97ef35258a08cb2682eee64a659
123 </span>
124 </div>
125 </div>
126 </div>
127 </div>
128
129 <div className="space-y-3">
130 <h3 className="text-sm font-semibold">Deploy a Site</h3>
131 <CodeBlock
132 code={`# Download and make executable
133curl -O https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-darwin
134chmod +x wisp-cli-aarch64-darwin
135
136# Deploy your site
137./wisp-cli-aarch64-darwin deploy your-handle.bsky.social \\
138 --path ./dist \\
139 --site my-site \\
140 --password your-app-password
141
142# Your site will be available at:
143# https://sites.wisp.place/your-handle/my-site`}
144 language="bash"
145 />
146 </div>
147
148 <div className="space-y-3">
149 <h3 className="text-sm font-semibold">Pull a Site from PDS</h3>
150 <p className="text-xs text-muted-foreground">
151 Download a site from the PDS to your local machine (uses OAuth
152 authentication):
153 </p>
154 <CodeBlock
155 code={`# Pull a site to a specific directory
156wisp-cli pull your-handle.bsky.social \\
157 --site my-site \\
158 --output ./my-site
159
160# Pull to current directory
161wisp-cli pull your-handle.bsky.social \\
162 --site my-site
163
164# Opens browser for OAuth authentication on first run`}
165 language="bash"
166 />
167 </div>
168
169 <div className="space-y-3">
170 <h3 className="text-sm font-semibold">
171 Serve a Site Locally with Real-Time Updates
172 </h3>
173 <p className="text-xs text-muted-foreground">
174 Run a local server that monitors the firehose for real-time
175 updates (uses OAuth authentication):
176 </p>
177 <CodeBlock
178 code={`# Serve on http://localhost:8080 (default)
179wisp-cli serve your-handle.bsky.social \\
180 --site my-site
181
182# Serve on a custom port
183wisp-cli serve your-handle.bsky.social \\
184 --site my-site \\
185 --port 3000
186
187# Downloads site, serves it, and watches firehose for live updates!`}
188 language="bash"
189 />
190 </div>
191
192 <div className="space-y-3">
193 <h3 className="text-sm font-semibold">
194 CI/CD with Tangled Spindle
195 </h3>
196 <p className="text-xs text-muted-foreground">
197 Deploy automatically on every push using{" "}
198 <a
199 href="https://blog.tangled.org/ci"
200 target="_blank"
201 rel="noopener noreferrer"
202 className="text-accent hover:underline"
203 >
204 Tangled Spindle
205 </a>
206 </p>
207
208 <div className="space-y-4">
209 <div>
210 <h4 className="text-xs font-semibold mb-2 flex items-center gap-2">
211 <span>Example 1: Simple Asset Publishing</span>
212 <Badge variant="secondary" className="text-xs">
213 Copy Files
214 </Badge>
215 </h4>
216 <CodeBlock
217 code={`when:
218 - event: ['push']
219 branch: ['main']
220 - event: ['manual']
221
222engine: 'nixery'
223
224clone:
225 skip: false
226 depth: 1
227
228dependencies:
229 nixpkgs:
230 - coreutils
231 - curl
232
233environment:
234 SITE_PATH: '.' # Copy entire repo
235 SITE_NAME: 'myWebbedSite'
236 WISP_HANDLE: 'your-handle.bsky.social'
237
238steps:
239 - name: deploy assets to wisp
240 command: |
241 # Download Wisp CLI
242 curl https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux -o wisp-cli
243 chmod +x wisp-cli
244
245 # Deploy to Wisp
246 ./wisp-cli deploy \\
247 "$WISP_HANDLE" \\
248 --path "$SITE_PATH" \\
249 --site "$SITE_NAME" \\
250 --password "$WISP_APP_PASSWORD"
251
252 # Output
253 #Deployed site 'myWebbedSite': at://did:plc:ttdrpj45ibqunmfhdsb4zdwq/place.wisp.fs/myWebbedSite
254 #Available at: https://sites.wisp.place/did:plc:ttdrpj45ibqunmfhdsb4zdwq/myWebbedSite
255 `}
256 language="yaml"
257 />
258 </div>
259
260 <div>
261 <h4 className="text-xs font-semibold mb-2 flex items-center gap-2">
262 <span>Example 2: React/Vite Build & Deploy</span>
263 <Badge variant="secondary" className="text-xs">
264 Full Build
265 </Badge>
266 </h4>
267 <CodeBlock
268 code={`when:
269 - event: ['push']
270 branch: ['main']
271 - event: ['manual']
272
273engine: 'nixery'
274
275clone:
276 skip: false
277 depth: 1
278 submodules: false
279
280dependencies:
281 nixpkgs:
282 - nodejs
283 - coreutils
284 - curl
285 github:NixOS/nixpkgs/nixpkgs-unstable:
286 - bun
287
288environment:
289 SITE_PATH: 'dist'
290 SITE_NAME: 'my-react-site'
291 WISP_HANDLE: 'your-handle.bsky.social'
292
293steps:
294 - name: build site
295 command: |
296 # necessary to ensure bun is in PATH
297 export PATH="$HOME/.nix-profile/bin:$PATH"
298
299 bun install --frozen-lockfile
300
301 # build with vite, run directly to get around env issues
302 bun node_modules/.bin/vite build
303
304 - name: deploy to wisp
305 command: |
306 # Download Wisp CLI
307 curl https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux -o wisp-cli
308 chmod +x wisp-cli
309
310 # Deploy to Wisp
311 ./wisp-cli deploy \\
312 "$WISP_HANDLE" \\
313 --path "$SITE_PATH" \\
314 --site "$SITE_NAME" \\
315 --password "$WISP_APP_PASSWORD"`}
316 language="yaml"
317 />
318 </div>
319 </div>
320
321 <div className="p-3 bg-muted/30 rounded-lg border-l-4 border-accent">
322 <p className="text-xs text-muted-foreground">
323 <strong className="text-foreground">Note:</strong> Set{" "}
324 <code className="px-1.5 py-0.5 bg-background rounded text-xs">
325 WISP_APP_PASSWORD
326 </code>{" "}
327 as a secret in your Tangled Spindle repository settings.
328 Generate an app password from your AT Protocol account settings.
329 </p>
330 </div>
331 </div>
332
333 <div className="space-y-3">
334 <h3 className="text-sm font-semibold">Learn More</h3>
335 <div className="grid gap-2">
336 <a
337 href="https://docs.wisp.place/cli"
338 target="_blank"
339 rel="noopener noreferrer"
340 className="flex items-center justify-between p-3 bg-muted/50 hover:bg-muted rounded-lg transition-colors border border-border"
341 >
342 <span className="text-sm">CLI Documentation</span>
343 <ExternalLink className="w-4 h-4 text-muted-foreground" />
344 </a>
345 <a
346 href="https://tangled.org/@nekomimi.pet/wisp.place-monorepo/tree/main/cli"
347 target="_blank"
348 rel="noopener noreferrer"
349 className="flex items-center justify-between p-3 bg-muted/50 hover:bg-muted rounded-lg transition-colors border border-border"
350 >
351 <span className="text-sm">Source Code</span>
352 <ExternalLink className="w-4 h-4 text-muted-foreground" />
353 </a>
354 <a
355 href="https://blog.tangled.org/ci"
356 target="_blank"
357 rel="noopener noreferrer"
358 className="flex items-center justify-between p-3 bg-muted/50 hover:bg-muted rounded-lg transition-colors border border-border"
359 >
360 <span className="text-sm">Tangled Spindle CI/CD</span>
361 <ExternalLink className="w-4 h-4 text-muted-foreground" />
362 </a>
363 </div>
364 </div>
365 </CardContent>
366 </Card>
367 </div>
368 );
369}