Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Farcaster Frame endpoint for KidLisp pieces

GET /frame/$piece returns Frame-compatible HTML with fc:frame meta
tags. Warpcast renders it as an interactive card with piece thumbnail
and "View" button that launches the piece on aesthetic.computer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+49
+49
lith/server.mjs
··· 460 460 } 461 461 }); 462 462 463 + // --- Farcaster Frame endpoint for KidLisp pieces --- 464 + app.get("/frame/:piece", async (req, res) => { 465 + const piece = req.params.piece.startsWith("$") ? req.params.piece : `$${req.params.piece}`; 466 + const code = piece.slice(1); 467 + const base = "https://aesthetic.computer"; 468 + const pieceUrl = `${base}/${piece}`; 469 + const keepUrl = `https://keep.kidlisp.com/${code}`; 470 + 471 + // Try to get thumbnail from oven cache 472 + const thumbUrl = `https://oven.aesthetic.computer/grab/webp/600/400/${piece}`; 473 + // Fallback OG image 474 + const ogImage = `https://oven.aesthetic.computer/kidlisp-og.png`; 475 + 476 + const frameEmbed = JSON.stringify({ 477 + version: "1", 478 + imageUrl: thumbUrl, 479 + button: { 480 + title: `View ${piece}`, 481 + action: { 482 + type: "launch_frame", 483 + url: pieceUrl, 484 + name: `KidLisp ${piece}`, 485 + splashImageUrl: "https://assets.aesthetic.computer/kidlisp-favicon.gif", 486 + splashBackgroundColor: "#000000", 487 + }, 488 + }, 489 + }); 490 + 491 + res.setHeader("Content-Type", "text/html; charset=utf-8"); 492 + res.send(`<!DOCTYPE html> 493 + <html> 494 + <head> 495 + <meta charset="utf-8"> 496 + <meta property="og:title" content="${piece} — KidLisp" /> 497 + <meta property="og:description" content="A KidLisp piece on Aesthetic Computer" /> 498 + <meta property="og:image" content="${thumbUrl}" /> 499 + <meta property="og:url" content="${pieceUrl}" /> 500 + <meta property="fc:frame" content='${frameEmbed.replace(/'/g, "&#39;")}' /> 501 + <meta name="fc:frame" content='${frameEmbed.replace(/'/g, "&#39;")}' /> 502 + <title>${piece} — KidLisp</title> 503 + </head> 504 + <body> 505 + <h1>${piece}</h1> 506 + <p><a href="${pieceUrl}">View on Aesthetic Computer</a></p> 507 + <p><a href="${keepUrl}">Keep on KidLisp</a></p> 508 + </body> 509 + </html>`); 510 + }); 511 + 463 512 // --- /media/* handler (ports Netlify edge function media.js) --- 464 513 app.all("/media/*rest", async (req, res) => { 465 514 const parts = req.path.split("/").filter(Boolean); // ["media", ...]