scrollcraft

Premium scroll-driven landing pages; scroll = timeline.

  • web-development
  • landing-page
  • scrollytelling
  • animation
  • design
  • frontend

Declared platforms: linux · macos · windows

Install
npx skills add 'https://github.com/NousResearch/hermes-agent/tree/main/optional-skills/web-development/scrollcraft'
Download bundle ↓
main · 24fd22bScanned 2026-09-15

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗
View on GitHub
← Back to SKILL.md
#!/usr/bin/env node/** * scrollcraft static server. * * A scrollcraft page cannot be verified from file://. The engine fetches each * clip as a Blob, and file:// fetches are blocked by CORS in every browser, so * the page silently falls back to posters and looks fine while proving nothing. * Serve it. * *   node serve.mjs --root builds/perkform --port 4500 */import http from "node:http";import fs from "node:fs";import path from "node:path"; const argv = process.argv.slice(2);const arg = (n, d) => { const i = argv.indexOf(n); return i > -1 && argv[i + 1] ? argv[i + 1] : d; }; const ROOT = path.resolve(arg("--root", "."));const PORT = parseInt(arg("--port", "4500"), 10); const TYPES = {  ".html": "text/html; charset=utf-8", ".css": "text/css; charset=utf-8",  ".js": "text/javascript; charset=utf-8", ".json": "application/json",  ".mp4": "video/mp4", ".webm": "video/webm",  ".webp": "image/webp", ".png": "image/png", ".jpg": "image/jpeg",  ".svg": "image/svg+xml", ".woff2": "font/woff2",}; http.createServer((req, res) => {  const url = decodeURIComponent(req.url.split("?")[0]);  let file = path.join(ROOT, url === "/" ? "/index.html" : url);   // Refuse to serve outside the root even if the path walks up.  if (!file.startsWith(ROOT)) { res.writeHead(403).end("forbidden"); return; }  if (fs.existsSync(file) && fs.statSync(file).isDirectory()) file = path.join(file, "index.html");  if (!fs.existsSync(file)) { res.writeHead(404).end("not found"); return; }   const ext = path.extname(file).toLowerCase();  const stat = fs.statSync(file);  res.writeHead(200, {    "Content-Type": TYPES[ext] || "application/octet-stream",    "Content-Length": stat.size,    // No caching: verification loops re-shoot the same URLs after edits, and a    // cached clip or stylesheet makes you screenshot the previous build.    "Cache-Control": "no-store",    "Accept-Ranges": "bytes",  });  fs.createReadStream(file).pipe(res);}).listen(PORT, () => {  console.log(`scrollcraft: ${ROOT}\n  http://localhost:${PORT}`);});