Skip to main content

Posts

These commands apply to the current local project (directory with .micropage/). Posts are authored as local Markdown files in the project's posts/ folder (scaffolded by micropage projects create).

Post files​

Each post is a file at posts/<name>.md: YAML front-matter followed by a Markdown body.

---
title: Hello, world
slug: hello
date: 2026-07-07
description: A short summary for the archive, meta description, and og tags.
visibility: listed
hero: ./hello.jpg
email: true
list: newsletter
subject: Hello, world!
preview: The first post on this site.
---

Body content goes here as standard Markdown.

![alt text](./photo.png)
FieldDescription
titleRequired.
slugOptional. Defaults to the filename minus a leading YYYY-MM-DD- date prefix. Unique per project.
dateOptional. The post's public date: YYYY-MM-DD (midnight UTC) or an ISO 8601 timestamp (no offset means UTC). Past or today only; scheduling isn't supported. Sets the published date of a live post; a draft holds it until first publish. Omitted, the post keeps its current date.
descriptionWeb summary — shown in the /content archive, meta description, and og tags.
visibilitylisted (default, appears in the site's /content index), unlisted (has a page but isn't listed), or none (email only, no web page).
heroOptional. A companion image file named like the post (e.g. hello.jpg next to hello.md), an asset filename, or an absolute URL.
emailSet to true to email the post on publish. Requires list.
listA newsletter form name — the send target.
subjectEmail subject. Defaults to the title.
previewEmail preheader / inbox preview text.

Local image references in the body (![alt](./photo.png)) are auto-uploaded and rewritten to hosted URLs on push.

Post dates​

A post's date defaults to the moment it is first published. Set date: to use a different one:

  • On a published post, push changes its published date, and the /content index and RSS feed reorder to match. A YYYY-MM-DD matching the current published day (UTC) changes nothing, so the original time of day is kept.
  • On a draft, the date is held and applied when the post is first published. Removing date: from the file and pushing again clears the held date, so the post gets its first-publish time instead. micropage posts pull writes a draft's held date into the file, so a pull followed by a push keeps it.
  • On a published post, removing date: keeps the current published date.

push​

Save new and changed local posts. Upserts posts/*.md files as post rows (content only) — does not publish or send email.

# Push every post file
micropage posts push

# Push only these slugs
micropage posts push hello launch

# Show what would happen; uploads and saves nothing
micropage posts push --dry-run
OptionDescription
[slugs...]Push only the posts with these slugs. A slug with no matching file is an error.
-f, --forcePush posts that are skipped or in conflict, overwriting the remote, without the server-side revision check. Recreates a post deleted remotely; for a post renamed remotely, creates a new post under the file's slug.
-n, --dry-runClassify and report only: no image uploads, no saves, no sync record update. Lines read would be created, would be updated (<fields>), plus would upload N image(s) where applicable.

Each file is compared with the remote post and reported as one of:

StateMeaning
createdNo remote post with this slug; saved as a new draft.
updated (<fields>)The file differs from the remote post; saved. Lists the changed fields (title, body, description, hero, visibility, list, email, subject, preview, date).
unchangedPushing would change nothing. Not saved, no images uploaded, no site rebuild.
skippedThe remote post changed since your last push or pull and your file didn't. Run micropage posts pull <slug> to update the file.
CONFLICTBoth the file and the remote post changed since your last push or pull, or the remote post changed while the push was running (the server refuses the save). Not pushed. Save your edits elsewhere, then pull, or overwrite the remote with --force.
skipped, deleted remotelyThe post this file was synced with no longer exists. Remove the file, or recreate the post with --force.
skipped, renamed remotelyThe post this file was synced with now has another slug. Pull it under the new slug and remove this file, or create a separate post with --force.

Saved posts show saved (draft) or saved (live); edits to a published post go live immediately and queue a site rebuild.

posts/hello.md -> "hello": unchanged
posts/launch.md -> "launch": updated (body, hero), saved (live; site rebuild queued)
posts/new.md -> "new": created, saved (draft)
posts/old.md -> "old": skipped, remote changed since last sync (edited in the editor?). Run "micropage posts pull old" to update your file.

1 created, 1 updated, 1 unchanged, 1 skipped, 0 conflict, 0 failed.

Sync record. push and pull remember what each post looked like when last synced in .micropage/posts-sync.json, and use it to tell remote edits (for example in the web editor) from local ones. The record is local to the checkout and ignored if it belongs to another project. A post with no sync record yet (the first push from a checkout, or after posts-sync.json is deleted) is pushed whenever it differs, without the remote-edit check, and reported as updated (<fields>; no sync record, remote edits not checked). A push also records its unchanged posts, and pull records every file it writes or finds already matching. Each save also carries the post's revision as push read it, and the server refuses the save if the post changed since, so an edit made in the editor while a push is running is reported as CONFLICT instead of overwritten. --force skips both checks.

Exit code. push exits non-zero if any post is in CONFLICT, was deleted or renamed remotely, fails to save or parse, or a requested slug has no file. unchanged and skipped (remote changed) posts alone exit 0. --dry-run uses the same rules.

Remote posts with no matching local file are reported as drift but are never deleted.

publish​

Put a post live on the web, and email it if it has a list:.

# Publish one post
micropage posts publish hello

# Publish every local post that is still a draft
micropage posts publish

# Publish an already-published email post again, re-sending the email
micropage posts publish hello --resend

If the post has email: true and a list:, publishing sends the newsletter email to that list. Publishing acts on the saved remote post, so push first.

Without a slug, only drafts are published; already-live posts, and email posts that were already sent, are skipped and no email is re-sent. With a slug, an already-published web-only post is published again (rebuilding the site), but an email post that was already sent is refused unless you pass --resend, even if it was unpublished in between, since publishing it again emails the list's current subscribers and resets the post's click stats.

OptionDescription
--resendAllow publishing an email post that was already sent, which re-sends the email.
-w, --watchStream the site rebuild's deploy events until it's live.

If a site publish or a change of live build replaces the queued rebuild, --watch prints build X superseded by build Y and follows build Y. If nothing replaces it, the watch ends with "nothing further to deploy".

unpublish​

Take a post off the web.

micropage posts unpublish hello

Removes the post's /content/<slug> page. The post itself is not deleted — it remains as a draft.

pull​

Write remote posts down to local posts/*.md files.

# Pull every remote post
micropage posts pull

# Pull only these slugs
micropage posts pull hello launch

The database is the source of truth for posts; run this before editing to avoid clobbering remote changes.

Files that already match the remote post are reported as unchanged and left alone. Any other existing file prompts before being overwritten; -f, --force overwrites without prompting. A requested slug with no remote post is an error. Each file written or found matching is recorded in the sync record.

Pulled files include list: (for email posts whose newsletter form still exists), subject: (when it differs from the title), and preview:, so pushing a freshly pulled file changes nothing. For published posts, date: is written as the UTC day of the published date.

list​

List the project's posts.

micropage posts list

Shows slug, title, visibility, emailed, status (Draft/Published), and created date.

rm​

Delete a post entirely (remote).

micropage posts rm hello

Typical workflow​

# Write a new post
nano posts/hello.md

# Save as a draft
micropage posts push

# Go live and email the list (if `list:` is set)
micropage posts publish hello

# Later: edit the file, push the update (goes live immediately)
nano posts/hello.md
micropage posts push

# Re-send the newsletter for the update
micropage posts publish hello --resend

# Take the post down (keeps it as a draft)
micropage posts unpublish hello