Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol.
wisp.place
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Wisp CLI - Download</title>
7 <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css" rel="stylesheet" />
8 <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet" media="(prefers-color-scheme: dark)" />
9 <style>
10 :root {
11 /* Light theme */
12 --demo-bg: #eeeeee;
13 --demo-text: #1a1a1a;
14 --demo-text-secondary: #666;
15 --demo-border: #ddd;
16 --demo-input-bg: #fff;
17 --demo-button-bg: #0066cc;
18 --demo-button-text: #fff;
19 --demo-code-bg: #f5f5f5;
20 --demo-code-border: #e0e0e0;
21 --demo-hr: #e0e0e0;
22 }
23
24 /* Dark theme */
25 @media (prefers-color-scheme: dark) {
26 :root {
27 --demo-bg: #1a1a1a;
28 --demo-text: #e0e0e0;
29 --demo-text-secondary: #999;
30 --demo-border: #444;
31 --demo-input-bg: #2a2a2a;
32 --demo-button-bg: #0066cc;
33 --demo-button-text: #fff;
34 --demo-code-bg: #2a2a2a;
35 --demo-code-border: #444;
36 --demo-hr: #444;
37 }
38 }
39
40 * {
41 margin: 0;
42 padding: 0;
43 box-sizing: border-box;
44 }
45
46 body {
47 margin: 0;
48 padding: 0;
49 background: var(--demo-bg);
50 color: var(--demo-text);
51 transition: background-color 200ms ease, color 200ms ease;
52 font-family: system-ui, sans-serif;
53 line-height: 1.6;
54 }
55
56 .container {
57 max-width: 860px;
58 margin: 40px auto;
59 padding: 0 20px;
60 min-height: 100vh;
61 }
62
63 h1 {
64 margin-top: 0;
65 color: var(--demo-text);
66 font-size: 2.5rem;
67 margin-bottom: 0.5rem;
68 }
69
70 .subtitle {
71 color: var(--demo-text-secondary);
72 font-size: 1.1rem;
73 margin-bottom: 2rem;
74 line-height: 1.4;
75 }
76
77 .description {
78 margin-bottom: 2rem;
79 line-height: 1.6;
80 color: var(--demo-text);
81 }
82
83 hr {
84 margin: 32px 0;
85 border: none;
86 border-top: 1px solid var(--demo-hr);
87 }
88
89 h2 {
90 color: var(--demo-text);
91 margin-bottom: 1rem;
92 margin-top: 2rem;
93 font-size: 1.5rem;
94 }
95
96 h3 {
97 color: var(--demo-text);
98 margin-bottom: 0.75rem;
99 margin-top: 1.5rem;
100 font-size: 1.2rem;
101 }
102
103 .downloads {
104 background: var(--demo-code-bg);
105 border: 1px solid var(--demo-code-border);
106 border-radius: 8px;
107 padding: 2rem;
108 margin-bottom: 2rem;
109 }
110
111 .downloads h2 {
112 margin-top: 0;
113 }
114
115 .download-link {
116 display: block;
117 background: var(--demo-button-bg);
118 color: var(--demo-button-text);
119 text-decoration: none;
120 padding: 12px 16px;
121 border-radius: 8px;
122 margin-bottom: 8px;
123 transition: opacity 0.2s;
124 font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
125 font-size: 0.9rem;
126 }
127
128 .download-link:hover {
129 opacity: 0.85;
130 }
131
132 .platform {
133 font-weight: bold;
134 margin-right: 0.5rem;
135 }
136
137 .cicd-section {
138 margin-top: 2rem;
139 }
140
141 .cicd-section h2 {
142 margin-top: 0;
143 }
144
145 .cicd-section > p {
146 color: var(--demo-text-secondary);
147 margin-bottom: 1rem;
148 }
149
150 pre {
151 background: var(--demo-code-bg) !important;
152 border: 1px solid var(--demo-code-border);
153 padding: 1.5rem !important;
154 border-radius: 8px;
155 overflow-x: auto;
156 font-size: 0.85rem;
157 line-height: 1.5;
158 margin: 1rem 0;
159 }
160
161 pre code {
162 color: var(--demo-text);
163 background: none !important;
164 padding: 0 !important;
165 text-shadow: none !important;
166 }
167
168 code {
169 font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
170 }
171
172 .note {
173 background: var(--demo-code-bg);
174 border-left: 4px solid var(--demo-button-bg);
175 border: 1px solid var(--demo-code-border);
176 border-left: 4px solid var(--demo-button-bg);
177 padding: 1rem;
178 margin-top: 1rem;
179 border-radius: 4px;
180 }
181
182 .note strong {
183 color: var(--demo-text);
184 }
185
186 .note code {
187 background: var(--demo-input-bg);
188 padding: 2px 6px;
189 border-radius: 4px;
190 border: 1px solid var(--demo-border);
191 }
192
193 a {
194 color: var(--demo-button-bg);
195 text-decoration: none;
196 }
197
198 a:hover {
199 text-decoration: underline;
200 }
201
202 .features {
203 margin: 2rem 0;
204 }
205
206 .features ul {
207 list-style: none;
208 padding-left: 0;
209 }
210
211 .features li {
212 padding: 0.5rem 0;
213 padding-left: 1.5rem;
214 position: relative;
215 line-height: 1.6;
216 }
217
218 .features li:before {
219 content: "✓";
220 position: absolute;
221 left: 0;
222 color: var(--demo-button-bg);
223 font-weight: bold;
224 }
225
226 .footer {
227 margin-top: 3rem;
228 padding-top: 2rem;
229 border-top: 1px solid var(--demo-hr);
230 text-align: center;
231 color: var(--demo-text-secondary);
232 }
233 </style>
234</head>
235<body>
236 <div class="container">
237 <h1>Wisp CLI <span style="font-size: 1.5rem; color: var(--demo-text-secondary);">v0.4.1</span></h1>
238 <p class="subtitle">Deploy static sites to the AT Protocol</p>
239
240 <div class="description">
241 <p>
242 The Wisp CLI is a command-line tool for deploying static websites directly to your AT Protocol account.
243 Host your sites on <a href="https://wisp.place" target="_blank">wisp.place</a> with full ownership and control,
244 backed by the decentralized AT Protocol.
245 </p>
246 </div>
247
248 <div class="features">
249 <h2>Features</h2>
250 <ul>
251 <li><strong>Deploy:</strong> Push static sites directly from your terminal</li>
252 <li><strong>Pull:</strong> Download sites from the PDS for development or backup</li>
253 <li><strong>Serve:</strong> Run a local server with real-time firehose updates</li>
254 <li>Authenticate with app password or OAuth</li>
255 </ul>
256 </div>
257
258 <div class="downloads">
259 <h2>Download v0.4.1</h2>
260 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-darwin" class="download-link" download>
261 <span class="platform">macOS (Apple Silicon):</span> wisp-cli-aarch64-darwin
262 </a>
263 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-linux" class="download-link" download>
264 <span class="platform">Linux (ARM64):</span> wisp-cli-aarch64-linux
265 </a>
266 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux" class="download-link" download>
267 <span class="platform">Linux (x86_64):</span> wisp-cli-x86_64-linux
268 </a>
269 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-windows.exe" class="download-link" download>
270 <span class="platform">Windows (x86_64):</span> wisp-cli-x86_64-windows.exe
271 </a>
272
273 <h3 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">SHA-1 Checksums</h3>
274 <pre style="font-size: 0.75rem; padding: 1rem;"><code class="language-bash">69de880e160a2f26e3c26b7c28030457913754dc wisp-cli-aarch64-darwin
275026189f2c10077a2be4705102e169e66cb207f84 wisp-cli-aarch64-linux
2764777cff07558906717402484a3313359880eae96 wisp-cli-x86_64-linux
277d6bc789d7fd7c787e5520eb476cee70c97ccb3ce wisp-cli-x86_64-windows.exe</code></pre>
278 </div>
279
280 <div class="cicd-section">
281 <h2>CI/CD Integration</h2>
282 <p>Deploy automatically on every push using <a href="https://tangledspindle.org" target="_blank">Tangled Spindle</a>:</p>
283
284 <pre><code class="language-yaml">when:
285 - event: ['push']
286 branch: ['main']
287 - event: ['manual']
288
289engine: 'nixery'
290
291clone:
292 skip: false
293 depth: 1
294 submodules: false
295
296dependencies:
297 nixpkgs:
298 - nodejs
299 - coreutils
300 - curl
301 github:NixOS/nixpkgs/nixpkgs-unstable:
302 - bun
303
304environment:
305 SITE_PATH: 'dist'
306 SITE_NAME: 'my-site'
307 WISP_HANDLE: 'your-handle.bsky.social'
308
309steps:
310 - name: build site
311 command: |
312 export PATH="$HOME/.nix-profile/bin:$PATH"
313
314 # regenerate lockfile, https://github.com/npm/cli/pull/8184 makes rolldown not install
315 rm package-lock.json bun.lock
316 bun install @rolldown/binding-linux-arm64-gnu --save-optional
317 bun install
318
319 # run directly with bun because of shebang issues in nix
320 bun node_modules/.bin/vite build
321
322 - name: deploy to wisp
323 command: |
324 # Download Wisp CLI
325 curl https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux -o wisp-cli
326 chmod +x wisp-cli
327
328 # Deploy to Wisp
329 ./wisp-cli \
330 "$WISP_HANDLE" \
331 --path "$SITE_PATH" \
332 --site "$SITE_NAME" \
333 --password "$WISP_APP_PASSWORD"</code></pre>
334
335 <div class="note">
336 <strong>Note:</strong> Set <code>WISP_APP_PASSWORD</code> as a secret in your Tangled Spindle repository settings.
337 Generate an app password from your AT Protocol account settings.
338 </div>
339 </div>
340
341 <div class="cicd-section">
342 <h2>Basic Usage</h2>
343
344 <h3>Deploy a Site</h3>
345 <pre><code class="language-bash"># Download and make executable
346curl -O https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-macos-arm64
347chmod +x wisp-cli-macos-arm64
348
349# Deploy your site
350./wisp-cli-macos-arm64 deploy your-handle.bsky.social \
351 --path ./dist \
352 --site my-site \
353
354# Your site will be available at:
355# https://sites.wisp.place/your-handle/my-site</code></pre>
356
357 <h3>Pull a Site from PDS</h3>
358 <p style="color: var(--demo-text-secondary); margin-bottom: 0.5rem;">Download a site from the PDS to your local machine (uses OAuth authentication):</p>
359 <pre><code class="language-bash"># Pull a site to a specific directory
360wisp-cli pull your-handle.bsky.social \
361 --site my-site \
362 --output ./my-site
363
364# Pull to current directory
365wisp-cli pull your-handle.bsky.social \
366 --site my-site
367</code></pre>
368 <h3>Serve a Site Locally with Real-Time Updates</h3>
369 <p style="color: var(--demo-text-secondary); margin-bottom: 0.5rem;">Run a local server that monitors the firehose for real-time updates (uses OAuth authentication):</p>
370 <pre><code class="language-bash"># Serve on http://localhost:8080 (default)
371wisp-cli serve your-handle.bsky.social \
372 --site my-site
373
374# Serve on a custom port
375wisp-cli serve your-handle.bsky.social \
376 --site my-site \
377 --port 3000
378
379# Downloads site, serves it, and watches firehose for live updates!
380
381# Enable SPA mode (serve index.html for all routes)
382wisp-cli serve your-handle.bsky.social \
383 --site my-site \
384 --spa
385
386# Enable directory listing for paths without index files
387wisp-cli serve your-handle.bsky.social \
388 --site my-site \
389 --directory</code></pre>
390 </div>
391
392 <div class="footer">
393 <p>Learn more at <a href="https://wisp.place">wisp.place</a></p>
394 </div>
395 </div>
396 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
397 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
398 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-bash.min.js"></script>
399 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-yaml.min.js"></script>
400</body>
401</html>