POSTCARRY 1.0.0 / FIELD GUIDE

Carry the content.
Keep the evidence.

A practical guide to moving a supported Hugo blog into an editable Astro project. Built for maintainers who want a reviewable handoff.

Linux x64 · Node.js 22.12+ · Local browser · No account

What “verified” means. The generated site matched the frozen Hugo baseline for the checked authored articles, supported structure, links, fragments, dates, aliases and resource bytes. It does not certify themes, search ranking, accessibility, deployment, external sites or unsupported content.

1. Your first result

Extract the complete buyer ZIP into a new folder on Linux x64. Install Node.js 22.12 or newer if it is not already available. Open a terminal in the extracted folder and check node --version. The buyer ZIP bundles Linux runtime dependencies and Hugo; no package download is needed for the sample workflow on the tested host.

node start.mjs

Open the printed http://127.0.0.1:PORT address in Chrome. Keep the terminal open. Choose Try Harbor Notebook. Nothing is uploaded to an external service.

Running PostCarry welcome screen with Try Harbor Notebook and Open a baseline
01 · The original fictional sample is available immediately.

Expect four authored pages: two published and two excluded from the build. The published routes are /notes/tide/ and /notes/gear.html. /old-tide/ is an alias to Tide & timber. One original SVG is copied byte for byte.

Choose a page in the left column. Switch between Original Markdown and Carried Markdown. Then choose Build & compare. A sample build takes a few seconds on the tested host; larger projects take longer. Wait for its result before opening another baseline.

Actual Harbor Notebook page review with four pages, two published, one resource and zero findings
02 · Review the source, authoritative route and transformed content together.

2. Capture your own source

Use a trusted local copy of your Hugo project. The capture command below explicitly runs its Hugo templates in a temporary copy. Do not use it on an untrusted downloaded repository. The web app never runs imported templates or npm scripts.

For capture, the single-page template must expose exactly one article containing .Content, and the original title and date. You can add the marker to your existing single template in the copy. The minimum capture template is:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>{{ .Title }}</title>
<body><main>
  <h1>{{ .Title }}</h1>
  <time datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
    {{ .Date.Format "2006-01-02" }}
  </time>
  <article data-postcarry>{{ .Content }}</article>
</main></body></html>

The original sample uses layouts/_default/single.html. This marker isolates authored article content from navigation and theme wrappers; all content inside that marker is compared. Your source requires an explicit, timezone-bearing date on every authored page. Dates and lastmod values retain their textual offsets in exported metadata.

chmod +x tools/hugo
node tools/capture.mjs \
  /absolute/path/to/trusted-hugo-copy \
  /absolute/path/to/new-baseline.postcarry.json \
  2026-10-03T00:00:00Z \
  "$PWD/tools/hugo"

Choose the intended build clock; the example clock is fixed for reproducibility. Keep the new baseline file outside the source folder. Existing output files are never overwritten. The command reads and hashes the source before and after the Hugo build and native page-list capture. If those hashes differ, capture fails. Symlinks are refused. Generated public, resources, node_modules, .git and the Hugo lock at the source root are excluded; other source files are inventoried.

Choose Open a baseline in PostCarry and select the new JSON file. A bare folder or arbitrary Hugo output is insufficient: the source, native HTML, page lists, clock and hashes must travel together.

3. Review, correct, and compare

The plan shows authored-page membership, exact native routes, aliases, resources and findings. Draft and future pages remain in the handoff but are excluded from the published site at the captured clock. Unknown metadata, raw HTML, custom shortcodes and other unsupported constructs stop the migration.

Correction happens in a working source copy. Review the indicated file and line, replace the unsupported construct deliberately, capture a new baseline, then reopen it. PostCarry does not silently delete unknown content or edit your source.

Running PostCarry refusing a gallery shortcode with a source path and line
03 · An unsupported gallery shortcode blocks build and export.

Build & compare builds only PostCarry's generated pinned Astro scaffold. It compares native rendered article text in document order, structural blocks, headings and IDs, code, lists/tables, figure fields, link destinations, timestamps, aliases, local fragments and asset hashes. Syntax-highlighting spans and presentation wrappers are ignored; code characters are retained, with one terminal newline normalized. Prose whitespace is collapsed. External links are compared but never visited.

Actual successful native comparison with downloadable Astro project
04 · Export becomes available only after the native comparison passes.

Hugo and Astro rendering rules are not identical. A build can succeed while comparison fails. In that case, the differences remain visible and export stays blocked. Unsupported typography/rendering variants may require source correction; there is no “ignore and certify” button.

4. Export and reopen

Choose Download Astro project. Extract into a new folder. Keep proof.json and migration-plan.json with the handoff. The latter includes source dispositions, original-to-target routes and resource hashes.

Folder or filePurpose
src/content/posts/Editable Markdown and supported frontmatter.
original-metadata/Exact original frontmatter text, including typed TOML dates and offsets.
unpublished/Converted draft/future Markdown, retained outside published output. Native renders are retained separately in unpublished-rendered/. Draft/future leaf-bundle resources are kept in unpublished-assets/, outside dist/.
public/ and dist/Copied assets and the already built static recipient site.
headings.mjs, routes.jsonNative heading-ID mapping and exact route/alias instructions.
package.json, package-lock.jsonPinned Astro starter dependencies; acquire once when rebuilding independently.

To view the included built site, serve dist with a local static server, for example:

python3 -m http.server 8080 --directory dist

Open http://127.0.0.1:8080/notes/tide/ for the example. The starter adds a neutral article index at / unless an authored route already occupies it; it does not migrate your homepage design, navigation or taxonomy pages. For a fresh independent rebuild of the exported starter:

npm ci
npm run build

The starter's dependency installation requires network access once; its compiled dist is already usable. Use the built site to check exact routes. The development server exposes temporary /carry-generated/ routes before finalization. When intentionally changing headings, update headings.mjs; when changing URLs, update the route map. Any edits invalidate the old proof; recapture and rebuild for new evidence.

Actual generated Astro article with blue tide gauge, caption and retained heading
05 · The recipient gets a working site and editable content, not an image of the old site.

Use Save baseline to retain the frozen project as JSON. Reopen it through Open a baseline to reproduce the transformation. Reopening deliberately resets build proof; run the comparison again. Save and download before closing the terminal. Ctrl+C stops the server and deletes its temporary build folders.

5. Eligibility and boundaries

SupportedExact boundary
MarkdownUTF-8 .md with YAML or TOML frontmatter; standalone pages and leaf bundles. Headings, paragraphs, emphasis, inline links/images, lists, blockquotes, fenced/inline code, GFM tables and strikethrough.
Metadatatitle, description, date, lastmod, draft, slug, url, aliases, tags, categories and publishDate. Dates require explicit RFC3339 timezones. Unknown fields block and remain in the saved source baseline.
ShortcodesAngle-delimited figure, ref, relref and highlight with language only. Figure supports src/alt/title/caption/attr/attrlink/link/target/rel/width/height. Custom classes, percent delimiters and options are refused. Literal shortcode text in code must use Hugo's documented comment escape.
ResourcesLocal PNG, JPEG, WebP, GIF, SVG and PDF in static/ or a leaf bundle. Bytes are copied unchanged. SVG is never executed in the review UI. Check your own assets before deployment.
RoutesNative page-list authority; root-relative slash-terminated or .html paths, aliases and internal fragments. No query-bearing primary routes, traversal, malformed escapes or normalized collisions.
Limits500 Markdown pages; 5,000 source files; 250 MiB source bytes plus published and unpublished native article HTML; 1 MiB each recognized text/native HTML file; 20 MiB binary resource; 360 MiB serialized baseline intake. Limits are rejection boundaries, not a speed guarantee.
ExcludedMultilingual sites, branch-bundle authored pages, modules/mounts, config directories, custom outputs, custom shortcode overrides/render hooks, raw HTML, footnotes, reference-style links, task-list controls, custom typographer mappings and expiry scheduling.

Theme design, homepage, menus, taxonomy styling, RSS, search, comments and deployment are outside this content migration. No universal Hugo compatibility, SEO or accessibility-compliance claim is made. Remote assets are not fetched or checked for availability. Native comparison can reject a rendering variant even when its syntax looks eligible.

Actual PostCarry review at a narrow mobile viewport
06 · The review desk also works in a narrow browser window; desktop is more convenient for long source files.

6. Troubleshooting

Message or symptomNext action
Baseline import failsA new import clears the previous review and proof immediately. Read the error shown in view, repair or recapture the baseline, and reopen it. Build & compare must pass again before download.
esbuild EACCES after extractionRe-extract with a tool that preserves Unix executable permissions, such as unzip. Python zipfile extraction can discard them.
Astro cannot write its config directoryUse a writable XDG_CONFIG_HOME and ASTRO_TELEMETRY_DISABLED=1 when rebuilding the recipient in a restricted environment.
node: command not foundInstall Node.js 22.12+ and reopen your terminal.
Permission denied for tools/hugoRun chmod +x tools/hugo. The bundled binary is Linux x64 only.
Missing article marker/title/dateAdd the documented capture wrapper in your working copy and recapture.
Source hash changedStop editing/build watchers during capture, choose a new output path, then retry.
Unknown field or shortcodeDecide its meaning in your source. This version does not infer custom rendering. Never remove meaningful content merely to obtain a pass.
Unreachable link or missing fragmentRepair the original link/anchor or supply the missing local resource, then recapture.
Build finishes, comparison failsRead the first differing token. Check punctuation, captions, dates and custom rendering. The output has not been verified; export remains disabled.
App cannot resolve dependencyRe-extract the complete Linux buyer archive. For development use npm ci with network access and your writable npm cache.
File already existsChoose a new baseline filename. PostCarry refuses silent overwrites.

7. Privacy, provenance and removal

The app binds to 127.0.0.1, checks exact Host/Origin and a random mutation token, and serves no arbitrary filesystem routes. Imported source is displayed as text. The baseline includes your source files and rendered HTML; do not share it if those are private. The recipient ZIP includes original metadata and excluded drafts/future content—review its contents before sharing.

The bundled sample and illustrations are original fictional material. Runtime screenshots were captured from the running app and generated site on Linux x64, Node 22.22.2, Chrome 152.0.7977.82, Hugo 0.167.0 and Astro 7.3.5. Other hosts and Hugo versions are unverified. Open-source libraries keep their own licenses; see THIRD-PARTY-NOTICES.md and bundled dependency license files.

To uninstall, stop the terminal process, delete the extracted PostCarry folder and any saved baselines/downloads you no longer need. Your original Hugo source was never edited by the app. No account cancellation is needed.