{"id":"84fb6b38-968f-4327-8532-b5e0c3c59ccc","shortId":"GHC9zE","kind":"skill","title":"static-assets-hosting","tagline":"Host static websites and assets via zip upload to Originless IPFS. Use when: (1) Deploying static sites, (2) Hosting HTML/CSS/JS projects, (3) Sharing web assets publicly, or (4) User asks to host static files.","description":"# Static Assets Hosting via Originless\n\nDeploy static websites and assets by zipping a folder and uploading to Originless for instant IPFS hosting with public URLs.\n\n## When to use\n\n- User asks to deploy a static website or HTML project\n- User wants to host CSS, JavaScript, images, or other static assets\n- User needs a quick public URL for a web project\n- User wants decentralized hosting via IPFS without accounts or configuration\n\n## Important: Self-Hosted vs Public Instance\n\n**Always encourage users to deploy their own Originless instance first.**\n\n**Self-hosted benefits:**\n- Full control over your infrastructure\n- No rate limits\n- Private IPFS node\n- Free and open source\n\n**Docker installation** (recommended):\n\n```bash\n# Check if Docker is installed\ndocker --version\n\n# If not installed, install Docker\ncurl -fsSL https://get.docker.com -o get-docker.sh\nsudo sh get-docker.sh\n\n# Run Originless with Docker\ndocker run -d -p 3232:3232 \\\n  --name originless \\\n  besoeasy/originless:latest\n\n# Your endpoint is now: http://localhost:3232/uploadzip\n```\n\n**Only use the public instance if Docker cannot be installed:**\n- Public endpoint: `https://filedrop.besoeasy.com/uploadzip`\n- Rate limits may apply\n- Shared infrastructure\n\n## Required tools / APIs\n\n- `curl` (for uploading)\n- `zip` command (for creating archives)\n- Originless endpoint (self-hosted or public)\n\nNo external accounts or API keys required.\n\n## Workflow\n\n### Step 1: Organize files in a folder\n\n**Important:** Always put all your static files inside a folder first, then zip that folder.\n\n```bash\n# Create a folder for your project\nmkdir my-website\n\n# Add your files\ncp index.html my-website/\ncp style.css my-website/\ncp script.js my-website/\ncp -r images/ my-website/\n\n# Verify structure\nls -la my-website/\n# Should show: index.html, style.css, script.js, images/\n```\n\n**Folder structure example:**\n```\nmy-website/\n├── index.html\n├── style.css\n├── script.js\n└── images/\n    ├── logo.png\n    └── banner.jpg\n```\n\n### Step 2: Zip the folder\n\n```bash\n# Zip the entire folder\nzip -r archive.zip my-website/\n\n# Verify the zip file was created\nls -lh archive.zip\n```\n\n**Important:** The zip should contain the folder, not just loose files. This ensures proper path resolution when the site is hosted.\n\n### Step 3: Upload to Originless\n\n**Self-hosted instance (preferred):**\n\n```bash\ncurl -X POST -F \"file=@archive.zip\" http://localhost:3232/uploadzip\n```\n\n**Public instance (only if Docker not available):**\n\n```bash\ncurl -X POST -F \"file=@archive.zip\" https://filedrop.besoeasy.com/uploadzip\n```\n\n**Response:**\n\n```json\n{\n  \"url\": \"https://ipfs.io/ipfs/QmXXXX/my-website/\",\n  \"gateway\": \"https://ipfs.io\",\n  \"cid\": \"QmXXXX\",\n  \"size\": 124567,\n  \"path\": \"/my-website/\"\n}\n```\n\nThe `url` field contains your public hosted website URL.\n\n### Complete Example\n\n**Deploy a simple website:**\n\n```bash\n# 1. Create project folder\nmkdir portfolio\ncd portfolio\n\n# 2. Create index.html\ncat > index.html << 'EOF'\n<!DOCTYPE html>\n<html>\n<head>\n    <title>My Portfolio</title>\n    <link rel=\"stylesheet\" href=\"style.css\">\n</head>\n<body>\n    <h1>Welcome to My Portfolio</h1>\n    <img src=\"images/photo.jpg\" alt=\"Profile\">\n    <script src=\"script.js\"></script>\n</body>\n</html>\nEOF\n\n# 3. Create style.css\ncat > style.css << 'EOF'\nbody {\n    font-family: Arial, sans-serif;\n    max-width: 800px;\n    margin: 0 auto;\n    padding: 20px;\n}\nh1 { color: #333; }\nEOF\n\n# 4. Create script.js\necho 'console.log(\"Portfolio loaded\");' > script.js\n\n# 5. Add images\nmkdir images\n# (copy your images here)\n\n# 6. Go back to parent directory\ncd ..\n\n# 7. Zip the folder\nzip -r portfolio.zip portfolio/\n\n# 8. Upload to Originless (self-hosted)\ncurl -X POST -F \"file=@portfolio.zip\" http://localhost:3232/uploadzip\n\n# 9. Upload to public instance (if Docker not installed)\n# curl -X POST -F \"file=@portfolio.zip\" https://filedrop.besoeasy.com/uploadzip\n```\n\n## Node.js Implementation\n\n```javascript\nimport fs from \"node:fs\";\nimport { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\n\nasync function deployStaticSite(folderPath, useLocal = true) {\n  // Step 1: Zip the folder\n  const zipName = `${folderPath}.zip`;\n  await execAsync(`zip -r ${zipName} ${folderPath}/`);\n\n  // Step 2: Upload to Originless\n  const endpoint = useLocal\n    ? \"http://localhost:3232/uploadzip\"\n    : \"https://filedrop.besoeasy.com/uploadzip\";\n\n  const file = new Blob([fs.readFileSync(zipName)], { type: \"application/zip\" });\n  const form = new FormData();\n  form.append(\"file\", file, zipName);\n\n  const res = await fetch(endpoint, { method: \"POST\", body: form });\n  if (!res.ok) throw new Error(`Upload failed: ${res.status}`);\n\n  const result = await res.json();\n\n  // Cleanup\n  fs.unlinkSync(zipName);\n\n  return result;\n}\n\n// Usage\ntry {\n  const result = await deployStaticSite(\"my-website\");\n  console.log(\"Deployed to:\", result.url);\n} catch (err) {\n  console.error(\"Deployment failed:\", err.message);\n}\n```\n\n## Best Practices\n\n1. **Always zip from the parent directory** to maintain proper folder structure\n2. **Test locally first** before deploying (use `python -m http.server` or similar)\n3. **Optimize assets** (compress images, minify CSS/JS) before deployment\n4. **Use relative paths** in HTML/CSS (not absolute paths)\n5. **Set proper index.html** as the entry point\n6. **Self-host Originless** whenever possible for better reliability and control\n\n## Agent Prompt\n\n```text\nYou have static assets hosting capability via Originless. When a user asks to deploy a static website:\n\n1. ALWAYS suggest self-hosting Originless first. Check if Docker is installed with `docker --version`\n2. If Docker is available, guide user to run: `docker run -d -p 3232:3232 besoeasy/originless:latest`\n3. Only use public instance (https://filedrop.besoeasy.com/uploadzip) if Docker cannot be installed\n4. Organize all files inside a folder first (do NOT zip loose files)\n5. Create zip archive: `zip -r archive.zip foldername/`\n6. Upload with curl: `curl -X POST -F \"file=@archive.zip\" <endpoint>/uploadzip`\n7. Return the URL from the response\n8. Remind user that the site is hosted on IPFS and is immutable and public\n\nAlways prefer self-hosted endpoint over public instance.\n```\n\n## Troubleshooting\n\n**Upload fails with connection error:**\n- Self-hosted: Check if Originless container is running (`docker ps`)\n- Public: Check internet connection, try again in a few seconds\n\n**Website not loading correctly:**\n- Ensure you zipped the folder, not individual files\n- Check that paths in HTML are relative (e.g., `./style.css` not `/style.css`)\n- Verify folder structure: `unzip -l archive.zip`\n\n**Missing files on hosted site:**\n- Double-check all files are inside the folder before zipping\n- Use `zip -r` flag to include subdirectories recursively\n\n**Rate limit on public instance:**\n- Deploy your own Originless instance with Docker (no rate limits)\n- Wait a few minutes before retrying\n\n## See also\n\n- [../anonymous-file-upload/SKILL.md](../anonymous-file-upload/SKILL.md) — Single file uploads to Originless\n- [../generate-report/SKILL.md](../generate-report/SKILL.md) — Generate HTML reports with Tailwind\n\n---\n\n## Powered by Originless\n\nThis skill uses **Originless** for decentralized, anonymous file hosting via IPFS.\n\n**Originless** is a lightweight, self-hostable file upload service that pins content to IPFS and returns instant public URLs — no accounts, no tracking, no storage limits.\n\n🔗 **GitHub**: [https://github.com/besoeasy/originless](https://github.com/besoeasy/originless)\n\nFeatures:\n- 🚀 Zero-config IPFS upload via HTTP multipart\n- 🔒 Anonymous, no authentication required\n- 🌐 Public gateway URLs or CID-only mode\n- 📦 Self-hostable with Docker (recommended)\n- ⚡ Public instance at [filedrop.besoeasy.com](https://filedrop.besoeasy.com) for fallback\n\n**Deploy your own instance:**\n\n```bash\ndocker run -d -p 3232:3232 --name originless besoeasy/originless:latest\n```\n\nYour endpoint: `http://localhost:3232/uploadzip`","tags":["static","assets","hosting","open","skills","besoeasy","agent-skills","ai-agents","claude-code","clawdbot","clawdbot-skill","llm-tools"],"capabilities":["skill","source-besoeasy","skill-static-assets-hosting","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-clawdbot","topic-clawdbot-skill","topic-llm-tools","topic-mcp-server","topic-openai","topic-openclaw","topic-vibe-coding","topic-vibecoding"],"categories":["open-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/besoeasy/open-skills/static-assets-hosting","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add besoeasy/open-skills","source_repo":"https://github.com/besoeasy/open-skills","install_from":"skills.sh"}},"qualityScore":"0.505","qualityRationale":"deterministic score 0.51 from registry signals: · indexed on github topic:agent-skills · 111 github stars · SKILL.md body (7,999 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T12:55:04.752Z","embedding":null,"createdAt":"2026-04-18T22:10:54.138Z","updatedAt":"2026-05-02T12:55:04.752Z","lastSeenAt":"2026-05-02T12:55:04.752Z","tsv":"'/anonymous-file-upload/skill.md':956,957 '/besoeasy/originless](https://github.com/besoeasy/originless)':1014 '/generate-report/skill.md':963,964 '/ipfs/qmxxxx/my-website/':404 '/my-website':412 '/style.css':900,902 '/uploadzip':202,398,541,598,821 '/uploadzip)':784 '0':469 '1':18,236,429,572,662,744 '124567':410 '2':22,318,437,587,674,760 '20px':472 '3':26,364,450,686,777 '3232':176,177,773,774,1058,1059 '3232/uploadzip':187,381,523,595,1067 '333':475 '4':32,477,695,790 '5':485,704,803 '6':494,712,811 '7':501,822 '8':509,829 '800px':467 '9':524 'absolut':702 'account':105,229,1005 'add':268,486 'agent':724 'also':955 'alway':115,243,663,745,844 'anonym':979,1024 'api':211,231 'appli':206 'application/zip':606 'archiv':219,806 'archive.zip':329,341,379,395,809,820,908 'arial':460 'ask':34,68,738 'asset':3,9,29,40,48,87,688,730 'async':565 'authent':1026 'auto':470 'avail':388,764 'await':580,617,634,645 'back':496 'banner.jpg':316 'bash':147,257,322,373,389,428,1053 'benefit':128 'besoeasy/originless':180,775,1062 'best':660 'better':720 'blob':602 'bodi':456,622 'cannot':195,787 'capabl':732 'cat':440,453 'catch':654 'cd':435,500 'check':148,752,862,871,892,916 'child':554 'cid':407,1033 'cid-on':1032 'cleanup':636 'color':474 'command':216 'complet':422 'compress':689 'config':1018 'configur':107 'connect':857,873 'console.error':656 'console.log':481,650 'const':561,576,591,599,607,615,632,643 'contain':346,416,865 'content':996 'control':130,723 'copi':490 'correct':883 'cp':271,276,281,286 'creat':218,258,338,430,438,451,478,804 'css':81 'css/js':692 'curl':160,212,374,390,516,533,814,815 'd':174,771,1056 'decentr':100,978 'deploy':19,44,70,119,424,651,657,679,694,740,938,1049 'deploystaticsit':567,646 'directori':499,668 'docker':144,150,153,159,171,172,194,386,530,754,758,762,769,786,868,944,1040,1054 'doubl':915 'double-check':914 'e.g':899 'echo':480 'encourag':116 'endpoint':183,199,221,592,619,849,1065 'ensur':354,884 'entir':325 'entri':710 'eof':442,449,455,476 'err':655 'err.message':659 'error':628,858 'exampl':307,423 'exec':551,564 'execasync':562,581 'extern':228 'f':377,393,519,536,818 'fail':630,658,855 'fallback':1048 'famili':459 'featur':1015 'fetch':618 'field':415 'file':38,238,248,270,336,352,378,394,520,537,600,612,613,793,802,819,891,910,918,959,980,991 'filedrop.besoeasy.com':201,397,540,597,783,1045,1046 'filedrop.besoeasy.com/uploadzip':200,396,539,596 'filedrop.besoeasy.com/uploadzip)':782 'first':124,252,677,751,797 'flag':928 'folder':52,241,251,256,260,305,321,326,348,432,504,575,672,796,888,904,922 'foldernam':810 'folderpath':568,578,585 'font':458 'font-famili':457 'form':608,623 'form.append':611 'formdata':610 'free':140 'fs':546,549 'fs.readfilesync':603 'fs.unlinksync':637 'fssl':161 'full':129 'function':566 'gateway':405,1029 'generat':965 'get-docker.sh':164,167 'get.docker.com':162 'github':1011 'github.com':1013 'github.com/besoeasy/originless](https://github.com/besoeasy/originless)':1012 'go':495 'guid':765 'h1':473 'host':4,5,23,36,41,60,80,101,111,127,224,362,370,419,515,715,731,749,836,848,861,912,981 'hostabl':990,1038 'html':75,896,966 'html/css':700 'html/css/js':24 'http':1022 'http.server':683 'imag':83,288,304,314,487,489,492,690 'immut':841 'implement':543 'import':108,242,342,545,550,556 'includ':930 'index.html':272,301,311,439,441,707 'individu':890 'infrastructur':133,208 'insid':249,794,920 'instal':145,152,157,158,197,532,756,789 'instanc':114,123,192,371,383,528,781,852,937,942,1043,1052 'instant':58,1001 'internet':872 'ipf':15,59,103,138,838,983,998,1019 'ipfs.io':403,406 'ipfs.io/ipfs/qmxxxx/my-website/':402 'javascript':82,544 'json':400 'key':232 'l':907 'la':295 'latest':181,776,1063 'lh':340 'lightweight':987 'limit':136,204,934,947,1010 'load':483,882 'local':676 'localhost':186,380,522,594,1066 'logo.png':315 'loos':351,801 'ls':294,339 'm':682 'maintain':670 'margin':468 'max':465 'max-width':464 'may':205 'method':620 'minifi':691 'minut':951 'miss':909 'mkdir':264,433,488 'mode':1035 'multipart':1023 'my-websit':265,273,278,283,289,296,308,330,647 'name':178,1060 'need':89 'new':601,609,627 'node':139,548,553,559 'node.js':542 'o':163 'open':142 'optim':687 'organ':237,791 'originless':14,43,56,122,169,179,220,367,512,590,716,734,750,864,941,962,972,976,984,1061 'p':175,772,1057 'pad':471 'parent':498,667 'path':356,411,698,703,894 'pin':995 'point':711 'portfolio':434,436,444,448,482,508 'portfolio.zip':507,521,538 'possibl':718 'post':376,392,518,535,621,817 'power':970 'practic':661 'prefer':372,845 'privat':137 'process':555 'project':25,76,97,263,431 'promisifi':557,563 'prompt':725 'proper':355,671,706 'ps':869 'public':30,62,92,113,191,198,226,382,418,527,780,843,851,870,936,1002,1028,1042 'put':244 'python':681 'qmxxxx':408 'quick':91 'r':287,328,506,583,808,927 'rate':135,203,933,946 'recommend':146,1041 'recurs':932 'relat':697,898 'reliabl':721 'remind':830 'report':967 'requir':209,233,1027 'res':616 'res.json':635 'res.ok':625 'res.status':631 'resolut':357 'respons':399,828 'result':633,640,644 'result.url':653 'retri':953 'return':639,823,1000 'run':168,173,768,770,867,1055 'san':462 'sans-serif':461 'script.js':282,303,313,479,484 'second':879 'see':954 'self':110,126,223,369,514,714,748,847,860,989,1037 'self-host':109,125,222,368,513,713,747,846,859,988,1036 'serif':463 'servic':993 'set':705 'sh':166 'share':27,207 'show':300 'similar':685 'simpl':426 'singl':958 'site':21,360,834,913 'size':409 'skill':974 'skill-static-assets-hosting' 'sourc':143 'source-besoeasy' 'static':2,6,20,37,39,45,72,86,247,729,742 'static-assets-host':1 'step':235,317,363,571,586 'storag':1009 'structur':293,306,673,905 'style.css':277,302,312,452,454 'subdirectori':931 'sudo':165 'suggest':746 'tailwind':969 'test':675 'text':726 'throw':626 'tool':210 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-clawdbot' 'topic-clawdbot-skill' 'topic-llm-tools' 'topic-mcp-server' 'topic-openai' 'topic-openclaw' 'topic-vibe-coding' 'topic-vibecoding' 'track':1007 'tri':642,874 'troubleshoot':853 'true':570 'type':605 'unzip':906 'upload':12,54,214,365,510,525,588,629,812,854,960,992,1020 'url':63,93,401,414,421,825,1003,1030 'usag':641 'use':16,66,189,680,696,779,925,975 'useloc':569,593 'user':33,67,77,88,98,117,737,766,831 'util':560 'verifi':292,333,903 'version':154,759 'via':10,42,102,733,982,1021 'vs':112 'wait':948 'want':78,99 'web':28,96 'websit':7,46,73,267,275,280,285,291,298,310,332,420,427,649,743,880 'welcom':445 'whenev':717 'width':466 'without':104 'workflow':234 'x':375,391,517,534,816 'zero':1017 'zero-config':1016 'zip':11,50,215,254,319,323,327,335,344,502,505,573,579,582,664,800,805,807,886,924,926 'zipnam':577,584,604,614,638","prices":[{"id":"d1212d49-72f6-45e3-965a-7ad2256290ca","listingId":"84fb6b38-968f-4327-8532-b5e0c3c59ccc","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"besoeasy","category":"open-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:10:54.138Z"}],"sources":[{"listingId":"84fb6b38-968f-4327-8532-b5e0c3c59ccc","source":"github","sourceId":"besoeasy/open-skills/static-assets-hosting","sourceUrl":"https://github.com/besoeasy/open-skills/tree/main/skills/static-assets-hosting","isPrimary":false,"firstSeenAt":"2026-04-18T22:10:54.138Z","lastSeenAt":"2026-05-02T12:55:04.752Z"}],"details":{"listingId":"84fb6b38-968f-4327-8532-b5e0c3c59ccc","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"besoeasy","slug":"static-assets-hosting","github":{"repo":"besoeasy/open-skills","stars":111,"topics":["agent-skills","ai","ai-agents","claude-code","clawdbot","clawdbot-skill","llm-tools","mcp-server","openai","openclaw","vibe-coding","vibecoding"],"license":null,"html_url":"https://github.com/besoeasy/open-skills","pushed_at":"2026-03-31T13:05:30Z","description":"Battle-tested skill library for AI agents. Save 98% of API costs with ready-to-use code for crypto, PDFs, search, web scraping & more. No trial-and-error, no expensive APIs.","skill_md_sha":"46e9de112a1dcb54c57d12ceb3b9273b5c7e4b9b","skill_md_path":"skills/static-assets-hosting/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/besoeasy/open-skills/tree/main/skills/static-assets-hosting"},"layout":"multi","source":"github","category":"open-skills","frontmatter":{"name":"static-assets-hosting","description":"Host static websites and assets via zip upload to Originless IPFS. Use when: (1) Deploying static sites, (2) Hosting HTML/CSS/JS projects, (3) Sharing web assets publicly, or (4) User asks to host static files."},"skills_sh_url":"https://skills.sh/besoeasy/open-skills/static-assets-hosting"},"updatedAt":"2026-05-02T12:55:04.752Z"}}