Best for
- Use this skill when the user mentions "pinme", or needs to upload files, store to IPFS, create/publish/deploy websites or full-stack services (including frontend pages, backend APIs, database storage, email sending, etc.
glitternetwork/pinme/skills/pinme/SKILL.md
Use this skill when the user mentions "pinme", or needs to upload files, store to IPFS, create/publish/deploy websites or full-stack services (including frontend pages, backend APIs, database storage, email sending, etc.), or any feature requiring backend database/server support.
Decision brief
Zero-config deployment tool: upload static files to IPFS, or create and deploy full-stack web projects (React+Vite + Cloudflare Worker + D1 database). Workers also support sending emails via the PinMe platform API.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/glitternetwork/pinme --skill "skills/pinme"Inspect the Agent Skill "pinme" from https://github.com/glitternetwork/pinme/blob/7822b0501607786958ecb458f3bd02a061933efa/skills/pinme/SKILL.md at commit 7822b0501607786958ecb458f3bd02a061933efa. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Review the “When to Use” section in the pinned source before continuing.
Login required. Use pinme login or pinme set-appkey before pinme upload or pinme import.
bash pinme upload pinme upload ./dist --domain my-site Optional: bind subdomain (wallet balance required) bash pinme upload ./document.pdf Single file pinme upload ./my-folder Folder pinme upload dist Vite/Vue build artifacts pinme upload build CRA build artifacts pinme upload o…
Review the “Common Examples” section in the pinned source before continuing.
nodemodules/, .env, .git/, src/
Permission review
The documentation includes network, browsing, or remote request actions.
"User Request" -> "Needs backend API or database?";The documentation includes network, browsing, or remote request actions.
# Outputs preview URL: https://pinme.eth.limo/#/preview/{CID}Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 90/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 3,734 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Zero-config deployment tool: upload static files to IPFS, or create and deploy full-stack web projects (React+Vite + Cloudflare Worker + D1 database). Workers also support sending emails via the PinMe platform API.
digraph pinme_decision {
"User Request" [shape=doublecircle];
"Needs backend API or database?" [shape=diamond];
"Upload Files (Path 1)" [shape=box];
"Full-Stack Project (Path 2)" [shape=box];
"User Request" -> "Needs backend API or database?";
"Needs backend API or database?" -> "Upload Files (Path 1)" [label="No"];
"Needs backend API or database?" -> "Full-Stack Project (Path 2)" [label="Yes"];
}
Login required. Use
pinme loginorpinme set-appkey <AppKey>beforepinme uploadorpinme import.
digraph upload_flow {
"Install/update pinme to latest" [shape=box];
"Authenticate" [shape=box];
"Determine build artifacts" [shape=box];
"pinme upload <path>" [shape=box];
"Return preview URL" [shape=doublecircle];
"Install/update pinme to latest" -> "Authenticate";
"Authenticate" -> "Determine build artifacts";
"Determine build artifacts" -> "pinme upload <path>";
"pinme upload <path>" -> "Return preview URL";
}
1. Check installation and update to latest:
LOCAL=$(pinme --version 2>/dev/null || echo "0.0.0")
LATEST=$(npm view pinme version)
[ "$LOCAL" != "$LATEST" ] && npm install -g pinme@latest || echo "pinme is up to date ($LOCAL)"
2. Authenticate:
pinme login
# or: pinme set-appkey <AppKey>
3. Determine upload target (priority order):
dist/ — Vite / Vue / Reactbuild/ — Create React Appout/ — Next.js static exportpublic/ — Plain static files4. Upload:
pinme upload <path>
pinme upload ./dist --domain my-site # Optional: bind subdomain (wallet balance required)
5. Return the final URL printed by PinMe to the user. URL priority is: DNS domain > PinMe subdomain > short URL > preview URL. If it falls back to preview, return the full URL including all hash characters — do not truncate.
pinme upload ./document.pdf # Single file
pinme upload ./my-folder # Folder
pinme upload dist # Vite/Vue build artifacts
pinme upload build # CRA build artifacts
pinme upload out # Next.js static export
pinme upload ./dist --domain my-site # Bind PinMe subdomain (wallet balance required)
pinme import ./my-archive.car # Import CAR file
node_modules/, .env, .git/, src/Login required. Uses React+Vite frontend + Cloudflare Worker backend + D1 SQLite database. When designing frontend projects, use Ant Design as the primary design reference, and prioritize following its conventions for layout, components, spacing, and interaction patterns.
digraph fullstack_flow {
"Install/update pinme to latest" [shape=box];
"pinme login" [shape=box];
"pinme create <name>" [shape=box];
"Modify template code" [shape=box];
"pinme save" [shape=box];
"Return preview URL" [shape=doublecircle];
"Install/update pinme to latest" -> "pinme login";
"pinme login" -> "pinme create <name>";
"pinme create <name>" -> "Modify template code";
"Modify template code" -> "pinme save";
"pinme save" -> "Return preview URL";
}
| Layer | Tech Stack | Deploy Target |
|---|---|---|
| Frontend | React + Vite (frontend/) | IPFS |
| Backend | Cloudflare Worker (backend/src/worker.ts) | {name}.pinme.pro |
| Database | D1 SQLite (db/*.sql) | Cloudflare D1 |
| Object storage | R2 (env.R2) | Cloudflare R2 |
pinme-r2 skill. PinMe injects the project bucket as env.R2; do not replace it with D1 BLOBs or Worker filesystem state.pinme login # Login (only needed once)
pinme create <dirName> # Clone template and create project (auto-fills API URL)
pinme save # First deploy / full update (frontend + backend + database, single command)
pinme update-worker # Update backend only (when only backend/src/worker.ts was modified)
pinme update-web # Update frontend only (when only frontend/src/ was modified)
pinme update-db # Run SQL migrations only (when only db/ was modified)
pinme savedeploys frontend + backend + database all at once. Only usepinme update-*when you're certain only one part was modified.
{project}/
├── pinme.toml # Root config (auto-generated, do not modify)
├── package.json # Monorepo root (workspaces: frontend + backend)
├── backend/
│ ├── wrangler.toml # Worker config (auto-generated, do not modify)
│ ├── package.json
│ └── src/
│ └── worker.ts # Backend entry — primarily used for JSON APIs in this template
├── db/
│ └── 001_init.sql # SQL table definitions
├── frontend/
│ ├── package.json
│ ├── vite.config.ts # Dev proxy: /api → localhost:8787
│ ├── index.html
│ ├── .env # Auto-generated: VITE_API_URL (do not modify)
│ └── src/
│ ├── main.tsx
│ ├── App.tsx
│ ├── utils/
│ │ ├── api.ts # export const API = import.meta.env.VITE_WORKER_URL || ''
│ │ └── config.ts # Auto-generated: public_client_config (only when auth is enabled)
│ └── pages/
│ └── Home/
│ └── index.tsx
└── .gitignore
LOCAL=$(pinme --version 2>/dev/null || echo "0.0.0")
LATEST=$(npm view pinme version)
[ "$LOCAL" != "$LATEST" ] && npm install -g pinme@latest
pinme login
pinme create my-app
cd my-app
pinme create generates a working Hello World template (includes frontend page + backend API routes + database schema). Modify the template to match the user's business logic — do not write from scratch:
backend/src/worker.ts — replace API routesfrontend/src/pages/ — replace page componentsdb/001_init.sql — replace table definitionspinme save
# Single command deploys frontend + backend + database
# Outputs preview URL: https://pinme.eth.limo/#/preview/{CID}
Return the preview URL to the user. Note: return the full URL including all hash characters — do not truncate.
The backend Worker is deployed at https://{name}.pinme.pro. Frontend API requests are automatically configured to point to that address — no manual setup needed.
| Changes | Command | Notes |
|---|---|---|
Backend only (backend/src/worker.ts) | pinme update-worker | Faster |
Frontend only (frontend/src/) | pinme update-web | Generates new CID |
Database only (db/) | pinme update-db | Runs new migrations |
| Multiple changes or uncertain | pinme save | Safe full deployment |
Each frontend deployment generates a new CID and preview URL. Old URLs remain accessible.
backend/src/worker.ts)In this template, the Worker backend is primarily used for JSON APIs. Prefer standard Web APIs and simple manual routing by default. Worker-compatible libraries can be added when needed, but the default template does not rely on extra frameworks. Avoid packages that depend on a full Node.js runtime, a persistent local filesystem, native binaries, or child processes.
export interface Env {
DB: D1Database; // When using database
R2: R2Bucket; // Project object storage; injected by PinMe
API_KEY?: string; // When using email sending
JWT_SECRET: string; // When using JWT auth
ADMIN_PASSWORD: string; // When using password auth
}
const CORS_HEADERS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-API-Key',
};
function json(data: unknown, status = 200): Response {
return Response.json(data, { status, headers: CORS_HEADERS });
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { pathname } = new URL(request.url);
const method = request.method;
if (method === 'OPTIONS') return new Response(null, { status: 204, headers: CORS_HEADERS });
try {
if (pathname === '/api/items' && method === 'GET') return handleGetItems(env);
if (pathname === '/api/items' && method === 'POST') return handleCreateItem(request, env);
return json({ error: 'Not found' }, 404);
} catch {
return json({ error: 'Internal server error' }, 500);
}
},
};
| Item | Notes |
|---|---|
| Dependency choice | Prefer standard Web APIs and simple manual routing by default. If extra dependencies are needed, prefer Worker-compatible libraries. |
| Node.js capability | Workers now support part of Node.js compatibility, but they are not a full Node.js runtime. Do not assume all Node.js built-in modules are available or behave exactly the same. |
| Filesystem | Do not treat a Worker like a server with a persistent local disk. Even if some fs capabilities are available, do not rely on persistence across requests. |
| Response types | This template mainly uses the Worker for JSON APIs. If there is a clear need, it can also be adapted to return HTML or other content. |
| Password storage | Never store passwords in plaintext. Use a dedicated password hashing algorithm such as bcrypt, scrypt, or Argon2. |
| SQL | Do not build SQL by string concatenation. Use parameterized queries such as .bind(). |
When the backend needs email sending, use the PinMe platform API (https://pinme.cloud/api/v4/send_email).
1. Configure API_KEY
Add to the Env interface:
export interface Env {
DB: D1Database;
API_KEY?: string; // Required for email sending
}
2. Email Handler Code
async function handleSendEmail(request: Request, env: Env): Promise<Response> {
const apiKey = env.API_KEY;
if (!apiKey) {
return json({ error: 'API_KEY not configured' }, 500);
}
const body = await request.json() as {
to?: string;
subject?: string;
html?: string;
};
if (!body.to) return json({ error: 'Email address is required' }, 400);
if (!body.subject) return json({ error: 'Subject is required' }, 400);
if (!body.html) return json({ error: 'HTML content is required' }, 400);
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(body.to)) {
return json({ error: 'Invalid email address' }, 400);
}
const response = await fetch('https://pinme.cloud/api/v4/send_email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
},
body: JSON.stringify({
to: body.to,
subject: body.subject,
html: body.html,
}),
});
const result = await response.json();
return json(result);
}
// Development: Vite proxies /api to localhost:8787
// Production: VITE_API_URL is auto-injected by pinme create
export const API = import.meta.env.VITE_API_URL || '';
export function getApiUrl(path: string): string {
return API ? `${API}${path}` : path;
}
// Query multiple rows
const { results } = await env.DB.prepare('SELECT * FROM t WHERE x = ?').bind(val).all();
// Query single row (returns null if not found)
const row = await env.DB.prepare('SELECT * FROM t WHERE id = ?').bind(id).first();
// Insert and return new row
const row = await env.DB.prepare('INSERT INTO t (a, b) VALUES (?, ?) RETURNING *').bind(a, b).first();
// Update
await env.DB.prepare('UPDATE t SET a = ? WHERE id = ?').bind(val, id).run();
// Delete (check if affected)
const { meta } = await env.DB.prepare('DELETE FROM t WHERE id = ?').bind(id).run();
if (meta.changes === 0) return json({ error: 'Not found' }, 404);
Format: db/NNN_description.sql (for example, 001_init.sql). Files are executed in filename order.
SQLite Type Constraints:
| Do Not Use | Alternative |
|---|---|
BOOLEAN | INTEGER (0 = false, 1 = true) |
DATETIME / TIMESTAMP | TEXT, stored as ISO 8601 (default: datetime('now')) |
JSON type | TEXT, using JSON.stringify() / JSON.parse() |
VARCHAR(n) | TEXT |
| Scenario | Default Suggestion |
|---|---|
| File storage (images, attachments, media) | Use the project R2 binding through env.R2; use the pinme-r2 skill for secure routes and metadata patterns |
| Real-time communication | This template defaults to regular HTTP APIs. If there is no clear real-time requirement, start with polling |
| Multiple Workers | This template defaults to combining functionality into a single Worker and separating routes by prefix |
| Multiple databases | This template defaults to combining data into one D1 database and only splitting when isolation is truly needed |
pinme.toml, backend/wrangler.toml, and frontend/.env are generated by PinMe. Do not edit them manually by default. If extra runtime configuration is truly needed, prefer doing it through PinMe-supported mechanisms.VITE_API_URL environment variable. Do not hardcode it.| Error | Solution |
|---|---|
command not found: pinme | npm install -g pinme |
No such file or directory | Verify that the path exists |
Permission denied | Check file or directory permissions |
| Upload failed | Check the network connection and retry |
| Not logged in | Run pinme login first |
pinme list / pinme ls -l 5 # View upload history
pinme list -c # Clear upload history
pinme rm <hash> # Delete uploaded content
pinme bind <path> --domain <domain> # Bind domain (VIP + AppKey required)
pinme export <CID> # Export as CAR file
pinme set-appkey # Set/view AppKey
pinme my-domains # List bound domains
pinme delete <project> # Delete project (Worker + domain + D1)
pinme logout # Log out
Frequently asked questions
Zero-config deployment tool: upload static files to IPFS, or create and deploy full-stack web projects (React+Vite + Cloudflare Worker + D1 database). Workers also support sending emails via the PinMe platform API.
The source record exposes this install command: npx skills add https://github.com/glitternetwork/pinme --skill "skills/pinme". Inspect the command and pinned source before running it.
Static rules flagged network in the source; the page lists the matching lines and excerpts.
Alternatives
NVIDIA/skills
Use this skill when the user wants to deploy, run, debug, tear down, or call the REST API of the RTVI-CV 2D detection / tracking microservice. Trigger when the user says things like 'deploy rtvi-cv', 'start warehouse 2d', 'add a stream', 'check rtvi-cv health', or 'stop the perception container'. Not for VLM, embedding, or analytics — use the matching vss-* skill.
UiPath/skills
UiPath Coded Apps — scaffold, build, run, and deploy Coded Web Apps and Coded Action Apps: React/TypeScript apps that call UiPath Cloud APIs via the `@uipath/uipath-typescript` SDK and ship to Automation Cloud (push/pull to Studio Web, pack, publish, deploy, OAuth-PKCE). Also generates live analytics & governance dashboards from a plain-language request, wired to tenant data via the Insights real-time API, with edit and deploy flows. For RPA→uipath-rpa, Python agents→uipath-agents, Maestro flows
NVIDIA/skills
Deploy and operate the RTVI-CV-3D microservice as MV3DT (`MODE=mv3dt`): per-camera DeepStream perception plus BEV Fusion over calibrated cameras. Supports the bundled sample dataset, custom video files, and RTSP streams, and chains to `vss-generate-video-calibration` when calibration is missing. Use `vss-deploy-profile` for the full warehouse blueprint and `vss-deploy-detection-tracking-2d` for single-camera 2D detection.
kychee-com/run402
Provision Postgres + REST API + auth + content-addressed storage + serverless functions + email — paid with x402 USDC on Base. Prototype tier is free on testnet. Use when the user asks to build a webapp, deploy a site, create a database, generate images, or mentions Run402.