001

Introduction

Blocnet is a decentralized hosting platform. You push a site — it gets pinned across a distributed IPFS node network. No server to babysit. No availability to worry about. No bill at the end of the month.

Every deployment produces a content identifier (CID) — a cryptographic fingerprint of your site's files. That CID is immutable and permanent. You can verify it, share it, and it will resolve from any IPFS gateway on the planet. When you deploy a new version, the pointer updates; the old CID stays accessible forever.

What is IPFS?

IPFS (InterPlanetary File System) is a peer-to-peer network for storing and sharing files. Instead of a URL pointing to a server (like https://myserver.com/index.html), IPFS addresses content by what it is — a hash of the file contents. This means:

  • No single point of failure — any node that has the content can serve it.
  • Tamper-proof — if the content changes, the address changes. What you requested is guaranteed to be what you receive.
  • Permanent — as long as at least one node pins your content, it's accessible.

Think of it like BitTorrent for websites: instead of one server hosting your files, the content lives across many nodes simultaneously.

Why blocnet?

Decentralized

No single company, server, or government can take your site down.

Permanent history

Every deployment gets a permanent CID. Old versions never disappear.

Three commands

Install, register, deploy. From zero to live in under a minute.

No servers

Nothing to patch, no origin to DDoS, no region to go down.

Who is this for?

  • Developers shipping static sites, SPAs, or documentation
  • Projects that need censorship resistance or permanent URLs
  • Anyone who wants immutable deployment history
  • Builders tired of paying $20/month for three hobby projects
Static sites only. Blocnet hosts the output of a build — HTML, CSS, JavaScript, images, fonts. It does not run servers, databases, or backend code. If your project needs a backend, host that separately and call it from your frontend.
002

Quick Start

From zero to a live, permanently-hosted site in four steps.

01

Install the CLI

Install the blocnet CLI globally using npm. You'll need Node.js 18 or later.

Terminal
$ npm install -g blocnet
💡Don't have Node.js? Download it from nodejs.org. The LTS version is recommended.
02

Create an account

Register directly from the CLI. It'll ask for your email and password — no browser required.

Terminal
$ blocnet register
Email: you@example.com
Password: ••••••••
Account created. Logged in as you@example.com

Already have an account? Use blocnet login instead.

03

Deploy your site

Navigate to your project's build output directory and run deploy. Blocnet zips your files, uploads them to IPFS, and gives you a live URL.

Terminal
$ cd my-project/dist
$ blocnet deploy
  Site: my-project.blocnet.cc
 Packing files…
 Uploading to IPFS…
 Deployed!

  URL: https://my-project.blocnet.cc
💡Deploy the build output of your project, not the source. For React/Vite that's usually dist/. For Next.js with static export it's out/. For plain HTML, it's your project root.
04

Open your site

Open the live URL in your browser directly from the terminal:

Terminal
$ blocnet open
  Opening https://my-project.blocnet.cc…

Framework examples

Blocnet deploys the static output of any framework. Here's how to prep common setups:

React (Vite)npm run builddist/
Next.js (static)next build && next exportout/
Astronpm run builddist/
SvelteKit (static adapter)npm run buildbuild/
Vue CLInpm run builddist/
Plain HTMLproject root
003

How It Works

Blocnet is a deployment layer on top of IPFS. Understanding the pieces makes debugging easier and builds confidence in the platform.

Content addressing vs. location addressing

Traditional web hosting serves files at a fixed URL — a location. If the server at that location goes down, the file is unreachable. IPFS addresses files by their content — a cryptographic hash that is unique to those exact bytes.

TRADITIONAL (LOCATION-ADDRESSED)
https://myserver.com/index.html
This URL means: "ask server myserver.com for index.html." If the server is unreachable, you get nothing.
BLOCNET (CONTENT-ADDRESSED)
QmXoypizjW3WknF
jJnVx1KVrmfQkr5...
This CID means: "find the data that hashes to this value." Any IPFS node that has it can serve it — no single point of failure.

What is a CID?

A CID (Content Identifier) is the address of your content on IPFS. It's generated by hashing your files — the same files always produce the same CID, and different files always produce a different CID.

QmXoypizjW3WknFjJnVx1KVrmfQkrPZSyXoypizj
Multibase prefix (Qm = base58)
CIDv0 content
Multihash (SHA-256)
Content hash (the actual fingerprint)

The deployment flow

Here's what happens when you run blocnet deploy:

blocnet CLI
Your machine
ZIP upload
blocnet API
Railway
pin files
Pinata / IPFS
returns CID
save CID → slug mapping
🌐
Browser
your visitors
serve files
blocnet Gateway
*.blocnet.cc
fetch by CID
IPFS Network
distributed nodes
  1. The CLI zips your build directory and uploads it to the blocnet API.
  2. The API unpacks the zip and uploads each file to Pinata (IPFS pinning service). A root CID is returned for the whole directory.
  3. The CID is saved in the database alongside your site's slug (e.g. my-project).
  4. Your my-project.blocnet.cc URL is now live. The gateway resolves it.

How the gateway works

*.blocnet.cc is an HTTP gateway. When someone visits my-project.blocnet.cc:

  1. The gateway looks up my-project in the database and finds the active CID.
  2. It fetches the requested path from IPFS (e.g. CID/about/index.html).
  3. It streams the file back to the browser with the correct Content-Type header.
  4. For client-side routed SPAs, unknown paths fall back to index.html automatically.
Immutable history. Every deployment generates a unique CID that never changes. Even after you redeploy, the old version stays accessible via its CID directly — useful for debugging regressions or sharing a specific version with a client.
004

CLI Reference

All blocnet operations are available from the command line. The CLI stores your credentials at ~/.blocnet/config.json.

INSTALL
npm install -g blocnet

Commands

blocnet register
auth

Create a new blocnet account. Prompts for email and password. Automatically saves credentials so you're logged in immediately.

EXAMPLE
$ blocnet register
Email: you@example.com
Password: ••••••••
Account created. Logged in as you@example.com
blocnet login
auth

Authenticate an existing account. Saves a token to ~/.blocnet/config.json. Run this if you've logged out or switched machines.

EXAMPLE
$ blocnet login
Email: you@example.com
Password: ••••••••
Logged in as you@example.com
blocnet logout
auth

Clear stored credentials. Deletes ~/.blocnet/config.json. You'll need to run login or register before deploying again.

EXAMPLE
$ blocnet logout
Logged out.
blocnet deploy
deploy

Zips a directory and deploys it to IPFS via the blocnet API. Creates a new site automatically on first deploy. Writes the site slug to a .blocnet-site file in the deployed directory so status and open work without the --site flag.

--dir <path>Path to deploy. Defaults to the current directory (.).
--site <id>Redeploy to an existing site by ID instead of creating a new one.
EXAMPLE
$ blocnet deploy --dir ./dist
  Site: my-project.blocnet.cc
⠙ Packing files…
⠹ Uploading to IPFS…
✓ Deployed!
  URL: https://my-project.blocnet.cc
blocnet sites
info

List all sites associated with your account, with their URLs and deployment status.

EXAMPLE
$ blocnet sites

  my-project   my-project.blocnet.cc   live
  old-site     old-site.blocnet.cc     live
blocnet status
info

Show the deployment history for a site — each deploy's CID, date, and whether it's the current live version. Run from a deployed directory and --site can be omitted.

--site <slug>Show status for a specific site. If omitted, reads .blocnet-site from the current directory.
EXAMPLE
$ blocnet status

  my-project  https://my-project.blocnet.cc

  #  CID                    Date
  2  QmXoypizjW3WknFj…    30 Apr 2026 14:00  latest
  1  QmYoypizjW3WknFj…    29 Apr 2026 09:30
blocnet open
info

Open the live URL for a site in your default browser. Works on macOS, Linux, and Windows.

--site <slug>Open a specific site. If omitted, reads .blocnet-site from the current directory.
EXAMPLE
$ blocnet open
  Opening https://my-project.blocnet.cc…
The .blocnet-site file. After a successful deploy, blocnet writes a .blocnet-site file to the deployed directory containing the site's slug. The status and open commands read this file automatically — so if you run them from the same directory, you don't need to specify --site.
005

GitHub Integration

Connect a GitHub repository and every push to your production branch triggers an automatic build and deployment — no CI/CD setup required.

How it works

When you connect a repo, blocnet registers a webhook with GitHub. Every git push to the configured branch sends a notification to the blocnet API. The API clones the repo, runs your build command, and deploys the output to IPFS — exactly like blocnet deploy, but triggered automatically.

Setup

  1. Open your site in the Dashboard and click Connect GitHub.
  2. Authorize the blocnet GitHub App to access your repositories.
  3. Select the repository and the branch to deploy from (usually main).
  4. Set your build command and output directory (or leave as auto-detected).
  5. Click Connect. Push anything to the branch — the first automated deploy starts immediately.

Build configuration

Blocnet auto-detects the framework from your package.json. You can override this with a blocnet.json in your project root:

blocnet.json
{
  "buildCommand": "npm run build",
  "outputDir": "dist",
  "installCommand": "npm install"
}

All three fields are optional. Defaults:

  • buildCommand — auto-detected (e.g. npm run build)
  • outputDir — auto-detected (e.g. dist, out, build)
  • installCommandnpm install

Supported frameworks

Next.jsViteSvelteKitNuxtAstroCreate React AppRemixGatsbyHugoJekyllEleventyStatic HTML
Build environment. The build runs on blocnet's servers with Node.js 20 and npm available. If your project requires a specific Node version or additional system packages, use blocnet.json to specify an installCommand that sets these up.
Never commit secret keys, API tokens, or .env files to your repository. Build-time environment variables can be set in the Dashboard under your site's settings.
006

Custom Domains

Every site gets a free slug.blocnet.cc subdomain. You can also point your own domain — mysite.com, docs.mycompany.com, anything — at it.

Add a custom domain

  1. Open your site in the Dashboard and click Domains → Add domain.
  2. Enter your domain (e.g. mysite.com or www.mysite.com).
  3. Blocnet shows you the DNS record to add. Copy it.
  4. Log in to your domain registrar and add the CNAME record.
  5. Wait for DNS propagation (usually 5–30 minutes, up to 48 hours in rare cases).
  6. Blocnet detects propagation automatically and provisions an SSL certificate.

DNS records

Add a CNAME record at your registrar pointing to proxy.blocnet.cc:

DNS RECORDS
# Root domain (mysite.com)
@    CNAME    proxy.blocnet.cc

# Subdomain (www.mysite.com)
www  CNAME    proxy.blocnet.cc

# Any subdomain (docs.mysite.com)
docs CNAME    proxy.blocnet.cc

Common registrars — Cloudflare, Namecheap, Google Domains, GoDaddy — all support CNAME records. Look for a "DNS Management" or "DNS Records" section in your registrar's dashboard.

💡Using Cloudflare? Set the proxy status to DNS only (grey cloud, not orange). Proxying through Cloudflare can conflict with blocnet's SSL provisioning.

SSL certificates

SSL is automatic. Once blocnet detects your CNAME is live, it provisions a Let's Encrypt certificate — usually within 5 minutes of DNS propagation. Certificates renew automatically every 90 days. You never need to manage them.

Wildcard domains. Wildcard domains (e.g. *.mysite.com) are supported. Instead of a CNAME record, they require a DNS TXT record for Let's Encrypt validation. The Dashboard will provide the exact TXT record value when you add a wildcard domain.
007

API Reference

The REST API lets you manage sites and trigger deployments programmatically. The CLI uses this API internally — anything the CLI can do, you can do directly via HTTP.

BASE URL
https://api.blocnet.cc

Authentication

All endpoints except /auth/register and /auth/login require a Bearer token. Get your token by calling login:

GET TOKEN
curl -X POST https://api.blocnet.cc/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"yourpass"}'

# Response:
{ "token": "eyJhbGci...", "user": { "email": "you@example.com" } }

Pass the token in all subsequent requests:

AUTH HEADER
Authorization: Bearer eyJhbGci...

Endpoints

POST/auth/registerpublic

Create a new account.

REQUEST BODY
{ "email": "you@example.com", "password": "yourpass" }
RESPONSE
{ "token": "eyJhbGci...", "user": { "email": "you@example.com" } }
POST/auth/loginpublic

Authenticate and receive a JWT token.

REQUEST BODY
{ "email": "you@example.com", "password": "yourpass" }
RESPONSE
{ "token": "eyJhbGci...", "user": { "email": "you@example.com" } }
GET/sites

List all sites for the authenticated user. Returns each site with its most recent deployment.

RESPONSE
{ "sites": [{ "id": "...", "name": "My Site", "slug": "my-site",
             "deployments": [{ "ipfsCid": "Qm...", "deployedAt": "..." }] }] }
POST/sites

Create a new site. The slug is auto-generated from the name.

REQUEST BODY
{ "name": "My Site" }
RESPONSE
{ "site": { "id": "...", "name": "My Site", "slug": "my-site" } }
GET/sites/slug/:slug

Get full details for a site including the last 5 deployments and GitHub configuration.

RESPONSE
{ "site": { "id": "...", "slug": "my-site", "name": "My Site",
            "deployments": [...], "github": null } }
DELETE/sites/:id

Delete a site. This removes the registry entry (blocnet.cc URL stops resolving) but does not unpin IPFS content.

RESPONSE
204 No Content
POST/deployments/:siteId

Deploy a zip archive to a site. Send as multipart/form-data with an "archive" field containing the zip file.

REQUEST BODY
multipart/form-data: archive=<zip file>
RESPONSE
{ "deployment": { "id": "...", "ipfsCid": "Qm...", "status": "active" },
  "url": "https://my-site.blocnet.cc" }
008

FAQ

Common questions from developers new to decentralized hosting.

Something not covered here? Open an issue on GitHub or reach out via the Dashboard. We respond to every question.
009

Run a Node

Node operators extend the blocnet network by serving IPFS content from their own infrastructure. When your node is healthy, the blocnet gateway routes real user traffic through it — reducing latency for visitors near your region and making the network more resilient.

Requirements

Before you register, you need a server that is already running and reachable over HTTPS. Specifically:

  • A publicly accessible server — a VPS, cloud VM (DigitalOcean, Hetzner, AWS EC2, etc.), or bare metal machine with a fixed IP address
  • A domain name pointed at that server, e.g. node1.example.com — this becomes your node's endpoint URL
  • A valid TLS certificate for that domain so the endpoint is reachable over https:// (Let's Encrypt / Certbot works fine)
  • Node.js 18+ installed on the server
  • Outbound access from the server to IPFS gateways (port 443)

The endpoint is simply https:// + the domain you pointed at your server. For example, if you set up node1.example.com to point at your VPS and got an SSL certificate for it, your endpoint is https://node1.example.com. You will enter this when registering.

Step 1 — Register your node

  1. Log in and open the Dashboard.
  2. Click the Nodes tab.
  3. Click Register a Node and fill in the form:
    • Name — a human-readable label for your own reference (e.g. frankfurt-01)
    • Endpoint — the https:// URL of the domain you pointed at your server (e.g. https://node1.example.com). This is where blocnet will send traffic.
    • Region — choose the region closest to your server's physical location
  4. Submit. Your node appears in the list with status Pending.

Step 2 — Await approval

The blocnet team reviews pending nodes manually. We check that the endpoint is reachable and the region is accurate. Approval typically takes 24–48 hours. You'll see the status change to Approved in your Dashboard.

Node key — save it immediately. When your node is approved, a one-time node key appears in your Dashboard. Copy it and store it securely — it is never shown again. This key authenticates your node daemon with the blocnet API.

Step 3 — Run the node daemon

The node daemon does two things: it serves IPFS content at /ipfs/:cid/*, and it sends a heartbeat to the blocnet API every 60 seconds so the gateway knows your node is alive. Any HTTP server that implements this contract qualifies. Here is a minimal reference implementation:

server.js
const express = require('express');
const app = express();

const NODE_KEY     = process.env.BLOCNET_NODE_KEY;
const IPFS_GATEWAY = process.env.IPFS_GATEWAY || 'https://ipfs.io';

// Serve IPFS content — the gateway calls this endpoint
app.get('/ipfs/:cid/*', async (req, res) => {
  const filePath = req.params[0] || 'index.html';
  try {
    const upstream = await fetch(
      `${IPFS_GATEWAY}/ipfs/${req.params.cid}/${filePath}`
    );
    if (!upstream.ok) { res.status(upstream.status).send(); return; }
    res.set(
      'Content-Type',
      upstream.headers.get('content-type') || 'application/octet-stream'
    );
    res.send(Buffer.from(await upstream.arrayBuffer()));
  } catch {
    res.status(502).send();
  }
});

// Heartbeat — tells blocnet your node is alive
async function heartbeat() {
  try {
    await fetch('https://api.blocnet.cc/nodes/heartbeat', {
      method: 'POST',
      headers: { Authorization: `Bearer ${NODE_KEY}` },
    });
  } catch {}
}
setInterval(heartbeat, 60_000);
heartbeat(); // send one immediately on startup

app.listen(process.env.PORT || 3000, () =>
  console.log('blocnet node daemon running')
);

Install the single dependency and start the daemon:

TERMINAL
npm install express
BLOCNET_NODE_KEY=<your-node-key> node server.js

In production, run the daemon under a process manager (PM2, systemd, Docker) so it restarts automatically on crash. Example with PM2:

PM2
npm install -g pm2
BLOCNET_NODE_KEY=<your-node-key> pm2 start server.js --name blocnet-node
pm2 save
pm2 startup   # follow the printed command to auto-start on reboot

Step 4 — Verify the node is online

Once the daemon is running and sending heartbeats, refresh the Nodes tab in your Dashboard. The Last Heartbeat column should show a time within the last two minutes. The blocnet gateway will begin routing traffic to your node automatically — no further configuration needed.

API contract

The blocnet gateway expects two things from your node:

CONTENT ENDPOINT
GET /ipfs/:cid/:filePath

# Example:
GET /ipfs/QmXyZ.../index.html

# Expected: 200 with the file body, correct Content-Type header
# On missing file: 404
# On upstream error: 502 or 500
HEARTBEAT ENDPOINT
POST https://api.blocnet.cc/nodes/heartbeat
Authorization: Bearer <node-key>

# Expected: { "ok": true }
# Send every 60 seconds. Nodes with no heartbeat in the last 5 minutes
# are removed from routing automatically.
Keep your node key secret. Anyone with the key can send heartbeats on behalf of your node. Store it in an environment variable, not in source code.