index.astro renders three partials extracted from a Figma-to-Website (F2W) export:
_from_f2w_head.astro — inline reaction/variable script + runtime <script src>_from_f2w_styles.astro — every <style> block from the source page_from_f2w_body.astro — the <div id="__x2d_body">…</div> content treeWhen 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.
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).
After curl, the structure is approximately:
| Lines | Content | Goes 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 |
8× <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
Every <script> and <style> you copy in MUST carry an Astro directive — otherwise Astro will hoist/scope/process it and break things.
is:inline. Without it, Astro bundles <script> tags, which strips them from <head> and reorders execution. The inline F2W_REACTIONS script must run before runtime.js.is:inline on every block. (Astro’s default scopes a <style> tag with a data-astro-cid-… attribute added only to elements in the same component. Since the actual elements live in _from_f2w_body.astro (a different component), an unmarked <style> block silently applies to nothing.) is:global would also cascade correctly, but Astro+Vite then runs the CSS through Lightning CSS, which has been observed to “simplify” nested calc() expressions in ways that change rendering — e.g. calc(calc(1px*var(--x))*-.02) → calc(1px*var(--x)*-.02) produced different computed values for some elements, blowing up font sizes. Always use is:inline so the F2W CSS is emitted byte-for-byte and the optimizer never touches it.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.
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.
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.
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.
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):
reset.css sets ul, ol { list-style: none }. F2W lists ship with li:before { content: '' } and rely on the browser default disc/decimal markers. Override with #__x2d_body ul, #__x2d_body ol { list-style-type: revert }.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.
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.
The published page also contains:
<head> meta/title/canonical/preconnect tags — BaseLayout.astro handles these.cdn.usefathom.com) — already wired up elsewhere.<script type="module" src="_jampack/…"> quicklink loader at </body> — Astro/jampack handles this automatically at build time.<a> badge at the end of <body> — already present directly in index.astro.