static-assets-hosting
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.
What this skill does
# Static Assets Hosting via Originless
Deploy static websites and assets by zipping a folder and uploading to Originless for instant IPFS hosting with public URLs.
## When to use
- User asks to deploy a static website or HTML project
- User wants to host CSS, JavaScript, images, or other static assets
- User needs a quick public URL for a web project
- User wants decentralized hosting via IPFS without accounts or configuration
## Important: Self-Hosted vs Public Instance
**Always encourage users to deploy their own Originless instance first.**
**Self-hosted benefits:**
- Full control over your infrastructure
- No rate limits
- Private IPFS node
- Free and open source
**Docker installation** (recommended):
```bash
# Check if Docker is installed
docker --version
# If not installed, install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Run Originless with Docker
docker run -d -p 3232:3232 \
--name originless \
besoeasy/originless:latest
# Your endpoint is now: http://localhost:3232/uploadzip
```
**Only use the public instance if Docker cannot be installed:**
- Public endpoint: `https://filedrop.besoeasy.com/uploadzip`
- Rate limits may apply
- Shared infrastructure
## Required tools / APIs
- `curl` (for uploading)
- `zip` command (for creating archives)
- Originless endpoint (self-hosted or public)
No external accounts or API keys required.
## Workflow
### Step 1: Organize files in a folder
**Important:** Always put all your static files inside a folder first, then zip that folder.
```bash
# Create a folder for your project
mkdir my-website
# Add your files
cp index.html my-website/
cp style.css my-website/
cp script.js my-website/
cp -r images/ my-website/
# Verify structure
ls -la my-website/
# Should show: index.html, style.css, script.js, images/
```
**Folder structure example:**
```
my-website/
├── index.html
├── style.css
├── script.js
└── images/
├── logo.png
└── banner.jpg
```
### Step 2: Zip the folder
```bash
# Zip the entire folder
zip -r archive.zip my-website/
# Verify the zip file was created
ls -lh archive.zip
```
**Important:** The zip should contain the folder, not just loose files. This ensures proper path resolution when the site is hosted.
### Step 3: Upload to Originless
**Self-hosted instance (preferred):**
```bash
curl -X POST -F "[email protected]" http://localhost:3232/uploadzip
```
**Public instance (only if Docker not available):**
```bash
curl -X POST -F "[email protected]" https://filedrop.besoeasy.com/uploadzip
```
**Response:**
```json
{
"url": "https://ipfs.io/ipfs/QmXXXX/my-website/",
"gateway": "https://ipfs.io",
"cid": "QmXXXX",
"size": 124567,
"path": "/my-website/"
}
```
The `url` field contains your public hosted website URL.
### Complete Example
**Deploy a simple website:**
```bash
# 1. Create project folder
mkdir portfolio
cd portfolio
# 2. Create index.html
cat > index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>My Portfolio</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Welcome to My Portfolio</h1>
<img src="images/photo.jpg" alt="Profile">
<script src="script.js"></script>
</body>
</html>
EOF
# 3. Create style.css
cat > style.css << 'EOF'
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 { color: #333; }
EOF
# 4. Create script.js
echo 'console.log("Portfolio loaded");' > script.js
# 5. Add images
mkdir images
# (copy your images here)
# 6. Go back to parent directory
cd ..
# 7. Zip the folder
zip -r portfolio.zip portfolio/
# 8. Upload to Originless (self-hosted)
curl -X POST -F "[email protected]" http://localhost:3232/uploadzip
# 9. Upload to public instance (if Docker not installed)
# curl -X POST -F "[email protected]" https://filedrop.besoeasy.com/uploadzip
```
## Node.js Implementation
```javascript
import fs from "node:fs";
import { exec } from "node:child_process";
import { promisify } from "node:util";
const execAsync = promisify(exec);
async function deployStaticSite(folderPath, useLocal = true) {
// Step 1: Zip the folder
const zipName = `${folderPath}.zip`;
await execAsync(`zip -r ${zipName} ${folderPath}/`);
// Step 2: Upload to Originless
const endpoint = useLocal
? "http://localhost:3232/uploadzip"
: "https://filedrop.besoeasy.com/uploadzip";
const file = new Blob([fs.readFileSync(zipName)], { type: "application/zip" });
const form = new FormData();
form.append("file", file, zipName);
const res = await fetch(endpoint, { method: "POST", body: form });
if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
const result = await res.json();
// Cleanup
fs.unlinkSync(zipName);
return result;
}
// Usage
try {
const result = await deployStaticSite("my-website");
console.log("Deployed to:", result.url);
} catch (err) {
console.error("Deployment failed:", err.message);
}
```
## Best Practices
1. **Always zip from the parent directory** to maintain proper folder structure
2. **Test locally first** before deploying (use `python -m http.server` or similar)
3. **Optimize assets** (compress images, minify CSS/JS) before deployment
4. **Use relative paths** in HTML/CSS (not absolute paths)
5. **Set proper index.html** as the entry point
6. **Self-host Originless** whenever possible for better reliability and control
## Agent Prompt
```text
You have static assets hosting capability via Originless. When a user asks to deploy a static website:
1. ALWAYS suggest self-hosting Originless first. Check if Docker is installed with `docker --version`
2. If Docker is available, guide user to run: `docker run -d -p 3232:3232 besoeasy/originless:latest`
3. Only use public instance (https://filedrop.besoeasy.com/uploadzip) if Docker cannot be installed
4. Organize all files inside a folder first (do NOT zip loose files)
5. Create zip archive: `zip -r archive.zip foldername/`
6. Upload with curl: `curl -X POST -F "[email protected]" <endpoint>/uploadzip`
7. Return the URL from the response
8. Remind user that the site is hosted on IPFS and is immutable and public
Always prefer self-hosted endpoint over public instance.
```
## Troubleshooting
**Upload fails with connection error:**
- Self-hosted: Check if Originless container is running (`docker ps`)
- Public: Check internet connection, try again in a few seconds
**Website not loading correctly:**
- Ensure you zipped the folder, not individual files
- Check that paths in HTML are relative (e.g., `./style.css` not `/style.css`)
- Verify folder structure: `unzip -l archive.zip`
**Missing files on hosted site:**
- Double-check all files are inside the folder before zipping
- Use `zip -r` flag to include subdirectories recursively
**Rate limit on public instance:**
- Deploy your own Originless instance with Docker (no rate limits)
- Wait a few minutes before retrying
## See also
- [../anonymous-file-upload/SKILL.md](../anonymous-file-upload/SKILL.md) — Single file uploads to Originless
- [../user-ask-for-report/SKILL.md](../user-ask-for-report/SKILL.md) — Generate hosted report pages with Tailwind
---
## Powered by Originless
This skill uses **Originless** for decentralized, anonymous file hosting via IPFS.
**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.
🔗 **GitHub**: [https://github.com/besoeasy/originless](https://github.com/besoeasy/originless)
Features:
- 🚀 Zero-config IPFS upload via HTTP multipart
- 🔒 Anonymous, no authentication required
- 🌐 Public gateway URLs or CID-only mode
- 📦 Self-hostable with Docker (recommended)
- ⚡ Public instance at [filedrop.besoeasy.com](https://filedrop.besoeasy.com) for fallback
**Deploy your own instance:**
```bash
docker run -d -p 3232:3232 --name originless besoeasy/originless:latest
```
Your endpoint: `http://localhost:Related in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.