Publish Croptop sites to IPFS from Linux, macOS, or Windows. One binary with an IPFS node built in: it renders your posts with the Croptop template, adds them to IPFS, and keeps your site's IPNS name pointing at the latest version. The console runs in your browser, so the same thing works from a phone on your network.
This is a port of the Croptop scheme of the Planet Mac app. It reads and writes the same files, so you can move a library over from the Mac app and back.
One line, any platform:
curl -fsSL https://crop.top/install.sh | sh # macOS and Linuxirm https://crop.top/install.ps1 | iex # WindowsOr pick what fits:
- macOS app: download
Croptop.dmgfrom the latest release, drag Croptop to Applications. It is not notarized yet: the first launch is blocked, then System Settings, Privacy & Security shows an Open Anyway button for it. - Homebrew:
brew install mejango/tap/croptop - Windows installer:
croptop-setup.exefrom the latest release. Windows will show a SmartScreen notice because the installer is unsigned; choose More info, Run anyway. - Debian, Ubuntu: the
.debfrom the latest release. Fedora: the.rpm. - Plain binary: the
.tar.gzor.zipfor your platform.
Croptop updates itself: the console shows a banner when a new release is out, and croptop update does the same from a terminal.
croptop
The first start creates the node's identity and blockstore and opens
http://127.0.0.1:8086. Data lives in:
| OS | Data directory |
|---|---|
| macOS | ~/Library/Application Support/croptop |
| Linux | ~/.config/croptop |
| Windows | %AppData%\croptop |
Pass --data <dir> to use another location. Keep the console running while
you want the site served from your machine; every ten minutes it renews the
IPNS record.
With the Croptop Mac app installed on the same Mac:
croptop import-planet
This copies every site, its posts and files, and the IPNS keys out of the
app's container. It only reads, so the Mac app can keep running. Generated
files such as nft.json are kept byte for byte, so posts already sold as
NFTs keep their onchain metadata CIDs.
The first publish from croptop reads the current sequence number of the
IPNS record from the network and publishes above it, so the Mac app's
copy is superseded cleanly. Quit the Mac app afterwards, or it will notice
it is no longer the publisher and stop.
A site is its IPNS key. Everything else is on IPFS.
On the machine you have now, open the site's settings and use Show key
(or croptop key export <site>). On the new machine:
croptop adopt yoursite.eth --key site.pem
or use Adopt a site in the console and paste the key. Croptop fetches the published site, rebuilds the editable files from it, learns the current sequence number, and takes over. The old machine does not fight over the name: it takes in what the new one publishes.
Two machines can share a site. A running console takes in what the other
one publishes by itself: within a minute when both push to the same host,
within ten minutes otherwise. It downloads only the posts that are new or
changed, newest edit per post wins, and a post deleted here stays deleted.
Sync (or croptop sync <site>) does the same at once, then publishes from
here.
Keep a copy of the key somewhere safe. It is the only thing IPFS cannot give back.
An agent, a CI job, or any machine that keeps nothing between runs can post with the site's key alone: no copy of the site and no gateway of your own. docs/agents.md is the short version to hand to a bot. Export the key once and store it as a secret:
croptop key export yoursite > site.pem
Then on each run:
croptop post --key site.pem --title "Shipped the fix" --content "What changed, in **markdown**." --tags agent screenshot.png
post --key builds on the version crop.top holds (or --host, for a site
that pushes to its own host; the agent and your machine should use the
same one) and uploads only what
changed: the new post, planet.json, rss.xml, and a page for any new
tag. Every other file stays as your machine rendered it, and the upload is
the size of the post, not of the site. What it reads from crop.top is
checked against the version's CID. crop.top keeps the new version,
announces it, and renews its name every half hour, so the worker can exit
when the command returns.
If the site changed while the agent was posting, crop.top refuses the post
and nothing is lost: run it again. The site must have been published once
from the console, which pushes it to crop.top. If an older croptop made
that publish, publish once more with this one: planet.json then carries
the settings a post page needs (gateway, ENS or custom domain, claimed
name, custom code), so the agent's pages match yours. A console running
on your machine takes the agent's posts in within a minute.
croptop follow yoursite.eth or an IPNS name, or Follow a site in the console
Your node fetches the site, keeps it, serves it at /f/<ipns>/, checks
for a new version every six hours, and re-announces it to the network every
twelve. A site stays online because its readers host it. Each of your own
sites shows how many nodes are hosting it.
Every site renders with the built-in Croptop template until you say
otherwise. On a site's Template page, Fork to edit copies the template
into the site, where you can change any file with the rendered preview
beside you; Reset brings the original back. Template authors publish a
template directory with croptop template publish <dir> and share the
CID; anyone installs it with croptop template install <cid or ENS name>
or from the same page. The template context is documented in
docs/format.md.
A post is HTML, and its attachments travel with it. Attach a script, add
<script type="module" src="widget.js"></script> to the post, and it runs
on the published page with window.croptop for the site, the post, the
template settings, the chain table, the reader's wallet, and IPFS. The
editor's widget palette inserts starter snippets. See docs/widgets.md.
croptop passcode set
croptop serve --role node --listen 0.0.0.0:8086
runs headless on a Raspberry Pi or a small server: it keeps your IPNS
records alive, re-provides your sites and the ones you follow, and takes
edits from the console opened from a laptop or phone. croptop status
prints what it is doing.
Set a passcode, then listen on all interfaces:
croptop passcode set
croptop --listen 0.0.0.0:8086
Sign in as user Croptop with the passcode. Over the internet, put the
machine on Tailscale or similar rather than
opening the port. The published site trees at /<site-id>/ are always open;
everything else needs the passcode.
Two engines are built in. embedded (the default) runs an IPFS node inside
croptop itself, built on boxo, kubo's own libraries: no download, no child
process, same CIDs, same IPNS records, NAT traversal through relays and
hole punching. kubo downloads and runs kubo v0.43.0 as a child process
instead. Switch with croptop --engine kubo; the choice is remembered.
Keys are shared between engines, so switching back and forth is safe.
A publish uploads only what changed since the version the site's host holds: the changed files plus a list of what to keep, so deleted posts go too. The first upload of a site sends everything, in the background, and survives a slow link or a sleeping laptop: it stops only when nothing moves for two minutes, and the next try resumes where it stopped.
A publish writes the IPNS record to the DHT and the IPNS pubsub topic. The
embedded engine also sends it to crop.top's routing endpoint (and to
delegated-ipfs.dev while it lasts), and joins the network through the default
bootstrap peers, crop.top's node, and the peers it was connected to last
time. crop.top shows a pushed version within a minute. eth.sucks, eth.shop
and eth.limo keep their own resolution caches and can show the previous
version for a long while after that, whichever engine published; the
console's site page links the version the network holds. Set
CROPTOP_DEBUG=1 to see the engine's log lines.
croptop host makes a server a gateway and pin host for a domain, the way
crop.top runs. Sites push to it on publish and stay up while your computer is
closed. See docs/host.md.
croptop run the console (default)
croptop import-planet copy sites and keys from the Croptop Mac app; run again any time to merge posts made there since
croptop adopt <name> --key f take over a published site
croptop sync <site> merge the network's version, then publish
croptop publish <site> render, add to IPFS, update the IPNS name
croptop key export <site> print the site's private key
croptop key import <site> f install a key for a site you already have
croptop post --key f --title t [--content c] [--tags a,b] [--host url] [files]
post with only the key; see Posting from an agent
croptop passcode set
croptop template list | install <cid or name> | publish <dir>
croptop engine print the active ipfs engine
croptop version
--force on publish overrides the "published elsewhere" and
"network unreachable" checks.
The console speaks Planet's REST API at /v0 (see Planet's
Technotes/API.md), so Planet's pn CLI and other clients work. The
console's own routes live under /v0/croptop/.
Selling a site's posts into a Juicebox project (pointing its collection addresses at a project's NFT hook and opening posting) is a recipe in docs/selling-posts.md; shop creation and the wallet flows are in docs/shop-creation.md.
Sites are reachable through any gateway that resolves ENS and IPNS names: eth.sucks, eth.shop, eth.limo, and more as they appear. Each site picks one as its canonical address in Settings; that one is written into the site's absolute links and RSS feed. The default is eth.sucks.
Aggregating other sites, Filebase/Pinnable/Cloudflare pinning, drafts,
the podcast feed (rss.xml is generated, podcast.xml is not), HEIC
images, video compression, full-text search, following other sites. Video
thumbnails are generated only when ffmpeg is on your PATH.
The published file layout is documented in docs/format.md.
The site template is the git submodule templates/croptop
(SiteTemplateCroptop),
embedded into the binary. To work on the template, point at a checkout:
go run ./cmd/croptop --templates ../SiteTemplateCroptop --data .data
go test ./... runs everything; the tests that need kubo look for a
downloaded binary under .data/kubo and skip otherwise.
MIT. The bundled Press Start 2P font is under the SIL Open Font License.
On macOS, Croptop.app is a window around the console. While it is open your IPFS node runs; quit it and the node stops. Drop images, video or audio on its Dock icon or into the window and it opens a new post with them attached: pick the site, add a title, a few words and tags, then post, or post and publish. Click the icon to open the console. Keep it in the Dock (right-click, Options, Keep in Dock) and add it to your Login Items if you want the node up from login on.
From a terminal, croptop post photo.jpg clip.mp4 does the same. For a machine without the app (a server, Linux), croptop service install keeps the console running from login on through launchd or a systemd user unit; croptop service status and uninstall do what they say. The app and the service do not mix: opening the app removes the service and takes over.
The Mac app is signed and notarized with Developer ID when the release is built with signing credentials; see docs/signing.md.