the statusphere demo reworked into a vite/react app in a monorepo

Update tutorial for new behavior

+13 -34
+9 -28
TUTORIAL.md
··· 25 25 26 26 The Atmosphere works the same way, except we're going to check `at://` instead of `https://`. Each user has a data repo under an `at://` URL. We'll crawl all the `at://`s in the Atmosphere for all the "status.json" records and aggregate them into our SQLite database. 27 27 28 - > `at://` is the URL scheme of the AT Protocol. 28 + > `at://` is the URL scheme of the AT Protocol. Under the hood it uses common tech like HTTP and DNS, but it adds all of the features we'll be using in this tutorial. 29 29 30 30 ## Step 1. Starting with our ExpressJS app 31 31 ··· 278 278 // If the user is signed in, get an agent which communicates with their server 279 279 const agent = await getSessionAgent(req, res, ctx) 280 280 if (!agent) { 281 - return res.status(401).json({ error: 'Session required' }) 281 + return res.status(401).type('html').send('<h1>Error: Session required</h1>') 282 282 } 283 283 284 284 // Construct their status record ··· 298 298 }) 299 299 } catch (err) { 300 300 logger.warn({ err }, 'failed to write record') 301 - return res.status(500).json({ error: 'Failed to write record' }) 301 + return res.status(500).type('html').send('<h1>Error: Failed to write record</h1>') 302 302 } 303 303 304 304 res.status(200).json({}) ··· 310 310 311 311 ```html 312 312 <!-- src/pages/home.ts --> 313 - <div class="status-options"> 314 - ${['👍', '🦋', '🥳', /*...*/].map(status => html` 315 - <div class="status-option" data-value="${status}"> 313 + <form action="/status" method="post" class="status-options"> 314 + ${STATUS_OPTIONS.map(status => html` 315 + <button class="status-option" name="status" value="${status}"> 316 316 ${status} 317 - </div>` 318 - )} 319 - </div> 320 - ``` 321 - 322 - And write some client-side javascript to submit the status on click: 323 - 324 - ```javascript 325 - /* src/pages/public/home.js */ 326 - Array.from(document.querySelectorAll('.status-option'), (el) => { 327 - el.addEventListener('click', async (ev) => { 328 - const res = await fetch('/status', { 329 - method: 'POST', 330 - headers: { 'content-type': 'application/json' }, 331 - body: JSON.stringify({ status: el.dataset.value }), 332 - }) 333 - const body = await res.json() 334 - if (!body?.error) { 335 - location.reload() 336 - } 337 - }) 338 - }) 317 + </button> 318 + `)} 319 + </form> 339 320 ``` 340 321 341 322 And here we are!
+4 -6
src/pages/home.ts
··· 78 78 ${STATUS_OPTIONS.map( 79 79 (status) => 80 80 html`<button 81 - class=${ 82 - myStatus?.status === status 83 - ? 'status-option selected' 84 - : 'status-option' 85 - } 81 + class=${myStatus?.status === status 82 + ? 'status-option selected' 83 + : 'status-option'} 86 84 name="status" 87 85 value="${status}" 88 86 > 89 87 ${status} 90 - </div>` 88 + </button>` 91 89 )} 92 90 </form> 93 91 ${statuses.map((status, i) => {