CtrlK
BlogDocsLog inGet started
Tessl Logo

adobe/stardust

Redesign an existing website to make it better. Built on top of impeccable.

71

Quality

89%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

content-preservation.mdskills/migrate/reference/

Content preservation

What migrate keeps from the existing site, what it transforms, and what it explicitly drops. The default answer is "preserve everything"; deviations require a basis in direction.md.


Preserve verbatim

These are the things the redesign never changes unless direction.md § Anti-references or a sibling note explicitly authorises it:

  • Headline text for every heading in current/pages/<slug>.json § headings. The redesign restyles type, scale, and rhythm — not what the headlines say.
  • Body copy for every paragraph and list item. Restyle, do not rewrite.
  • Paragraph boundaries come from the source's block-level nodes (p, direct-child divs), each node's inline text joined with spaces — never from splitting captured text on newlines. get_text('\n')-style extraction breaks on every INLINE element (a bolded lead, a link, a superscript), so "one line = one paragraph" turned a 5-paragraph disclaimer into 16 fragment <p>s and doubled the section height — a defect that reads as CSS at the pixel gate but is an import bug (recorded).
  • CTA labels for every button and button-styled link. The visual treatment changes; the label does not.
  • Navigation labels in headers and footers.
  • Form fields — name, type, label, required state, placeholder. The form's visual treatment changes; the schema does not.
  • Link destinations. Every href resolves to the same target. Internal links are rewritten to the migrated tree (see § Internal link rewriting); external links are passed through untouched.
  • Alt text for every image.
  • Sequence and grouping of content within sections, unless direction.md explicitly authorises a structural change for this page.

When migrate cannot preserve a content item — it doesn't fit the chosen component, it overflows a constraint, it duplicates something the new IA already covers — the deviation goes in the provenance block's contentDeviations[] array with { kind, source, target, reason } so the user can audit.

Transform with rules

  • Tone of microcopy that the redesign explicitly governs through DESIGN.json.narrative.dos / donts (e.g., voice rules carried from the divergence toolkit § 7). Migrate may apply minor tone adjustments to button microcopy and inline labels — never to headlines or body paragraphs. Each adjustment is logged in contentDeviations[].
  • Internal link paths are rewritten per § Internal link rewriting.
  • Asset paths are rewritten per § Media references.
  • Whitespace and line breaks in copy are normalised; trailing whitespace and double-spaces collapse.

Drop deliberately

  • Inline analytics tags and tracking pixels (Facebook pixel, Google Tag Manager, Hotjar, Segment, Linkedin Insight). The migrated site is a static HTML deliverable; tracking is added back during deploy by a separate concern.
  • Cookie consent banners. Same reason — re-add at deploy time with the org's preferred CMP.
  • Embedded chat widgets (Intercom, Drift, Zendesk Chat). Re-wire at deploy.
  • Inline JS for polyfills, A/B testing harnesses, feature flags, experiment SDKs. Out of scope for static HTML output.
  • Empty or placeholder sections (<section><!-- TODO --></section> in the current site). Drop and log.

Every drop is logged in contentDeviations[] with kind: "dropped" and a reason.

Internal link rewriting

For every <a href>:

  1. Skip when href starts with # (intra-page anchor), mailto:, tel:, javascript:, or a non-HTTP scheme.
  2. External (different host than state.json.site.originUrl): pass through unchanged.
  3. Internal (same host, including same-host with absolute URL):
    • Strip origin and tracking params (utm_*, gclid, fbclid).

    • Look up the target path in state.json.pages[].url to find the slug.

    • If found, rewrite href to the migrated path (per the slug mapping in migration-procedure.md § Output path mapping). Use root-relative paths (/about/, /docs/api/) so the migrated site moves cleanly across hosts.

    • If not found (target was never extracted or was filtered out), compute the migrated path the slug would resolve to (per migration-procedure.md § Output path mapping) and rewrite the href to that path anyway. Mark the link data-broken-link="true" and log under provenance.brokenInternalLinks[]. The migrated tree stays internally consistent — every same-host link is a relative migrated path; broken links surface as an explicit signal, not as escape hatches to the live origin. The user resolves by extracting the missing page (and re-running migrate) or accepting the broken link.

      Partial-inventory carve-out (stardust-style e2e finding). When the run is deliberately scoped to a subset of the inventory (an explicit <slug> list, or siblings not yet migrated), a rewritten-but-nonexistent migrated path makes the mandatory file-protocol-audit.mjs fail on every page that links a not-yet-migrated sibling — the two contracts are only co-satisfiable on full-inventory runs. On a scoped run the link to a known-inventory-but-unmigrated page keeps the resolvable absolute origin URL instead, still flagged data-broken-link="true" and logged; a later migrate run that covers the target reconciles it to the relative migrated path (the sha change re-renders the linking page). The audit accepts data-broken-link-flagged origin URLs as known-broken on scoped runs.

  4. Preserve any href fragment (#section-3) and query string (?ref=foo) exactly when rewriting.

Media references

Asset bundling is run as the last step of the per-page render — see reference/asset-bundling.md for the canonical contract. Summary of the content-preservation surface:

  1. Asset references on the rendered page (any of the six detection shapes in asset-bundling.md § Detection) are resolved against the asset-prefix set, copied into stardust/migrated/assets/<subpath> with subdir structure preserved, and rewritten to root-relative /assets/<subpath>.
  2. Preserve srcset, sizes, loading, decoding, alt, width, height verbatim. The bundler updates srcset URLs by splitting on commas, rewriting each URL, and re-joining with the descriptors preserved.
  3. If the source file is missing from stardust/current/assets/<subpath>, the bundler still rewrites the HTML reference (so the bundle stays internally consistent) and logs under provenance.contentDeviations[] with kind: "asset-missing". The bundle will 404 on that asset at deploy time — a downstream concern that the migrate report surfaces explicitly.

For inline SVGs, preserve the markup verbatim (modulo class-name substitutions to match the new component classes when the component template requires it).

For iframes (YouTube, Vimeo, Calendly): preserve the embed code verbatim. They are external dependencies the migrated site depends on.

Forms

The form schema (action, method, field set) is preserved verbatim. The form's visual treatment is restyled per DESIGN.json component form (or input + button if no form component is defined).

Form actions pointing at third-party services (Stripe Payment Links, Calendly, Typeform, Mailchimp, Formspree) are preserved as-is — they continue to work after deploy.

Form actions pointing at the origin's own backend (e.g., /api/contact) are preserved with a warning logged in contentDeviations[] with kind: "self-hosted-form" and a hint: "the origin's /api/contact endpoint must remain available at the migrated site's origin, or the form must be re-wired to a static-form service."

Dynamic dependencies

self-hosted-form is one instance of a general rule: nothing the evidence recorded as dynamic may ship static silently. Before rendering a page, look up the rows of stardust/dynamic-features.md that touch it (by reach / evidence; per-page dynamic section when the crawl ran with --dynamics):

  • embed-passthrough → preserve the markup verbatim (iframe, player link, third-party form action, widget mount) — no log entry.
  • index-backed / data-fed / rebuild-native / client-only → the section is rendered by the block deploy builds for it; migrate emits the authored fallback rows (or the #modal link, the player URL) and logs contentDeviations[] kind: "dynamic-dependency" with the disposition, the row id and the endpoint, so the report shows what the page depends on at runtime.
  • static-snapshot / decided-out → render the captured state and log kind: "dynamic-dependency" with the disposition and the reason.
  • No inventory or no row → the Phase 1 safety net ran stardust:dynamics Phases 1–3; if a dynamic dependency still has no row, log disposition: "unclassified" and surface it first in the report — a dynamic-gap learning.

Deviation shape:

{ "kind": "dynamic-dependency", "disposition": "data-fed", "row": "reviews-rail",
  "endpoint": "GET api.example-vendor.test/v1/reviews", "note": "authored fallback: 3 rows" }

Voice and tone deviations

When the redesign moves the tone axis (per direction.md § Movements), migrate may not re-write headlines or body copy to match the new tone. It restyles only.

If the user wants tone-aligned copy, they run a separate pass: $impeccable clarify stardust/migrated/<slug> after migration. Stardust does not auto-trigger that.

Headings hierarchy

Preserve the heading levels from current/pages/<slug>.json § headings. The redesign may re-style headings dramatically but must not skip levels (an h2 cannot become an h4) or invent new headings.

If the current site has skipped levels (h1h3), migrate fixes them by demoting where needed and logs the fix in contentDeviations[] with kind: "heading-level-fix". This is one of the few accessibility corrections migrate makes by default.

Lang and direction attributes

<html lang="..."> is preserved from the current page's language field. <html dir="ltr|rtl"> is added when DESIGN.md's extensions.breakpoints.rtl is true or when the current page was RTL.

Mass-applied direction-driven changes

The following come from direction.md and apply to every migrated page identically (not page-by-page deviations):

  • Logo path (always /assets/logo.<ext>).
  • Favicon — extracted at extract time, variants generated at prepare-migration Phase 4, linked via <link rel="icon"> per metadata-and-jsonld.md § Favicon.
  • Site-wide nav structure — emitted from stardust/canon/header.html on every page; re-iterating the canon-author prototype updates it sitewide.

Delegated concerns

This doc covers body content. Two adjacent concerns are delegated to dedicated references:

  • Head metadata (title, description, OG, Twitter, JSON-LD, canonical, robots, theme-color, favicon) → metadata-and-jsonld.md. The five-category model (system-fixed, brand-level, preserved, derived, stripped) governs head composition end-to-end.
  • Font handling@font-face URLs are downloaded to stardust/migrated/assets/fonts/ during prepare-migration Phase 4 (assets prep). Migrate-time fonts are local; missing downloads surface a warning per affected page in the run summary.

skills

README.md

tile.json