Skip to content

fix(dla): name Wix pages from nav label or slug when every page shares the site-wide SEO title - #4720

Open
ellenbauer wants to merge 138 commits into
feat/site-artifact-import-clifrom
fix/dla-wix-sitewide-page-titles
Open

fix(dla): name Wix pages from nav label or slug when every page shares the site-wide SEO title#4720
ellenbauer wants to merge 138 commits into
feat/site-artifact-import-clifrom
fix/dla-wix-sitewide-page-titles

Conversation

@ellenbauer

Copy link
Copy Markdown

Related issues

How AI was used in this PR

Found, fixed, and tested with Claude Code while migrating a real Wix site (www.360chiro.co.uk). The helper and test were written test-first; I reviewed the diff and the evidence below comes from an actual import.

Proposed Changes

  • On many Wix sites the owner sets one custom SEO title for every page. document.title then carries no page identity, and the existing " | Site Name" suffix-strip has nothing to strip — so every imported page lands in wp-admin with the same title. On www.360chiro.co.uk, all 14 pages imported as "Chiropractor Sheffield - Expert Care for Pain Relief", making the Pages list unusable.
  • New shared helper resolvePageTitle (in lib/html-extract, reusable by other adapters): after the suffix-strip, a title that equals the discovered site-wide title is demoted to the page's navigation label (what the Wix editor shows as the page name, e.g. /treatments → "Treatments", /new-patients → "First Visit"), else the humanized slug ("neck-pain-stiffness" → "Neck Pain Stiffness"). The homepage keeps the site title unless the nav names it ("Home").
  • The original SEO title is still preserved per page as seoTitle (_seo_title meta) — this only changes the WordPress admin title, not SEO data.
  • Discovery already collects both signals (siteMeta.title, navigation), so no new capture work is needed.

Testing Instructions

  • cd packages/data-liberation-agent && npx vitest run test/html-extract.test.ts test/adapters/wix.test.ts (8 new + 8 existing tests).
  • End-to-end: liberate a Wix site whose pages share one SEO title (e.g. www.360chiro.co.uk) and check Pages in wp-admin — before: 14 pages all titled "Chiropractor Sheffield - Expert Care for Pain Relief"; after: "Treatments", "Fees", "Contact Us", "First Visit", …
  • Sites with normal per-page titles ("About | MySite") are unaffected — covered by tests.

Pre-merge Checklist

  • Tests added and passing (test/html-extract.test.ts)
  • tsc --noEmit clean for the package
  • CI green

Note: the full package suite has 9 pre-existing failures in test/legacy-scripts.test.ts on my machine only because the checkout path contains a space — the test shells node --check ${path} unquoted. Unrelated to this change; happy to fix that in a follow-up.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GpLtieepeCxY3hXzJfsfoV

chubes4 and others added 30 commits August 23, 2026 18:34
Keep the site create change focused on generic static source imports while preserving the Figma implementation on its dedicated branch.

AI assistance: OpenAI gpt-5.6-sol via OpenCode removed the isolated Figma handoff scope and verified the focused CLI tests, lint, typecheck, and build. Chris Huber reviewed and remains responsible for the change.
AI assistance: OpenAI gpt-5.6-sol via OpenCode reduced the fixture after reproducing and timing the test locally; Chris Huber reviewed and remains responsible for the change.
AI assistance: OpenAI gpt-5.6-sol via OpenCode verified the Homeboy release asset and updated Studio's default importer URL. Chris Huber remains responsible for the change.
chubes4 and others added 27 commits August 25, 2026 00:09
The export selected portable media against its own 160 MiB cap without
knowing how many bytes the routes, captured render dependencies, and
reports already take. On a 28-page Wix capture the media filled that cap
and the artifact writer then threw "Portable capture exceeds compiler
limits" against the 192 MiB total, discarding a three-minute capture
instead of degrading.

Reserve the staged route HTML, the captured non-script resources, and the
report files that already exist on disk, and give media only what is left
under the artifact limit (still capped at 160 MiB). The reservation is an
upper bound: media that does not fit is retained external, as before,
rather than failing the export. The receipt reports the effective
`max_bytes` and the `reserved_bytes` behind it, and the artifact header
carries the effective total limit.

`ExportCaptureOptions.limits` lets a caller (and the test) override the
artifact and media limits without touching the compiler defaults.

Re-exporting the same Wix capture selects the same 167 files (24.3 MB)
with 145 MB reserved and a 56 MB media budget; the artifact is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The media downloader fetched with no Accept header, so format-negotiating
CDNs (Wix, Squarespace, Cloudinary f_auto, imgix auto=format, Photon)
returned the legacy/original encoding. On a small Wix store the retina
variants came back as 1-7 MB PNGs instead of the ~10 KB AVIFs a visitor's
browser receives, the portable media set filled its 160 MiB budget, and
the artifact export failed against the 192 MiB compiler limit.

Send Chromium's image Accept header and name the downloaded file by the
negotiated content type when it differs from the URL extension, so an AVIF
body is not stored as `.png`. Same-format aliases (`.jpeg`/`.jpg`,
`.tif`/`.tiff`) keep the URL extension.

On the same site the export now completes at 128 MB, with 162 AVIF assets
in the generated theme instead of 82 multi-megabyte PNGs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The generated import script wrote Static Site Importer's full response
into `.studio-import/result.json` as `import_receipt`. On a 28-page Wix
artifact that response was 3.04 GB (`import_report` 2.72 GB,
`materialization_receipt` 325 MB). macOS `write(2)` rejects a single
write of 2 GB or more, so `file_put_contents` returned false and the
import failed with "result receipt could not be saved" after every page
and the theme had already been materialized.

Store the existing bounded projection (`static_site_importer_studio_result_projection`)
as the receipt on both the success and failure paths. The CLI only reads
`continuation`, `canonicalization_pending`, `completed_routes`, and
`total_routes` from the receipt, and the database option already stores
the same projection.

With this change the same import completes, canonicalizes 32 pages, and
writes a 124 KB receipt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…th-scope-nimbus

# Conflicts:
#	packages/data-liberation-agent/dist/mcp-server.bundle.mjs
#	packages/data-liberation-agent/dist/scripts/carry-reconstruct-drive.mjs
#	packages/data-liberation-agent/dist/scripts/carry-replica-shots.mjs
#	packages/data-liberation-agent/dist/scripts/chunk-6UJ5H2IN.mjs
#	packages/data-liberation-agent/dist/scripts/chunk-Q5FWHB6M.mjs
#	packages/data-liberation-agent/dist/scripts/chunk-RH45CRZA.mjs
#	packages/data-liberation-agent/dist/scripts/enrich-product-marketing.mjs
#	packages/data-liberation-agent/src/adapters/wix/discover.ts
When desktop and mobile captures share a responsive body signature but
their style blocks differ, the export returned the desktop document
unchanged: mobile styles were dropped entirely and desktop styles were
left unwrapped, so the page shipped with no mobile CSS (proven on a Wix
homepage whose DOM matched across viewports while its CSS did not).

Keep the single shared body but merge CSS responsively: wrap desktop
styles in media="(min-width:769px)" and append the mobile document's
style blocks as media="(max-width:768px)", without the
.data-liberation-mobile-document scoping that only exists in two-body
output. Identical bodies with identical styles keep the current
single-document output, and differing bodies keep the existing
two-document behavior.

Known limitation (out of scope): mobile-only body attributes/classes
are still lost when the shared desktop body is kept.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Direct-artifact imports wrote continuation receipts carrying only
{continuation: true}, so the CLI printed 'Static site import progress:
0/0 routes' for the entire run (observed for ~25 minutes on a real
studio create --from <url>): the fabricated ?? 0 fallbacks were the only
data on that path, since url_batch_run counts exist only for URL-batch
imports and the direct path returns before canonical documents exist.

Enrich the continuation receipts with what is actually measured: the
dependency-preparation lifecycle checkpoint reports its stage, and the
direct ingest continuation passes through the importer's status plus
url_batch_run route counts only when the importer provides them. The
CLI now prints real route counts when present, otherwise the reported
stage ('Static site import continuing: dependencies prepared'), and
never fabricates 0/0 route numbers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Captured routes that resolve to the same website path now collapse onto
the already-claimed route when the alternate address declares it as
canonical (e.g. / and /index.html serving one document). The receipt
records duplicateRoutes so aliases stay auditable. Non-canonical
collisions (/about vs /about/) still fail with the existing error.

Fixes Automattic/data-liberation-agent#107
…s the site-wide SEO title

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GpLtieepeCxY3hXzJfsfoV
@chubes4
chubes4 force-pushed the feat/site-artifact-import-cli branch from 43bc3f9 to b7abf7d Compare August 30, 2026 05:03
@chubes4
chubes4 requested a review from a team as a code owner August 30, 2026 05:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants