Updating F2W partials from a published page

index.astro renders three partials extracted from a Figma-to-Website (F2W) export:

When the user gives a published F2W URL (e.g. https://<slug>.figweb.site/) and asks to update one or more of these partials, follow this procedure.

All three partials are listed in the repo-root .prettierignore and must stay there — see §8.

1. Fetch the raw HTML

Do NOT use WebFetch — it summarizes and you’ll lose the inline scripts/styles. Use curl to a temp file:

curl -sL "<url>" -o /tmp/figweb.html

The published page is mostly on a single line per element (minified).

2. Source-page anatomy

After curl, the structure is approximately:

LinesContentGoes into
<script>window.F2W_REACTIONS=…;window.F2W_LANGUAGES=void 0</script>one giant inline script defining F2W_REACTIONS, F2W_VARIABLES, F2W_COLLECTION_MODE_BPS, etc._from_f2w_head.astro
<script src="/__assets/runtime-<hash>.js"></script>runtime loader_from_f2w_head.astro
<style> blocks (<style media="all">…</style>, <style>@font-face…</style>, etc.)global CSS, font-faces, body CSS variables, #_/#__x2d_body layout, responsive overrides_from_f2w_styles.astro
<div id="__x2d_body">…</div>full page body tree (sections, hero, plugin cards, etc.)_from_f2w_body.astro

The <body id="_"> wrapper from the source is dropped — BaseLayout.astro already provides <body>.

Locate the boundaries with:

grep -nE '<script|</script>|<style|</style>|<div id="__x2d_body"' /tmp/figweb.html

3. Critical Astro attributes

Every <script> and <style> you copy in MUST carry an Astro directive — otherwise Astro will hoist/scope/process it and break things.

Verify there are no bare <style> tags after editing:

grep -n '<style' site-drc/www/src/pages/_from_f2w_styles.astro

Each match must have either is:inline or is:global.

4. Reaction-ID consistency check

Hover/click/etc. effects break silently if _from_f2w_head.astro and _from_f2w_body.astro come from different F2W generations. The runtime does F2W_REACTIONS[id] for each data-reaction-* attribute; an unknown id means no listener is attached, no error logged.

After updating, verify every body-side ID exists in the head:

comm -23 \
  <(grep -oE 'data-reaction-(hover|click|press|drag|submit)="[0-9]+"' \
      site-drc/www/src/pages/_from_f2w_body.astro | grep -oE '[0-9]+' | sort -nu) \
  <(grep -oE '[0-9]{2,5}:\{type:' \
      site-drc/www/src/pages/_from_f2w_head.astro | grep -oE '^[0-9]+' | sort -nu)

Output must be empty. If not, the head and body are mismatched — refetch both from the same URL.

5. Runtime asset

The <script src="/__assets/runtime-<hash>.js"> reference must point at a file that exists in site-drc/www/public/__assets/. When the F2W export changes the hash, download the new runtime:

curl -sL "https://<slug>.figweb.site/__assets/runtime-<hash>.js" \
  -o site-drc/www/public/__assets/runtime-<hash>.js

Old runtime files can be deleted once nothing references them.

6. Partial updates

If the user asks to update only one partial, still fetch the URL and replace the corresponding section. But warn them: updating only the body without the head (or vice versa) is what causes the reaction-ID mismatch above. Either update both, or run the consistency check and abort if it fails.

8. Site overrides for F2W discrepancies

The published F2W page renders standalone — no reset.css, no shared layout. Inside this Astro site, BaseLayout.astro loads /css/reset.css and /css/global.css, which can clash with what F2W assumes.

When something looks broken vs. the source page, suspect the reset before suspecting the partials.

Known clashes (handled with <style is:global> blocks directly in index.astro, where they survive partial refreshes):

When you find a new clash, add a similarly-scoped override in index.astro (between <F2WSTYLES /> and <F2WBODY />) and document it here. Do not patch the F2W partials — those get overwritten on refresh.

10. Prettier must not touch these files

The body partial contains text inside <span class="text">…</span> elements, and .text has white-space: pre-wrap. Any whitespace/newline that Prettier inserts inside a text node becomes visible whitespace in the rendered page (manifested as oddly indented continuation lines under plugin descriptions).

The repo-root .prettierignore already lists all three partials. After updating any of them, do NOT run prettier --write on them, and verify they’re still in .prettierignore — if a contributor removed the entry, restore it. lint-staged + husky honour .prettierignore, so commits won’t reformat the files as long as the entries are present.

If you ever need to reformat these files for readability, edit the source on F2W instead and refetch — never let Prettier rewrite the body partial.

11. What NOT to copy from the source

The published page also contains: