Skip to content
On this page

Using poplin ​

Every command, every agent tool, and every refusal, each with one example. To get an install first, see Install.

text
You:    Put this report online.           ->  the agent calls publish_site
You:    Share it with anyone I send it.   ->  the agent calls update_site, access unlisted
You:    Take it down.                     ->  the agent calls delete_site

An agent uses the tools. A person uses the commands. Both do the same things.

How a site is named ​

text
report--k3f9x2ab71qz
|       |
|       the id: 12 random characters
the name: taken from the folder or the file

That is the label. Every command and tool takes it to name one site. The bare id (k3f9x2ab71qz) works too, and so does the public name of a public site (docs).

Publish ​

ExampleDoes
poplin ./reportmakes a new site, private, from a folder
poplin ./report.htmlmakes a new site from one HTML file
poplin ./report --site report--k3f9x2ab71qzputs new content on that site; the address stays
poplin ./report --name q3-reportmakes a new site with that name
poplin ./demo --unlisted --expires 7dmakes a new site with settings (see below)
poplin ./report --dry-runlists the files and the name, and uploads nothing
text
$ poplin ./report
uploaded 3 files, 48 KB
made  report--k3f9x2ab71qz  private
https://report--k3f9x2ab71qz-p-poplin.example.com
  • No --site means a new site, every time. Keep the label and pass it to update.
  • A folder needs an index.html at its top.
  • Not uploaded: hidden files (a name that starts with a dot) and anything named node_modules.
  • A name is 3 to 40 lowercase letters, digits, and single dashes.
  • Ctrl-C stops a publish, an import, or a copy: the upload on its way is given up, so its site is not made or changed, and the command exits 1. A second Ctrl-C ends it at once.

Who can open a site ​

AccessWho can open itSet it with
privateonly you, after a loginpoplin set report--k3f9x2ab71qz --private
unlistedanyone who has the linkpoplin set report--k3f9x2ab71qz --unlisted
publiceveryonepoplin set report--k3f9x2ab71qz --public
ExampleDoes
poplin set report--k3f9x2ab71qz --publicpublic at its own name: report-page.example.com
poplin set report--k3f9x2ab71qz --public --public-name docspublic at another name: docs-page.example.com
  • To or from private changes the address: the letter before -poplin turns from p to u, or back. The old address sends visitors on.
  • A public site keeps its unlisted address too.
  • Leaving public gives the public name up. That address stops working.

The address shows each part of an address. Security says what each access protects.

Other settings of a site ​

A publish takes these flags too.

ExampleDoes
poplin set report--k3f9x2ab71qz --name q3-reportrenames it; its id and every address stay
poplin set report--k3f9x2ab71qz --title "Q3 sales"sets the title your dashboard shows
poplin set report--k3f9x2ab71qz --expires 7dmoves it to the trash in 7 days
poplin set report--k3f9x2ab71qz --expires 2026-12-01moves it to the trash on that day
poplin set report--k3f9x2ab71qz --expires neverkeeps it
poplin set report--k3f9x2ab71qz --search-engines onlets search engines list it, once it is public
poplin set report--k3f9x2ab71qz --embeddable offstops other pages from showing it in a frame
ExampleDoes
poplin listlists every site
poplin list --trashlists the deleted sites
poplin show report--k3f9x2ab71qzshows one site: its address, its settings, its kept versions
poplin rollback report--k3f9x2ab71qzmakes the version before live again
poplin rollback report--k3f9x2ab71qz --to 3makes version 3 live again
poplin new-link report--k3f9x2ab71qzgives the site a new id; the old address stops at once
poplin duplicate report--k3f9x2ab71qzmakes a private copy, with a new address
poplin delete report--k3f9x2ab71qzmoves the site into the trash
poplin restore report--k3f9x2ab71qztakes it back out of the trash
poplin delete report--k3f9x2ab71qz --foreverremoves it now, after you type its label; nothing restores it
  • Versions: an install keeps a few per site. poplin config versions_kept shows how many.
  • Trash: a deleted site waits some days, then it is gone. poplin config trash_days shows how many.
  • A new link is for an address that reached the wrong person. A public site keeps its public name.
  • Pages opened: poplin show report--k3f9x2ab71qz says about how often a site's pages were opened, today and in the last 7 days. The numbers come from a sample, so they read about 120. A page a browser shows from its own copy, inside 5 minutes, is not counted.

Back up and put back ​

ExampleDoes
poplin exportdownloads every site and the settings as one zip
poplin export --all-versions --out backup.zipadds the kept versions, and names the zip
poplin export report--k3f9x2ab71qzdownloads one site
poplin export --out backup.zip --overwritereplaces a zip that is already there
poplin import backup.zipputs the sites of a zip back
poplin import backup.zip --dry-runchecks the zip, lists its sites, and imports nothing
poplin import backup.zip --site report--k3f9x2ab71qzputs one site back
poplin import backup.zip --settingsreplaces the install's settings too, but for the logins
poplin import backup.zip --settings --loginsreplaces the logins as well
  • The zip holds plain files. It holds no token and no signing key.
  • Nothing is overwritten. A site the install already has is skipped.

This computer ​

ExampleDoes
poplin login --server https://poplin.example.comlogs this computer in: you allow it in your browser
poplin login --publisher --name ci-runnersaves a login that manages only the sites it publishes
poplin login --no-browserprints the address and opens no browser
poplin whoamiprints the install, the role, and when the login runs out
poplin logoutrevokes the login and forgets it
text
$ poplin login --server https://poplin.example.com
  ->  prints an address and a short code
  ->  you open the address, check that the code is the same, and allow it
  ->  the login is saved on this computer

An install begins five logins a minute for all computers together. In a minute that is full, poplin login waits and asks again.

POPLIN_SERVER and POPLIN_TOKEN in the environment stand in for a saved login.

The install ​

ExampleDoes
poplin configshows every setting
poplin config versions_keptshows one setting
poplin config versions_kept 10changes one setting
poplin doctorchecks that the install answers; changes nothing
poplin setup --server https://poplin.your-name.workers.dev --domain example.com --login you@example.comfinishes a new install, as its setup page does
poplin setup --check --server https://poplin.your-name.workers.devlists what that would change, with the same flags; changes nothing
poplin help rollbackshows the help of one command

poplin setup reads the Cloudflare API token from POPLIN_SETUP_TOKEN in the environment. A new install needs --domain and --login. On an install that has them, --login alone corrects a first login that was mistyped. It needs no login, and it works only until the first login to the install. Install shows where it fits.

The settings poplin config takes:

SettingHolds
default_expires, default_search_engineswhat a new site starts with
versions_kept, trash_dayshow much is kept, and for how long
loginsthe emails that may log in
dashboard_titlethe dashboard's title
outside_pages, search_engines_allowed, block_botswhat the install lets in
max_total_size, max_site_size, max_sitessize limits
max_files_per_publish, max_files_per_dayhow many files one publish holds, and all publishes begun in one UTC day
requests_per_day, site_share_of_day, site_requests_per_minute, visitor_requests_per_minuterequest limits

An import and a copy count as a publish, with every version an import holds. A publish that is given up or runs out gives none of the day's files back.

Every command that talks to the install also takes --json, for the answer as JSON, and --server, to name the install.

The agent tools ​

poplin mcp runs the MCP server on this computer. An agent starts it and calls these tools:

ToolExample inputSame as
publish_site{ "path": "./report" }poplin ./report
publish_site{ "path": "./report", "site": "report--k3f9x2ab71qz" }poplin ./report --site report--k3f9x2ab71qz
update_site{ "site": "report--k3f9x2ab71qz", "access": "unlisted" }poplin set report--k3f9x2ab71qz --unlisted
get_site{ "site": "report--k3f9x2ab71qz" }poplin show report--k3f9x2ab71qz
list_sites{ "trash": true }poplin list --trash
rollback_site{ "site": "report--k3f9x2ab71qz", "version": 3 }poplin rollback report--k3f9x2ab71qz --to 3
new_link{ "site": "report--k3f9x2ab71qz" }poplin new-link report--k3f9x2ab71qz
delete_site{ "site": "report--k3f9x2ab71qz" }poplin delete report--k3f9x2ab71qz
restore_site{ "site": "report--k3f9x2ab71qz" }poplin restore report--k3f9x2ab71qz
duplicate_site{ "site": "report--k3f9x2ab71qz" }poplin duplicate report--k3f9x2ab71qz
  • publish_site and update_site take the site settings: name, access, public_name, title, search_engines, embeddable, expires.
  • delete_site with "forever": true removes the site at once, with no trash.
  • The agent's rules are in the skill: skills/poplin/SKILL.md.

What a visitor sees ​

A visitor opensSees
an unlisted or a public sitethe site
a private site, logged in as youthe site
a private site, not logged inthe login
the -poplin address of a deleted or expired site, or one from before a new linkthe login; Not found once logged in
a public name no site holdsNot found
any site, too often in a minuteToo many requests. Try again in 60 seconds.
any site, once the day's free allowance of the database for reading is used upThis site is paused until midnight UTC.

When poplin refuses ​

A refused command prints one sentence and often a hint. With --json it prints an object with a code. A tool answers with the same object.

Logging in, and reaching the install

CodeMeansWhat to do
no_login, no_serverthis computer has no loginpoplin login --server https://poplin.example.com
not_logged_inthe login ran outpoplin login
login_denied, login_expired, interruptedthe login was not allowed; nothing was savedpoplin login again, and allow it in the browser
bad_loginthe saved login cannot be usedpoplin login again
bad_server--server takes an https:// address, host only--server https://poplin.example.com
wrong_serverthe login is for another installlog in to this one with --server
not_allowedthis login may not do thatpoplin whoami shows the login; use an admin's
not_set_upthe install has stored no settingstry again; if it stays, deploy the install again
no_working_loginthe new logins would let nobody log inkeep one email that is a login now in the list
unreachable, timeoutno answer camecheck the address and the network; poplin list before a retry
not_json, unexpected_answerthe answer is not a poplin install'spoplin whoami shows the address in use
method_not_allowed, unsupported_media_typethe install and this poplin are of two versionsupdate the older one
too_many_requestsasked too oftenwait a minute
allowance_spentthe day's free allowance of the database is used upwait until 00:00 UTC; asking sooner is refused the same way
internal, crashedsomething failedtry again; poplin doctor reports on the install

Setting up an install

CodeMeansWhat to do
no_setup_serverpoplin setup was given no addresspoplin setup --server https://poplin.your-name.workers.dev
no_setup_tokenPOPLIN_SETUP_TOKEN holds no tokenput the token of Install, step 3, in it
setup_token_refusedthe token was refused, or it is of another accountmake one with the rights step 3 lists, in the install's account
setup_provider_silentCloudflare gave the install no answertry again
setup_no_domainthe token shows no such domaingive --domain a domain that is Active in the token's account
setup_bad_domain--domain holds more than a domainthe domain alone: --domain example.com
setup_bad_login--login holds no email addressa new install needs both: --domain <domain> --login <email>
setup_closednothing at that address takes a setupafter the first login, use the dashboard's Domain tab

Naming a site

CodeMeansWhat to do
not_foundno site with that label or public namepoplin list
in_trashthe site is in the trashpoplin restore report--k3f9x2ab71qz
not_in_trashthe site is not in the trashnothing
no_such_versionthe site keeps no such versionpoplin show report--k3f9x2ab71qz lists them
name_taken, reserved_namethe public name is heldpoplin set report--k3f9x2ab71qz --public --public-name docs
bad_namethe name breaks the rules3 to 40 lowercase letters, digits, and single dashes
bad_argumentan argument is missing or malformedpoplin help set shows what a command takes
usage-errorthe command line names something unknownpoplin help lists every command
not_confirmedthe label you typed is not the site'snothing was deleted; run it again
no_terminal--forever needs a terminal to ask ondelete without it: the site goes to the trash

Publishing

CodeMeansWhat to do
unreadablethe path cannot be publishedcheck the path
no_indexthe folder has no index.html at its topadd one, or publish one HTML file
no_namethe path gives no namepoplin ./report --name q3-report
bad_patha file's path cannot be servedrename or remove that file
too_largea size limit is passedpoplin config shows the limits
too_many_sitesthe install holds as many sites as it maypoplin config max_sites; poplin list --trash still counts
size_mismatch, stale_version, missing_filesthe publish did not complete; nothing went livepublish again
upload_finishedthe publish is already livenothing
stoppedyou stopped the command with Ctrl-Crun it again; an upload not given up runs out in about a day

Backups

CodeMeansWhat to do
file_existsthe zip is already therepoplin export --out backup.zip --overwrite
unwritablethe zip cannot be writtenname another place with --out
other_formatthe install's backups are newer than this poplinupdate poplin
site_changeda site changed while it was exportedexport again
bad_backupthe file is not a backup; nothing was sentpass a zip that poplin export made
backup_too_newthe backup is newer than the installupdate the install, then import again
no_settingsthe zip is one site's backup: it has no settingsimport it without --settings
not_in_backupthe zip holds no such sitepoplin import backup.zip --dry-run
id_takenthe install already has that sitepoplin show report--k3f9x2ab71qz
Built from main at d4f6e86Source: docs/using.md