Site Rescue is a platform-neutral, CLI-first, local-first toolkit for rescuing websites from hosted platforms that are shutting down or becoming inaccessible. Weebly is the first source adapter; it is not the architecture of the product.
Site Rescue
v0.1.0is the first public release and is licensed under Apache-2.0.
- Versioned normalized content schema with runtime validation
- Platform-neutral source-adapter contract and deterministic registry selection
- Bounded, deterministic, same-origin HTML crawler
- Shared bounded HTTP retry, timeout, and response-body policy for HTML and assets
- Fresh-output-only lifecycle for capture, export, report, and end-to-end rescue commands
- Self-contained Node.js CLI release package with SHA-256 inventory and smoke verification
- Apache-2.0 project licensing with bundled third-party license and NOTICE preservation
site-rescue --versionrelease-version command- Weebly detection with confidence and human-readable evidence
- Generic HTML fallback detection and standards-based content normalization
site-rescue diagnose <url>CLI commandsite-rescue capture <url>normalized JSON capture commandsite-rescue export <site.json>platform-neutral static HTML export commandsite-rescue report <site.json>migration readiness and manual-review report commandsite-rescue verify <site-directory>offline static link and asset verification commandsite-rescue manifest <rescue-directory>deterministic whole-bundle SHA-256 manifest commandsite-rescue verify-bundle <rescue-directory>offline rescue bundle integrity commandsite-rescue preview <site-directory>verified local HTTP preview commandsite-rescue rescue <url>end-to-end local capture, static export, report, verification, and bundle manifest command- Content-addressed asset downloads with SHA-256 checksums and duplicate-file reuse
- Bounded CSS
@importandurl()dependency discovery with local reference rewriting - Local path rewriting for normalized image, gallery, and video blocks
- Static pages with local navigation, responsive baseline CSS, and verified asset copies
- Explicit
baselineorsourcestatic export style modes with safe baseline fallback - Same-origin redirect preservation with normalized 301 mappings and duplicate-page prevention
- Deterministic
redirects.jsonhandoff manifests and offline-verifiable HTML fallback pages - Deterministic
rescue-manifest.jsoninventories for capture, site, and report artifacts - Offline fixture tests for schema, crawling, adapter detection, and CLI orchestration
- Node.js 20.19 or newer (the CI baseline is recorded in
.node-version) - pnpm 10.34.5 (recorded in
packageManager)
Download site-rescue-v0.1.0.zip and site-rescue-v0.1.0.zip.sha256 from the v0.1.0 GitHub Release. The archive contains a bundled CLI and does not require pnpm or a dependency installation, but it still requires Node.js 20.19 or newer.
Verify and extract on PowerShell:
Get-FileHash .\site-rescue-v0.1.0.zip -Algorithm SHA256
Get-Content .\site-rescue-v0.1.0.zip.sha256
Expand-Archive .\site-rescue-v0.1.0.zip
node .\site-rescue-v0.1.0\bin\site-rescue.js --version
node .\site-rescue-v0.1.0\bin\site-rescue.js --helpVerify and extract on macOS or Linux:
shasum -a 256 -c site-rescue-v0.1.0.zip.sha256
unzip site-rescue-v0.1.0.zip
node site-rescue-v0.1.0/bin/site-rescue.js --version
node site-rescue-v0.1.0/bin/site-rescue.js --helpThe source archive generated automatically by GitHub is not the bundled CLI release package.
pnpm install
pnpm site-rescue --version
pnpm site-rescue diagnose https://example.weebly.com
pnpm site-rescue diagnose https://example.com
pnpm site-rescue rescue https://example.weebly.com --output ./rescued-site
pnpm site-rescue rescue https://example.weebly.com --output ./styled-rescue --style-mode source
pnpm site-rescue capture https://example.weebly.com --output ./capture
pnpm site-rescue export ./capture/site.json --output ./site
pnpm site-rescue export ./capture/site.json --output ./styled-site --style-mode source
pnpm site-rescue report ./capture/site.json --output ./report
pnpm site-rescue verify ./site
pnpm site-rescue manifest ./rescued-site
pnpm site-rescue verify-bundle ./rescued-site
pnpm site-rescue preview ./siteThe one-step command keeps reusable capture data separate from the generated website:
rescued-site/
├─ rescue-manifest.json
├─ capture/
│ ├─ site.json
│ └─ assets/
├─ site/
│ ├─ index.html
│ ├─ redirects.json
│ ├─ assets/
│ └─ ...
└─ report/
├─ migration-report.json
└─ migration-report.md
Skip binary asset downloads when only a normalized capture document is needed:
pnpm site-rescue capture https://example.weebly.com --output ./capture --skip-assetsLimit discovery when testing a large site:
pnpm site-rescue diagnose https://example.weebly.com --max-pages 20Tune bounded request reliability when a source server is slow or unstable:
pnpm site-rescue diagnose https://example.weebly.com --max-retries 3 --request-timeout-ms 20000 --max-html-bytes 8388608capture, export, report, and rescue require a new output directory. If the path already exists, the command stops before changing it. A failed run removes only the new directory created for that run.
After building, the CLI entry point can also be run directly:
pnpm build
node apps/cli/dist/index.js diagnose https://example.weebly.com
node apps/cli/dist/index.js rescue https://example.weebly.com --output ./rescued-site
node apps/cli/dist/index.js rescue https://example.weebly.com --output ./styled-rescue --style-mode source
node apps/cli/dist/index.js capture https://example.weebly.com --output ./capture
node apps/cli/dist/index.js export ./capture/site.json --output ./site
node apps/cli/dist/index.js export ./capture/site.json --output ./styled-site --style-mode source
node apps/cli/dist/index.js report ./capture/site.json --output ./report
node apps/cli/dist/index.js verify ./site
node apps/cli/dist/index.js manifest ./rescued-site
node apps/cli/dist/index.js verify-bundle ./rescued-site
node apps/cli/dist/index.js preview ./sitePrepare and verify the self-contained release candidate package:
pnpm build
pnpm release:check
node release/package/bin/site-rescue.js --version
node release/package/bin/site-rescue.js --helpThe generated release/package directory is ignored by Git. It contains one bundled CLI entry point, Apache-2.0 project licensing, third-party runtime notices, release metadata and documentation, a source map, and SHA256SUMS.txt.
capture/site.json contains site metadata, navigation, normalized pages and blocks, an asset manifest, redirects, and warnings. Successfully downloaded files are stored under capture/assets/; each manifest entry retains its original sourceUrl and adds localPath, mediaType, and a SHA-256 checksum. Failed downloads remain as source URLs and produce asset-download-failed warnings without aborting the rest of the capture.
Example output:
Site Rescue diagnosis
URL: https://example.weebly.com/
Platform: Weebly (100% confidence)
evidence: Hostname is on weebly.com
evidence: Generator metadata names Weebly
Discovered pages (3):
- /
- /about.html
- /contact.html
site-rescue/
├─ apps/
│ └─ cli/ # Thin command-line application
├─ packages/
│ ├─ content-schema/ # Platform-neutral normalized site model
│ ├─ core/ # Source-adapter contracts and registry selection
│ ├─ http-policy/ # Bounded retry, timeout, and response-body reads
│ ├─ output-safety/ # Fresh-output-only command lifecycle
│ ├─ crawler/ # Bounded same-origin page discovery
│ ├─ css-references/ # Shared CSS AST parsing and reference rewriting
│ ├─ redirects/ # Redirect evidence mapping and conflict handling
│ ├─ asset-pipeline/ # Downloading, hashing, deduplication, and path rewriting
│ ├─ report/ # Platform-neutral migration analysis and reports
│ ├─ rescue-manifest/ # Whole-bundle inventory and integrity verification
│ ├─ static-verifier/ # Offline generated-site integrity checks
│ ├─ preview-server/ # Loopback-only static site preview
│ ├─ release-tools/ # Release package build, checksum, and smoke verification
│ ├─ exporters/
│ │ └─ static-html/ # Platform-neutral static website generation
│ └─ adapters/
│ ├─ generic-html/ # Conservative standards-based fallback adapter
│ └─ weebly/ # Weebly-only detection rules
├─ fixtures/
│ └─ weebly/ # Sanitized, deterministic test pages
└─ docs/
├─ RELEASE_CHECKLIST.md # Exact-commit public release procedure
└─ adr/ # ADR-001 through ADR-018
The intended long-term boundary is:
source website -> source adapter -> normalized site schema -> exporter -> target website
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm release:checkGitHub Actions runs these checks plus built and packaged CLI smoke tests on every pull request and every push to main. The workflow uses a frozen lockfile, pinned action commits, read-only repository permissions, and a 10-minute job timeout.
Default tests do not access live websites. Live compatibility checks should remain separate and explicit.
- Crawls only HTTP(S) links on the exact origin of the starting page.
- Removes URL fragments and ignores common non-document extensions.
- Fetches HTML only, follows links breadth-first, and stops at 50 pages by default.
- Limits each HTML response to 5 MiB and each attempt to 15 seconds by default.
- Retries transient request failures and HTTP 408, 429, 500, 502, 503, and 504 responses twice by default.
- Does not retry permanent HTTP responses such as 404.
- Records same-origin requested-to-final URL aliases and normalizes each final page only once.
- Does not execute JavaScript, sign in, bypass access controls, or process private content.
- Client-rendered pages and interaction-only navigation may be missed.
Only crawl and migrate websites you own or are authorized to process. Review the source site's terms and applicable policies before running the tool.
- Runs after platform-specific adapters with intentionally low detection confidence.
- Extracts server-rendered metadata, navigation, common content blocks, and referenced assets.
- Preserves forms, tables, and objects as inert source for manual review.
- Adds a
generic-html-fallbackwarning to every capture, so reports never claim automatic readiness. - Does not execute JavaScript or recover client-rendered state, application behavior, or platform-specific features.
- Downloads HTTP(S) assets already discovered by the source adapter, including images, video sources, posters, and linked stylesheets.
- Recursively discovers CSS
@importandurl()dependencies, including fonts and background images. - Rewrites successfully downloaded CSS references to local relative paths; failed references remain absolute and produce warnings.
- Stores binary assets using content-derived filenames and reuses one file when multiple URLs return identical bytes.
- Stores rewritten stylesheets under stable source-URL hash paths so circular imports can be resolved safely.
- Limits each asset to 50 MiB by default and records individual failures as warnings.
- Limits each asset request attempt to 30 seconds and uses the shared transient retry policy.
- Limits stylesheet import depth to 5 and CSS-discovered assets to 500 by default.
- Does not execute downloaded content.
- Preserves source stylesheets as migration assets and applies them only when
--style-mode sourceis explicitly selected.
- Consumes only a validated
site.jsonand its local assets; it does not call the crawler or Weebly adapter. - Writes one HTML file per normalized page and rewrites known internal page and asset references as relative links.
- Copies local assets only after validating their recorded SHA-256 checksums.
- Escapes text content and displays preserved embed or raw HTML as inert source instead of executing it.
- Adds a small responsive baseline stylesheet; it does not reproduce the original platform theme pixel-for-pixel.
- Defaults to
--style-mode baseline; source mode loads the baseline first and then verified top-level source stylesheets. - Source mode refuses captures with missing or unverified top-level stylesheets instead of linking remote CSS.
- Re-running export in baseline mode provides a deterministic fallback if source CSS conflicts with normalized markup.
- Converts followed same-origin path aliases into normalized 301 migration mappings.
- Writes a deterministic
redirects.jsonmanifest for production-host configuration. - Writes a canonical, meta-refresh, and clickable-link HTML fallback for each non-colliding redirect source path.
- Rejects redirect output collisions and redirects whose targets are not exported pages.
- Treats generated 301 status as migration intent; it does not reproduce the source server's exact status or intermediate chain.
- Skips query-bearing, cross-origin, missing-target, and conflicting redirect evidence with explicit warnings.
- HTML fallback pages do not deliver HTTP 301 responses; configure the manifest in the production host.
- Consumes only a validated
site.json; it does not call the crawler or a source adapter. - Writes deterministic
migration-report.jsonandmigration-report.mdartifacts. - Summarizes pages, nested content blocks, verified, unverified, and remote assets, warnings, and manual-review items.
- Summarizes preserved redirects and requires review for production HTTP redirect configuration.
- Marks a capture as
review-requiredwhen warnings, remote assets, preserved embeds, or raw HTML remain. - The report is guidance for migration review; it does not claim visual or functional parity with the source site.
- Scans generated HTML and CSS files and validates local HTML attributes,
@import, andurl()references. - Checks page fragments against HTML
idand legacy anchornamevalues. - Rejects unsafe URL schemes, invalid encodings, paths outside the site root, and unverified symbolic-link targets.
- Counts external references but never requests them over the network.
- Returns exit code
2when broken local references are found, making the command suitable for CI. - A successful verification proves local file integrity, not migration completeness or external-link availability.
- Runs static verification first and refuses to serve a site with broken local references.
- Serves only on
127.0.0.1, using port4173unless--portis supplied. - Supports normal nested
index.htmlroutes and common static asset content types. - Prevents path traversal and symbolic-link escapes outside the selected site directory.
- Uses no-cache response headers so repeated manual reviews read current local files.
- Stops cleanly with
Ctrl+C; it does not open a browser automatically.
- Treats
capture/,site/, andreport/as one portable rescue bundle. - Writes a canonically sorted
rescue-manifest.jsoncontaining relative POSIX paths, roles, byte sizes, and SHA-256 checksums. - Validates
capture/site.json, requires reports to match that capture, and runs static verification before writing a manifest. - Detects missing, unexpected, size-mismatched, and checksum-mismatched files without network access.
- Rejects symbolic links, special filesystem entries, unsafe manifest paths, unexpected top-level entries during manifest creation, and bundles above 100,000 files.
- Returns exit code
2fromverify-bundlefor integrity mismatches, making it suitable for backup and handoff checks. - Excludes the manifest itself from its file inventory so identical bundle contents produce identical manifest bytes.
- SHA-256 proves content consistency against the recorded manifest; it is not a digital signature and does not prove who created the bundle.
capture,export,report, andrescueaccept only a non-existing output directory.- Existing files and directories are refused before command work begins and are never modified.
- A failed operation removes only the exact output directory created by that operation.
manifestandverify-bundleintentionally inspect an existing rescue bundle.- Phase 16 does not provide overwrite, resume, or incremental capture modes.
- All workspace packages must use the root semantic version and remain private before the release policy changes.
release:checkrebuildsrelease/package, verifies every checksum, executes bundled--versionand--help, and produces a real migration report from an offline fixture.- The release package bundles runtime dependencies but still requires Node.js 20.19 or newer.
- Package metadata remains
private: trueto prevent accidental npm publication; the planned first distribution channel is GitHub Releases. - Root, workspace, and generated package metadata use the
Apache-2.0SPDX identifier; bundled dependencies remain under their own terms recorded inTHIRD_PARTY_NOTICES.txt. Exact-version audited license overrides cover published packages that omit their license file. - Follow the release checklist before changing visibility, tagging, or publishing.
- See the public repository publication record for the completed visibility, history-audit, and GitHub protection checks.
- See CHANGELOG.md, CONTRIBUTING.md, and SECURITY.md for project policy.
- Use the structured bug report for reproducible defects with sanitized fixtures and logs.
- Use the feature request for focused migration capabilities.
- Follow SECURITY.md and use a private security advisory for vulnerabilities. Never disclose credentials, private website content, personal data, or customer data in an issue.
- GUI or hosted SaaS
- Cloudflare infrastructure or domain automation
- Payments, CMS, page builder, membership, or e-commerce
- Pixel-perfect cloning or AI redesign
- Astro or framework-specific exporters
- Automatic deployment or hosting
- Host-specific redirect configuration, cross-origin redirects, or query-based redirect rules
- LAN or public-network serving, HTTPS, authentication, or live reload
- Automatically applying source stylesheets by default, CSS optimization, or visual parity analysis
- CSS sanitization, selector translation, theme editing, or an interactive style toggle
- Inline styles and JavaScript-loaded CSS
- JavaScript rendering, browser automation, authenticated crawling, or form behavior recreation
- ZIP/TAR creation, encryption, digital signatures, cloud upload, or incremental backups
See Architecture Decision Records for ADR-001 through ADR-019.
Site Rescue is licensed under the Apache License 2.0. Bundled third-party runtime components retain their own licenses and notices.