A CLI tool for publishing Markdown files and folders directly to FlowerShow with OAuth authentication.
Note: This package was previously named
flowershow. If you're migrating from the old package, see the Migration Guide.
npm install -g flowershow-publish@latestThen use the publish command anywhere:
publish auth login
publish ./my-notesBefore using any commands, you must authenticate:
publish auth loginThis will:
- Display a URL and verification code
- Open your browser to authorize the CLI
- Store your authentication token locally
# Publish a folder
publish ./my-notes
# Publish a single file
publish ./my-note.md# Sync a folder site
publish sync ./my-notes
# Sync a single file site
publish sync ./my-note.mdAuthenticate with FlowerShow via browser OAuth flow.
publish auth loginCheck your current authentication status.
publish auth statusRemove your stored authentication token.
publish auth logoutSee Authentication Documentation for detailed information.
Publish files or folders to FlowerShow.
Options:
--overwrite- Overwrite existing site if it already exists--name <siteName>- Custom name for the site (defaults to file/folder name). Note: If you use it, you need to pass it also to thesynccommand later on, so that Flowershow knows content of which site you're trying to sync.
Examples:
# Publish a single markdown file
publish ./my-note.md
# Publish multiple files
publish ./intro.md ./chapter1.md ./chapter2.md
# Publish a folder
publish ./my-notes
# Overwrite an existing site
publish ./my-notes --overwrite
# Publish with a custom site name
publish ./my-notes --name my-custom-site
# Combine options
publish ./my-notes --name my-custom-site --overwriteWhat happens:
- Files are discovered and filtered (ignores
.git,node_modules, etc.; also supports.gitignoreand will ignore paths listed there) - Project name is derived from the first file name or the folder name
- Site is created via the FlowerShow API
- Presigned URLs are obtained for secure file uploads
- Files are uploaded directly to Cloudflare R2 storage
- CLI waits for markdown files to be processed
- Site URL is displayed
Single file behavior:
- Filename becomes the project name (e.g.
publish about.mdwill create a site namedabout) - File is saved as
README.md(orREADME.mdxdepending on the original file extension) - Site accessible at
/@{username}/{filename}(e.g./@johndoe/about)
Multiple files behavior:
- First filename becomes the project name (e.g.
publish about.md team.md abc.mdwill create a site namedabout) - First file is saved as
README.md(orREADME.mdx) - Subsequent files keep their original names
- Site accessible at
/@{username}/{first-filename}(e.g./@johndoe/about)
Folder behavior:
- Folder name becomes the project name (e.g.
publish my-digital-garden/blogwill create a site namedblog) - All files maintain their relative paths
- Site accessible at
/@{username}/{foldername}(e.g./@johndoe/blog)
Sync changes to an existing published site. Only uploads new or modified files, and deletes files that no longer exist locally.
Options:
--name <siteName>- Specify site name if different from folder name--dry-run- Show what would be synced without making changes--verbose- Show detailed list of all files in each category
Examples:
# Sync changes to a folder
publish sync ./my-notes
# Preview changes without syncing
publish sync ./my-notes --dry-run
# Show detailed file lists including unchanged files
publish sync ./my-notes --verbose
# Sync to a specific site name
publish sync ./my-notes --name my-custom-site
# Combine options
publish sync ./my-notes --dry-run --verboseWhat happens:
- Files are discovered and SHA hashes calculated
- File list is sent to the API for comparison
- API compares with existing files and determines:
- New files (not in database)
- Modified files (different SHA hash)
- Deleted files (in database but not in request)
- Unchanged files (same SHA hash)
- Sync summary is displayed
- Only new/modified files are uploaded
- Deleted files are removed by the API
- CLI waits for markdown files to be processed
- Site URL is displayed
When to use sync vs publish:
- Use
publishfor initial site creation or complete site replacement - Use
syncfor updates to existing sites
List all sites published by your authenticated user.
publish listShows site names, URLs, and timestamps.
Delete a site and all its files.
publish delete my-notesRemoves the site and all its files via the FlowerShow API.
The CLI automatically ignores common non-content files and directories:
.git/,node_modules/,.cache/,dist/,build/.DS_Store,Thumbs.db.env*,*.log.next/,.vercel/,.turbo/
If .gitignore file is present in the published folder, the Flowershow CLI will also ignore files matched by it.
All CLI-published sites are accessible at:
https://my.flowershow.app/@{username}/{project-name}
Where {username} is your authenticated username.
Run publish auth login to authenticate.
Your token may have been revoked. Re-authenticate:
publish auth loginA site with that name already exists. You can:
- Use the
--overwriteflag:publish <path> --overwrite - Delete it first:
publish delete <name> - Rename your file/folder
- Use
publish listto see all existing sites - Or use
publish syncto update an existing site incrementally
The sync command requires the site to already exist. If you get this error:
- Use
publishto create the site first - Check the site name with
publish list - Specify the correct site name with
--name
The site is live, but some pages may not be ready yet. The Cloudflare worker processes files asynchronously. Check your site again in a moment.
All CLI commands communicate with the Flowershow API:
- Authentication: OAuth device flow endpoints
- Site Management: Create, list, and delete sites
- File Upload: Presigned URL generation and status polling
- User Info: Retrieve authenticated user details
- Token Storage: Authentication tokens are stored in
~/.flowershow/token.json - Token Format: CLI tokens use the
fs_cli_prefix - Token Expiration: Tokens do not expire by default
- Token Revocation: Revoke tokens from the Flowershow dashboard or via
flowershow auth logout - Secure Uploads: Files are uploaded using time-limited presigned URLs
- No Credentials: CLI never stores database or storage credentials
- Clone and install dependencies:
cd cli
pnpm install- Configure environment:
Use local or other non-production API and publish URLs.
cp .env.example .envAPI_URL="http://cloud.localhost:3000"
APP_URL="http://my.localhost:3000"- Run commands:
pnpm dev auth login
pnpm dev ./my-notes
pnpm dev sync ./my-notesYou can also build the project, link it globally and use it as you normally would the npm-installed version:
pnpm build
npm link
publish ...