[{"data":1,"prerenderedAt":1785},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Finstant-first-frame-rendering":455,"\u002Fguides\u002Finstant-first-frame-rendering-surround":1780},[4,34,51,301,327,332,337,406],{"title":5,"path":6,"stem":7,"children":8,"package":11,"icon":33},"Getting Started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,13,18,23,28],{"title":10,"path":6,"stem":7,"package":11,"icon":12},"Introduction",null,"i-lucide-house",{"title":14,"path":15,"stem":16,"package":11,"icon":17},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":19,"path":20,"stem":21,"package":11,"icon":22},"Icons","\u002Fgetting-started\u002Ficons","1.getting-started\u002F3.icons","i-lucide-sparkles",{"title":24,"path":25,"stem":26,"package":11,"icon":27},"CLI","\u002Fgetting-started\u002Fcli","1.getting-started\u002F4.cli","i-lucide-terminal",{"title":29,"path":30,"stem":31,"package":11,"icon":32},"Roadmap","\u002Fgetting-started\u002Froadmap","1.getting-started\u002F5.roadmap","i-lucide-map","i-lucide-rocket",{"title":35,"package":11,"icon":36,"path":37,"stem":38,"children":39,"page":50},"Packages","i-lucide-package","\u002Fpackages","2.packages",[40,45],{"title":41,"path":42,"stem":43,"package":11,"icon":44},"@vyui\u002Fcore","\u002Fpackages\u002Fcore","2.packages\u002F1.core","i-lucide-box",{"title":46,"path":47,"stem":48,"package":11,"icon":49},"@vyui\u002Fkit","\u002Fpackages\u002Fkit","2.packages\u002F2.kit","i-lucide-layers",false,{"title":52,"package":11,"icon":53,"path":54,"stem":55,"children":56},"Components","i-lucide-layout-grid","\u002Fcomponents","3.components",[57,59,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,144,149,153,158,163,168,173,178,183,188,193,198,203,208,213,218,223,228,233,238,242,246,251,256,261,266,271,276,280,284,288,292,296],{"title":52,"path":54,"stem":58,"package":11,"icon":53},"3.components\u002Findex",{"title":60,"path":61,"stem":62,"package":63,"icon":64},"Accordion","\u002Fcomponents\u002Faccordion","3.components\u002Faccordion","kit","i-lucide-list-collapse",{"title":66,"path":67,"stem":68,"package":63,"icon":69},"Action Sheet","\u002Fcomponents\u002Faction-sheet","3.components\u002Faction-sheet","i-lucide-panel-bottom",{"title":71,"path":72,"stem":73,"package":63,"icon":74},"Alert","\u002Fcomponents\u002Falert","3.components\u002Falert","i-lucide-triangle-alert",{"title":76,"path":77,"stem":78,"package":79,"icon":74},"Alert Dialog","\u002Fcomponents\u002Falert-dialog","3.components\u002Falert-dialog","core",{"title":81,"path":82,"stem":83,"package":63,"icon":84},"App","\u002Fcomponents\u002Fapp","3.components\u002Fapp","i-lucide-smartphone",{"title":86,"path":87,"stem":88,"package":63,"icon":89},"Aspect Ratio","\u002Fcomponents\u002Faspect-ratio","3.components\u002Faspect-ratio","i-lucide-ratio",{"title":91,"path":92,"stem":93,"package":63,"icon":94},"Avatar","\u002Fcomponents\u002Favatar","3.components\u002Favatar","i-lucide-circle-user-round",{"title":96,"path":97,"stem":98,"package":63,"icon":99},"Avatar Group","\u002Fcomponents\u002Favatar-group","3.components\u002Favatar-group","i-lucide-users-round",{"title":101,"path":102,"stem":103,"package":63,"icon":104},"Button","\u002Fcomponents\u002Fbutton","3.components\u002Fbutton","i-lucide-square-mouse-pointer",{"title":106,"path":107,"stem":108,"package":63,"icon":109},"Calendar","\u002Fcomponents\u002Fcalendar","3.components\u002Fcalendar","i-lucide-calendar-days",{"title":111,"path":112,"stem":113,"package":63,"icon":114},"Card","\u002Fcomponents\u002Fcard","3.components\u002Fcard","i-lucide-square",{"title":116,"path":117,"stem":118,"package":63,"icon":119},"Checkbox","\u002Fcomponents\u002Fcheckbox","3.components\u002Fcheckbox","i-lucide-square-check",{"title":121,"path":122,"stem":123,"package":79,"icon":124},"Collapsible","\u002Fcomponents\u002Fcollapsible","3.components\u002Fcollapsible","i-lucide-chevrons-down-up",{"title":126,"path":127,"stem":128,"package":79,"icon":129},"Dialog","\u002Fcomponents\u002Fdialog","3.components\u002Fdialog","i-lucide-app-window",{"title":131,"path":132,"stem":133,"package":79,"icon":134},"Draggable","\u002Fcomponents\u002Fdraggable","3.components\u002Fdraggable","i-lucide-move",{"title":136,"path":137,"stem":138,"package":63,"icon":139},"Form","\u002Fcomponents\u002Fform","3.components\u002Fform","i-lucide-clipboard-list",{"title":141,"path":142,"stem":143,"package":79,"icon":22},"Icon","\u002Fcomponents\u002Ficon","3.components\u002Ficon",{"title":145,"path":146,"stem":147,"package":63,"icon":148},"Input","\u002Fcomponents\u002Finput","3.components\u002Finput","i-lucide-text-cursor-input",{"title":150,"path":151,"stem":152,"package":63,"icon":69},"Island","\u002Fcomponents\u002Fisland","3.components\u002Fisland",{"title":154,"path":155,"stem":156,"package":63,"icon":157},"Island Button","\u002Fcomponents\u002Fisland-button","3.components\u002Fisland-button","i-lucide-circle-ellipsis",{"title":159,"path":160,"stem":161,"package":63,"icon":162},"Island Group","\u002Fcomponents\u002Fisland-group","3.components\u002Fisland-group","i-lucide-panels-top-left",{"title":164,"path":165,"stem":166,"package":63,"icon":167},"KeyboardAware","\u002Fcomponents\u002Fkeyboard-aware","3.components\u002Fkeyboard-aware","i-lucide-keyboard",{"title":169,"path":170,"stem":171,"package":63,"icon":172},"Label","\u002Fcomponents\u002Flabel","3.components\u002Flabel","i-lucide-tag",{"title":174,"path":175,"stem":176,"package":63,"icon":177},"Modal","\u002Fcomponents\u002Fmodal","3.components\u002Fmodal","i-lucide-gallery-vertical-end",{"title":179,"path":180,"stem":181,"package":79,"icon":182},"Navigation","\u002Fcomponents\u002Fnavigation","3.components\u002Fnavigation","i-lucide-route",{"title":184,"path":185,"stem":186,"package":63,"icon":187},"Number Field","\u002Fcomponents\u002Fnumber-field","3.components\u002Fnumber-field","i-lucide-list-plus",{"title":189,"path":190,"stem":191,"package":79,"icon":192},"Pagination","\u002Fcomponents\u002Fpagination","3.components\u002Fpagination","i-lucide-ellipsis",{"title":194,"path":195,"stem":196,"package":63,"icon":197},"Pin Input","\u002Fcomponents\u002Fpin-input","3.components\u002Fpin-input","i-lucide-key-round",{"title":199,"path":200,"stem":201,"package":63,"icon":202},"Placeholder","\u002Fcomponents\u002Fplaceholder","3.components\u002Fplaceholder","i-lucide-square-dashed",{"title":204,"path":205,"stem":206,"package":63,"icon":207},"Popover","\u002Fcomponents\u002Fpopover","3.components\u002Fpopover","i-lucide-message-square-more",{"title":209,"path":210,"stem":211,"package":63,"icon":212},"Progress","\u002Fcomponents\u002Fprogress","3.components\u002Fprogress","i-lucide-chart-no-axes-column-increasing",{"title":214,"path":215,"stem":216,"package":63,"icon":217},"Radio Group","\u002Fcomponents\u002Fradio-group","3.components\u002Fradio-group","i-lucide-circle-dot",{"title":219,"path":220,"stem":221,"package":63,"icon":222},"Rating","\u002Fcomponents\u002Frating","3.components\u002Frating","i-lucide-star",{"title":224,"path":225,"stem":226,"package":79,"icon":227},"Scroll View","\u002Fcomponents\u002Fscroll-view","3.components\u002Fscroll-view","i-lucide-scroll",{"title":229,"path":230,"stem":231,"package":63,"icon":232},"Select","\u002Fcomponents\u002Fselect","3.components\u002Fselect","i-lucide-list-check",{"title":234,"path":235,"stem":236,"package":63,"icon":237},"Separator","\u002Fcomponents\u002Fseparator","3.components\u002Fseparator","i-lucide-separator-horizontal",{"title":239,"path":240,"stem":241,"package":79,"icon":69},"Sheet","\u002Fcomponents\u002Fsheet","3.components\u002Fsheet",{"title":243,"path":244,"stem":245,"package":63,"icon":162},"Skeleton","\u002Fcomponents\u002Fskeleton","3.components\u002Fskeleton",{"title":247,"path":248,"stem":249,"package":63,"icon":250},"Slider","\u002Fcomponents\u002Fslider","3.components\u002Fslider","i-lucide-sliders-horizontal",{"title":252,"path":253,"stem":254,"package":63,"icon":255},"Sortable","\u002Fcomponents\u002Fsortable","3.components\u002Fsortable","i-lucide-list-restart",{"title":257,"path":258,"stem":259,"package":63,"icon":260},"Stepper","\u002Fcomponents\u002Fstepper","3.components\u002Fstepper","i-lucide-list-ordered",{"title":262,"path":263,"stem":264,"package":63,"icon":265},"Swipe Action","\u002Fcomponents\u002Fswipe-action","3.components\u002Fswipe-action","i-lucide-move-horizontal",{"title":267,"path":268,"stem":269,"package":63,"icon":270},"Swiper","\u002Fcomponents\u002Fswiper","3.components\u002Fswiper","i-lucide-gallery-horizontal-end",{"title":272,"path":273,"stem":274,"package":63,"icon":275},"Switch","\u002Fcomponents\u002Fswitch","3.components\u002Fswitch","i-lucide-toggle-right",{"title":277,"path":278,"stem":279,"package":63,"icon":162},"Tabs","\u002Fcomponents\u002Ftabs","3.components\u002Ftabs",{"title":281,"path":282,"stem":283,"package":63,"icon":148},"Textarea","\u002Fcomponents\u002Ftextarea","3.components\u002Ftextarea",{"title":285,"path":286,"stem":287,"package":63,"icon":207},"Toast","\u002Fcomponents\u002Ftoast","3.components\u002Ftoast",{"title":289,"path":290,"stem":291,"package":63,"icon":275},"Toggle","\u002Fcomponents\u002Ftoggle","3.components\u002Ftoggle",{"title":293,"path":294,"stem":295,"package":63,"icon":162},"Toggle Group","\u002Fcomponents\u002Ftoggle-group","3.components\u002Ftoggle-group",{"title":297,"path":298,"stem":299,"package":63,"icon":300},"Tray","\u002Fcomponents\u002Ftray","3.components\u002Ftray","i-lucide-square-dashed-bottom",{"title":302,"path":303,"stem":304,"children":305,"package":11,"icon":307},"Theming","\u002Ftheming","4.theming\u002F1.index",[306,308,312,317,322],{"title":302,"path":303,"stem":304,"package":11,"icon":307},"i-lucide-palette",{"title":309,"path":310,"stem":311,"package":11,"icon":250},"Overrides","\u002Ftheming\u002Foverrides","4.theming\u002F2.overrides",{"title":313,"path":314,"stem":315,"package":11,"icon":316},"Colors","\u002Ftheming\u002Fcolors","4.theming\u002F3.colors","i-lucide-swatch-book",{"title":318,"path":319,"stem":320,"package":11,"icon":321},"Dark Mode","\u002Ftheming\u002Fdark-mode","4.theming\u002F4.dark-mode","i-lucide-moon",{"title":323,"path":324,"stem":325,"package":11,"icon":326},"Fonts","\u002Ftheming\u002Ffonts","4.theming\u002F5.fonts","i-lucide-type",{"title":328,"path":329,"stem":330,"package":11,"icon":331},"Accessibility","\u002Faccessibility","5.accessibility","i-lucide-accessibility",{"title":333,"path":334,"stem":335,"package":11,"icon":336},"i18n","\u002Fi18n","6.i18n","i-lucide-languages",{"title":338,"path":339,"stem":340,"children":341,"package":11,"icon":343},"Composables","\u002Fcomposables","7.composables\u002F1.index",[342,344,349,354,359,364,369,374,378,383,387,391,396,401],{"title":338,"path":339,"stem":340,"package":11,"icon":343},"i-lucide-square-function",{"title":345,"path":346,"stem":347,"package":11,"icon":348},"useEmitAsProps","\u002Fcomposables\u002Fuse-emit-as-props","7.composables\u002F10.use-emit-as-props","i-lucide-zap",{"title":350,"path":351,"stem":352,"package":11,"icon":353},"useForwardPropsEmits","\u002Fcomposables\u002Fuse-forward-props-emits","7.composables\u002F11.use-forward-props-emits","i-lucide-merge",{"title":355,"path":356,"stem":357,"package":11,"icon":358},"useForwardExpose","\u002Fcomposables\u002Fuse-forward-expose","7.composables\u002F12.use-forward-expose","i-lucide-share-2",{"title":360,"path":361,"stem":362,"package":11,"icon":363},"useStateMachine","\u002Fcomposables\u002Fuse-state-machine","7.composables\u002F13.use-state-machine","i-lucide-workflow",{"title":365,"path":366,"stem":367,"package":11,"icon":368},"usePrimitiveElement","\u002Fcomposables\u002Fuse-primitive-element","7.composables\u002F14.use-primitive-element","i-lucide-crosshair",{"title":370,"path":371,"stem":372,"package":11,"icon":373},"useAppConfig","\u002Fcomposables\u002Fuse-app-config","7.composables\u002F2.use-app-config","i-lucide-settings",{"title":375,"path":376,"stem":377,"package":11,"icon":321},"useColorMode","\u002Fcomposables\u002Fuse-color-mode","7.composables\u002F3.use-color-mode",{"title":379,"path":380,"stem":381,"package":11,"icon":382},"useComponentIcons","\u002Fcomposables\u002Fuse-component-icons","7.composables\u002F4.use-component-icons","i-lucide-shapes",{"title":384,"path":385,"stem":386,"package":11,"icon":69},"useTray","\u002Fcomposables\u002Fuse-tray","7.composables\u002F5.use-tray",{"title":388,"path":389,"stem":390,"package":11,"icon":336},"i18n composables","\u002Fcomposables\u002Fi18n-composables","7.composables\u002F6.i18n-composables",{"title":392,"path":393,"stem":394,"package":11,"icon":395},"useId","\u002Fcomposables\u002Fuse-id","7.composables\u002F7.use-id","i-lucide-hash",{"title":397,"path":398,"stem":399,"package":11,"icon":400},"useFilter","\u002Fcomposables\u002Fuse-filter","7.composables\u002F8.use-filter","i-lucide-filter",{"title":402,"path":403,"stem":404,"package":11,"icon":405},"useForwardProps","\u002Fcomposables\u002Fuse-forward-props","7.composables\u002F9.use-forward-props","i-lucide-arrow-right-left",{"title":407,"path":408,"stem":409,"children":410,"package":11,"icon":412},"Guides","\u002Fguides","8.guides\u002F1.index",[411,413,417,422,427,432,436,441,445,450],{"title":407,"path":408,"stem":409,"package":11,"icon":412},"i-lucide-book-open",{"title":414,"path":415,"stem":416,"package":11,"icon":348},"Instant first-frame rendering","\u002Fguides\u002Finstant-first-frame-rendering","8.guides\u002F10.instant-first-frame-rendering",{"title":418,"path":419,"stem":420,"package":11,"icon":421},"Lynx UI frameworks","\u002Fguides\u002Flynx-ui-frameworks","8.guides\u002F2.lynx-ui-frameworks","i-lucide-library",{"title":423,"path":424,"stem":425,"package":11,"icon":426},"What is Vue Lynx","\u002Fguides\u002Fvue-lynx","8.guides\u002F3.vue-lynx","i-lucide-component",{"title":428,"path":429,"stem":430,"package":11,"icon":431},"Lynx vs React Native","\u002Fguides\u002Flynx-vs-react-native","8.guides\u002F4.lynx-vs-react-native","i-lucide-git-compare",{"title":433,"path":434,"stem":435,"package":11,"icon":84},"Testing on your phone","\u002Fguides\u002Ftesting-on-device","8.guides\u002F5.testing-on-device",{"title":437,"path":438,"stem":439,"package":11,"icon":440},"Testing with Xcode","\u002Fguides\u002Ftesting-with-xcode","8.guides\u002F6.testing-with-xcode","i-lucide-apple",{"title":442,"path":443,"stem":444,"package":11,"icon":27},"The rspeedy dev server","\u002Fguides\u002Frspeedy-dev-server","8.guides\u002F7.rspeedy-dev-server",{"title":446,"path":447,"stem":448,"package":11,"icon":449},"Tailwind on Lynx","\u002Fguides\u002Ftailwind-on-lynx","8.guides\u002F8.tailwind-on-lynx","i-lucide-wind",{"title":451,"path":452,"stem":453,"package":11,"icon":454},"Theming on Lynx","\u002Fguides\u002Ftheming-on-lynx","8.guides\u002F9.theming-on-lynx","i-lucide-paintbrush",{"id":456,"title":414,"body":457,"description":1772,"extension":1773,"links":11,"meta":1774,"navigation":1775,"package":11,"path":415,"seo":1776,"stem":416,"__hash__":1779},"docs\u002F8.guides\u002F10.instant-first-frame-rendering.md",{"type":458,"value":459,"toc":1757},"minimark",[460,473,484,489,644,655,659,670,677,681,700,711,715,722,833,836,840,847,850,857,868,871,931,950,954,989,999,1002,1160,1167,1171,1180,1184,1187,1247,1253,1262,1311,1314,1318,1321,1463,1538,1541,1623,1629,1681,1688,1694,1698,1717,1728,1731,1735,1753],[461,462,463,464,468,469,472],"p",{},"A Lynx app launches into nothing. The main thread loads the template and waits while the background thread boots its JavaScript engine, evaluates your bundle, renders the Vue tree, and ships an ops batch back across the thread boundary. Vue Lynx 0.5 added Instant First-Frame Rendering to close that gap: with ",[465,466,467],"code",{},"enableIFR: true"," the main-thread bundle carries the Vue runtime and your app, so the first screen renders synchronously inside ",[465,470,471],{},"loadTemplate"," while the background thread is still starting.",[461,474,475,476,483],{},"The background thread then hydrates against a recording of the ops the main thread already applied, and takes ownership of the tree. ",[477,478,482],"a",{"href":479,"rel":480},"https:\u002F\u002Fvue.lynxjs.org\u002Fguide\u002Fifr",[481],"nofollow","Vue Lynx's own page"," documents that machinery. This page is the part that touches your components, where a render running twice changes what you are allowed to write.",[485,486,488],"h2",{"id":487},"turning-it-on","Turning it on",[490,491,497],"pre",{"className":492,"code":493,"filename":494,"language":495,"meta":496,"style":496},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { defineConfig } from '@lynx-js\u002Frspeedy'\nimport { pluginVueLynx } from 'vue-lynx\u002Fplugin'\n\nexport default defineConfig({\n  plugins: [\n    pluginVueLynx({\n      enableIFR: true,\n    }),\n  ],\n})\n","lynx.config.ts","ts","",[465,498,499,532,553,560,578,591,601,616,627,635],{"__ignoreMap":496},[500,501,504,508,512,516,519,522,525,529],"span",{"class":502,"line":503},"line",1,[500,505,507],{"class":506},"s7zQu","import",[500,509,511],{"class":510},"sMK4o"," {",[500,513,515],{"class":514},"sTEyZ"," defineConfig",[500,517,518],{"class":510}," }",[500,520,521],{"class":506}," from",[500,523,524],{"class":510}," '",[500,526,528],{"class":527},"sfazB","@lynx-js\u002Frspeedy",[500,530,531],{"class":510},"'\n",[500,533,535,537,539,542,544,546,548,551],{"class":502,"line":534},2,[500,536,507],{"class":506},[500,538,511],{"class":510},[500,540,541],{"class":514}," pluginVueLynx",[500,543,518],{"class":510},[500,545,521],{"class":506},[500,547,524],{"class":510},[500,549,550],{"class":527},"vue-lynx\u002Fplugin",[500,552,531],{"class":510},[500,554,556],{"class":502,"line":555},3,[500,557,559],{"emptyLinePlaceholder":558},true,"\n",[500,561,563,566,569,572,575],{"class":502,"line":562},4,[500,564,565],{"class":506},"export",[500,567,568],{"class":506}," default",[500,570,515],{"class":571},"s2Zo4",[500,573,574],{"class":514},"(",[500,576,577],{"class":510},"{\n",[500,579,581,585,588],{"class":502,"line":580},5,[500,582,584],{"class":583},"swJcz","  plugins",[500,586,587],{"class":510},":",[500,589,590],{"class":514}," [\n",[500,592,594,597,599],{"class":502,"line":593},6,[500,595,596],{"class":571},"    pluginVueLynx",[500,598,574],{"class":514},[500,600,577],{"class":510},[500,602,604,607,609,613],{"class":502,"line":603},7,[500,605,606],{"class":583},"      enableIFR",[500,608,587],{"class":510},[500,610,612],{"class":611},"sfNiH"," true",[500,614,615],{"class":510},",\n",[500,617,619,622,625],{"class":502,"line":618},8,[500,620,621],{"class":510},"    }",[500,623,624],{"class":514},")",[500,626,615],{"class":510},[500,628,630,633],{"class":502,"line":629},9,[500,631,632],{"class":514},"  ]",[500,634,615],{"class":510},[500,636,638,641],{"class":502,"line":637},10,[500,639,640],{"class":510},"}",[500,642,643],{"class":514},")\n",[461,645,646,647,650,651,654],{},"Element Templates come with it, because ",[465,648,649],{},"enableIFR"," turns on ",[465,652,653],{},"enableElementTemplates"," unless you say otherwise. Nothing in a typical component tree has to change.",[485,656,658],{"id":657},"keep-the-first-render-deterministic","Keep the first render deterministic",[461,660,661,662,665,666,669],{},"The render now executes once per thread, so it has to be a pure function of its inputs. ",[465,663,664],{},"Math.random()",", ",[465,667,668],{},"Date.now()",", and a branch that tests which thread it is running on all produce two different trees, and the background pass then tears down the first frame and rebuilds it from scratch.",[461,671,672,676],{},[673,674,675],"strong",{},"Rule for first screens:"," everything the render reads has to resolve the same way on both threads.",[485,678,680],{"id":679},"put-side-effects-in-composition-api-hooks","Put side effects in Composition API hooks",[461,682,683,684,665,687,665,690,665,693,665,696,699],{},"Vue Lynx re-exports ",[465,685,686],{},"onMounted",[465,688,689],{},"onBeforeMount",[465,691,692],{},"onUpdated",[465,694,695],{},"onUnmounted",[465,697,698],{},"onActivated"," and their siblings wrapped so registration is a no-op during the main-thread pass. Fetching, timers, and subscriptions written in those hooks therefore run once, on the background thread.",[461,701,702,703,706,707,710],{},"Options API ",[465,704,705],{},"mounted()"," is not suppressed yet, so a component with a side effect there runs it on both threads. Passing ",[465,708,709],{},"optionsApi: false"," to the plugin, as our example apps do, keeps the question from arising.",[485,712,714],{"id":713},"mount-a-shell-rather-than-skipping-the-mount","Mount a shell rather than skipping the mount",[461,716,717,718,721],{},"IFR only paints what exists synchronously, so the instinct on a network-driven screen is to skip ",[465,719,720],{},"app.mount()"," entirely. Skipping it buys the larger main-thread bundle and no first paint at all, which is the worst of both configurations. Mount, render a skeleton, and gate the network work instead.",[490,723,725],{"className":492,"code":724,"language":495,"meta":496,"style":496},"import { isIfrMainThread } from 'vue-lynx'\n\nconst { data } = useQuery({\n  queryKey: ['feed'],\n  queryFn: fetchFeed,\n  enabled: !isIfrMainThread(),\n})\n",[465,726,727,747,751,774,797,809,827],{"__ignoreMap":496},[500,728,729,731,733,736,738,740,742,745],{"class":502,"line":503},[500,730,507],{"class":506},[500,732,511],{"class":510},[500,734,735],{"class":514}," isIfrMainThread",[500,737,518],{"class":510},[500,739,521],{"class":506},[500,741,524],{"class":510},[500,743,744],{"class":527},"vue-lynx",[500,746,531],{"class":510},[500,748,749],{"class":502,"line":534},[500,750,559],{"emptyLinePlaceholder":558},[500,752,753,757,759,762,764,767,770,772],{"class":502,"line":555},[500,754,756],{"class":755},"spNyl","const",[500,758,511],{"class":510},[500,760,761],{"class":514}," data ",[500,763,640],{"class":510},[500,765,766],{"class":510}," =",[500,768,769],{"class":571}," useQuery",[500,771,574],{"class":514},[500,773,577],{"class":510},[500,775,776,779,781,784,787,790,792,795],{"class":502,"line":562},[500,777,778],{"class":583},"  queryKey",[500,780,587],{"class":510},[500,782,783],{"class":514}," [",[500,785,786],{"class":510},"'",[500,788,789],{"class":527},"feed",[500,791,786],{"class":510},[500,793,794],{"class":514},"]",[500,796,615],{"class":510},[500,798,799,802,804,807],{"class":502,"line":580},[500,800,801],{"class":583},"  queryFn",[500,803,587],{"class":510},[500,805,806],{"class":514}," fetchFeed",[500,808,615],{"class":510},[500,810,811,814,816,819,822,825],{"class":502,"line":593},[500,812,813],{"class":583},"  enabled",[500,815,587],{"class":510},[500,817,818],{"class":510}," !",[500,820,821],{"class":571},"isIfrMainThread",[500,823,824],{"class":514},"()",[500,826,615],{"class":510},[500,828,829,831],{"class":502,"line":603},[500,830,640],{"class":510},[500,832,643],{"class":514},[461,834,835],{},"Vue Lynx's own Hacker News example moved from skipping the mount to painting a chrome-and-spinner shell, and its measured FCP went from 38% worse than the no-IFR build to 12% better.",[485,837,839],{"id":838},"read-the-hydration-warning-as-a-performance-bug","Read the hydration warning as a performance bug",[461,841,842,843,846],{},"Identical ops batches are skipped because their result is already on screen, and text, style, and attribute differences are patched in place. A structural difference removes the first-frame tree and rebuilds it from the background ops, which logs ",[465,844,845],{},"[vue-lynx] IFR hydration mismatch"," in development.",[461,848,849],{},"Correctness never depended on the two renders matching, so the app still renders. What you lost is the speedup, which makes that warning worth chasing rather than silencing.",[485,851,853,854,856],{"id":852},"leave-enableelementtemplates-alone","Leave ",[465,855,653],{}," alone",[461,858,859,860,863,864,867],{},"Element Templates change how much work the synchronous render does. The compiler collapses a static subtree into a generated ",[465,861,862],{},"create()"," function and sends one ",[465,865,866],{},"INSTANTIATE_TEMPLATE"," op instead of per-node ops, patching only the dynamic holes afterwards. On a roughly 1,000-element scene that takes the render from about 8.4ms to 1.3ms, and a 1,400-element static screen ships 69 bytes of ops instead of 78KB.",[461,869,870],{},"A subtree qualifies when every node is a plain Lynx element and only property values or text content vary:",[490,872,876],{"className":873,"code":874,"language":875,"meta":496,"style":496},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cview class=\"card\">                      \u003C!-- lowered -->\n  \u003Cimage class=\"icon\" src=\"a.png\" \u002F>     \u003C!-- baked into the skeleton -->\n  \u003Ctext class=\"title\">{{ title }}\u003C\u002Ftext> \u003C!-- dynamic text hole -->\n  \u003Cview :class=\"badgeClass\" \u002F>           \u003C!-- dynamic class hole -->\n\u003C\u002Fview>\n","vue",[465,877,878,906,911,916,921],{"__ignoreMap":496},[500,879,880,883,886,889,892,895,898,900,903],{"class":502,"line":503},[500,881,882],{"class":510},"\u003C",[500,884,885],{"class":583},"view",[500,887,888],{"class":755}," class",[500,890,891],{"class":510},"=",[500,893,894],{"class":510},"\"",[500,896,897],{"class":527},"card",[500,899,894],{"class":510},[500,901,902],{"class":510},">",[500,904,905],{"class":514},"                      \u003C!-- lowered -->\n",[500,907,908],{"class":502,"line":534},[500,909,910],{"class":514},"  \u003Cimage class=\"icon\" src=\"a.png\" \u002F>     \u003C!-- baked into the skeleton -->\n",[500,912,913],{"class":502,"line":555},[500,914,915],{"class":514},"  \u003Ctext class=\"title\">{{ title }}\u003C\u002Ftext> \u003C!-- dynamic text hole -->\n",[500,917,918],{"class":502,"line":562},[500,919,920],{"class":514},"  \u003Cview :class=\"badgeClass\" \u002F>           \u003C!-- dynamic class hole -->\n",[500,922,923,926,928],{"class":502,"line":580},[500,924,925],{"class":510},"\u003C\u002F",[500,927,885],{"class":583},[500,929,930],{"class":510},">\n",[461,932,933,934,937,938,941,942,945,946,949],{},"Components, slots, ",[465,935,936],{},"v-if"," and ",[465,939,940],{},"v-for"," hosts, refs, keys, runtime directives, ",[465,943,944],{},"\u003Clist>",", and mixed dynamic text runs stay on the normal vnode path, though the plain-element bodies inside them can still be lowered. Scoped CSS survives, since the compiler bakes the scope ID into each lowered element. Reach for ",[465,947,948],{},"enableElementTemplates: false"," only to bisect a suspected lowering bug, never as a performance setting.",[485,951,953],{"id":952},"dev-only-the-hmr-websocket-polyfill-breaks-the-main-thread-pass","Dev-only: the HMR WebSocket polyfill breaks the main-thread pass",[461,955,956,959,960,963,964,967,968,971,972,975,976,978,979,981,982,984,985,988],{},[465,957,958],{},"rspeedy dev"," injects ",[465,961,962],{},"WebSocket"," into Lynx builds through a ",[465,965,966],{},"ProvidePlugin"," pointed at ",[465,969,970],{},"@lynx-js\u002Fwebsocket",", and that module calls ",[465,973,974],{},"lynx.getJSModule('GlobalEventEmitter')"," at module scope. The function does not exist on the main thread, so any graph holding a reference to ",[465,977,962],{}," throws during the IFR pass. Every Vy UI app holds one, because ",[465,980,355],{}," in ",[465,983,41],{}," imports ",[465,986,987],{},"@vueuse\u002Fcore"," and the kit plugin imports core.",[461,990,991,992,994,995,998],{},"What you see does not point at any of that. Evaluation dies before ",[465,993,720],{},", no element template ever registers, the screen fills with placeholder boxes, and the console repeats ",[465,996,997],{},"[vue-lynx] Unknown element template \"…\" on the main thread — rendering a placeholder",".",[461,1000,1001],{},"Production builds do not inject the polyfill, so this is a dev-server problem only. Until the polyfill defers that call, give the main thread something to find before the rest of your imports evaluate:",[490,1003,1006],{"className":492,"code":1004,"filename":1005,"language":495,"meta":496,"style":496},"\u002F\u002F Must come first — the polyfill runs at module scope.\nconst l = lynx as unknown as { getJSModule?: (name: string) => unknown }\nif (typeof l.getJSModule !== 'function') {\n  l.getJSModule = () => ({ addListener() {}, removeListener() {}, trigger() {}, emit() {} })\n}\n","src\u002Findex.ts",[465,1007,1008,1014,1066,1099,1155],{"__ignoreMap":496},[500,1009,1010],{"class":502,"line":503},[500,1011,1013],{"class":1012},"sHwdD","\u002F\u002F Must come first — the polyfill runs at module scope.\n",[500,1015,1016,1018,1021,1023,1026,1029,1033,1036,1038,1041,1044,1047,1051,1053,1056,1058,1061,1063],{"class":502,"line":534},[500,1017,756],{"class":755},[500,1019,1020],{"class":514}," l ",[500,1022,891],{"class":510},[500,1024,1025],{"class":514}," lynx ",[500,1027,1028],{"class":506},"as",[500,1030,1032],{"class":1031},"sBMFI"," unknown",[500,1034,1035],{"class":506}," as",[500,1037,511],{"class":510},[500,1039,1040],{"class":583}," getJSModule",[500,1042,1043],{"class":510},"?:",[500,1045,1046],{"class":510}," (",[500,1048,1050],{"class":1049},"sHdIc","name",[500,1052,587],{"class":510},[500,1054,1055],{"class":1031}," string",[500,1057,624],{"class":510},[500,1059,1060],{"class":755}," =>",[500,1062,1032],{"class":1031},[500,1064,1065],{"class":510}," }\n",[500,1067,1068,1071,1073,1076,1079,1081,1084,1087,1089,1092,1094,1097],{"class":502,"line":555},[500,1069,1070],{"class":506},"if",[500,1072,1046],{"class":514},[500,1074,1075],{"class":510},"typeof",[500,1077,1078],{"class":514}," l",[500,1080,998],{"class":510},[500,1082,1083],{"class":514},"getJSModule ",[500,1085,1086],{"class":510},"!==",[500,1088,524],{"class":510},[500,1090,1091],{"class":527},"function",[500,1093,786],{"class":510},[500,1095,1096],{"class":514},") ",[500,1098,577],{"class":510},[500,1100,1101,1104,1106,1109,1111,1114,1116,1118,1121,1124,1126,1129,1132,1134,1136,1139,1141,1143,1146,1148,1151,1153],{"class":502,"line":562},[500,1102,1103],{"class":514},"  l",[500,1105,998],{"class":510},[500,1107,1108],{"class":571},"getJSModule",[500,1110,766],{"class":510},[500,1112,1113],{"class":510}," ()",[500,1115,1060],{"class":755},[500,1117,1046],{"class":583},[500,1119,1120],{"class":510},"{",[500,1122,1123],{"class":583}," addListener",[500,1125,824],{"class":510},[500,1127,1128],{"class":510}," {},",[500,1130,1131],{"class":583}," removeListener",[500,1133,824],{"class":510},[500,1135,1128],{"class":510},[500,1137,1138],{"class":583}," trigger",[500,1140,824],{"class":510},[500,1142,1128],{"class":510},[500,1144,1145],{"class":583}," emit",[500,1147,824],{"class":510},[500,1149,1150],{"class":510}," {}",[500,1152,518],{"class":510},[500,1154,643],{"class":583},[500,1156,1157],{"class":502,"line":580},[500,1158,1159],{"class":510},"}\n",[461,1161,1162,1163,1166],{},"Pointing ",[465,1164,1165],{},"dev.client.websocketTransport"," at a module that requires the real polyfill lazily works too, and costs a build-config entry instead of a global patch.",[485,1168,1170],{"id":1169},"expect-a-short-dead-zone-for-events","Expect a short dead zone for events",[461,1172,1173,1174,1179],{},"Between first paint and background hydration the handler registry does not exist, so a tap in that window can be dropped. ",[477,1175,1178],{"href":1176,"rel":1177},"https:\u002F\u002Fvue.lynxjs.org\u002Fguide\u002Fmain-thread-script",[481],"Main-thread script"," handlers are unaffected because they already live on the main thread, which covers Vy UI's gesture surfaces.",[485,1181,1183],{"id":1182},"watch-the-bundle-especially-on-web","Watch the bundle, especially on web",[461,1185,1186],{},"The application now lives in both bundles and evaluates on both threads.",[1188,1189,1190,1203],"table",{},[1191,1192,1193],"thead",{},[1194,1195,1196,1200],"tr",{},[1197,1198,1199],"th",{},"cost",[1197,1201,1202],{},"measured on Vue Lynx's example suite",[1204,1205,1206,1218,1226,1239],"tbody",{},[1194,1207,1208,1215],{},[1209,1210,1211,1214],"td",{},[465,1212,1213],{},"main.lynx.bundle"," gzip",[1209,1216,1217],{},"about 2.26× larger at the median",[1194,1219,1220,1223],{},[1209,1221,1222],{},"Serial-work TTI proxy",[1209,1224,1225],{},"about 35% higher",[1194,1227,1228,1231],{},[1209,1229,1230],{},"Large apps under 4× CPU throttle",[1209,1232,1233,1234,1238],{},"FCP 25% to 44% ",[1235,1236,1237],"em",{},"worse"," on Elk and AI Chat",[1194,1240,1241,1244],{},[1209,1242,1243],{},"Content-first screens, full speed",[1209,1245,1246],{},"FCP roughly 12% to 26% better",[461,1248,1249,1250,1252],{},"A kit app lands at the heavier end of that range. A 30-card screen built from ",[465,1251,46],{}," went from 140.2KB to 367.8KB gzipped, or 2.62×, because the styled components and their theme tables now ship on both threads.",[461,1254,1255,1256,1261],{},"On the web, bundle parse sits directly on the FCP path, so the flag that wins on a small content-first screen can lose on a large one over a throttled CPU. Vue Lynx publishes both results rather than one headline number, and its ",[477,1257,1260],{"href":1258,"rel":1259},"https:\u002F\u002Fvue.lynxjs.org\u002Fguide\u002Fifr-benchmarks",[481],"benchmark page"," has the full campaigns.",[1188,1263,1264,1274],{},[1191,1265,1266],{},[1194,1267,1268,1271],{},[1197,1269,1270],{},"your first screen",[1197,1272,1273],{},"do this",[1204,1275,1276,1284,1295,1303],{},[1194,1277,1278,1281],{},[1209,1279,1280],{},"Renders from synchronous data",[1209,1282,1283],{},"Enable it",[1194,1285,1286,1289],{},[1209,1287,1288],{},"Fetch-driven, but has a real shell or skeleton",[1209,1290,1291,1292],{},"Enable it, and gate fetches on ",[465,1293,1294],{},"isIfrMainThread()",[1194,1296,1297,1300],{},[1209,1298,1299],{},"Fetch-driven with nothing useful to paint",[1209,1301,1302],{},"Build the shell first, then enable",[1194,1304,1305,1308],{},[1209,1306,1307],{},"Large bundle, slow CPU, web target",[1209,1309,1310],{},"Measure before committing, since throttling can reverse the win",[461,1312,1313],{},"CSS Module class names are a smaller surprise in the same area, since they can appear un-hashed on the first frame and get patched to their final names during hydration.",[485,1315,1317],{"id":1316},"prove-it-on-your-own-app","Prove it on your own app",[461,1319,1320],{},"Published medians will not tell you whether your first screen wins, and IFR is unusually easy to test because the same source builds both ways. Read the flag from an environment variable and add a second script:",[490,1322,1324],{"className":492,"code":1323,"filename":494,"language":495,"meta":496,"style":496},"const enableIFR = process.env.VYUI_IFR !== '0'\n\nexport default defineConfig({\n  source: {\n    define: { __IFR__: JSON.stringify(enableIFR) },\n  },\n  plugins: [\n    pluginVueLynx({ optionsApi: false, enableIFR }),\n  ],\n})\n",[465,1325,1326,1357,1361,1373,1383,1411,1416,1424,1451,1457],{"__ignoreMap":496},[500,1327,1328,1330,1333,1335,1338,1340,1343,1345,1348,1350,1352,1355],{"class":502,"line":503},[500,1329,756],{"class":755},[500,1331,1332],{"class":514}," enableIFR ",[500,1334,891],{"class":510},[500,1336,1337],{"class":514}," process",[500,1339,998],{"class":510},[500,1341,1342],{"class":514},"env",[500,1344,998],{"class":510},[500,1346,1347],{"class":514},"VYUI_IFR ",[500,1349,1086],{"class":510},[500,1351,524],{"class":510},[500,1353,1354],{"class":527},"0",[500,1356,531],{"class":510},[500,1358,1359],{"class":502,"line":534},[500,1360,559],{"emptyLinePlaceholder":558},[500,1362,1363,1365,1367,1369,1371],{"class":502,"line":555},[500,1364,565],{"class":506},[500,1366,568],{"class":506},[500,1368,515],{"class":571},[500,1370,574],{"class":514},[500,1372,577],{"class":510},[500,1374,1375,1378,1380],{"class":502,"line":562},[500,1376,1377],{"class":583},"  source",[500,1379,587],{"class":510},[500,1381,1382],{"class":510}," {\n",[500,1384,1385,1388,1390,1392,1395,1397,1400,1402,1405,1408],{"class":502,"line":580},[500,1386,1387],{"class":583},"    define",[500,1389,587],{"class":510},[500,1391,511],{"class":510},[500,1393,1394],{"class":583}," __IFR__",[500,1396,587],{"class":510},[500,1398,1399],{"class":514}," JSON",[500,1401,998],{"class":510},[500,1403,1404],{"class":571},"stringify",[500,1406,1407],{"class":514},"(enableIFR) ",[500,1409,1410],{"class":510},"},\n",[500,1412,1413],{"class":502,"line":593},[500,1414,1415],{"class":510},"  },\n",[500,1417,1418,1420,1422],{"class":502,"line":603},[500,1419,584],{"class":583},[500,1421,587],{"class":510},[500,1423,590],{"class":514},[500,1425,1426,1428,1430,1432,1435,1437,1440,1443,1445,1447,1449],{"class":502,"line":618},[500,1427,596],{"class":571},[500,1429,574],{"class":514},[500,1431,1120],{"class":510},[500,1433,1434],{"class":583}," optionsApi",[500,1436,587],{"class":510},[500,1438,1439],{"class":611}," false",[500,1441,1442],{"class":510},",",[500,1444,1332],{"class":514},[500,1446,640],{"class":510},[500,1448,624],{"class":514},[500,1450,615],{"class":510},[500,1452,1453,1455],{"class":502,"line":629},[500,1454,632],{"class":514},[500,1456,615],{"class":510},[500,1458,1459,1461],{"class":502,"line":637},[500,1460,640],{"class":510},[500,1462,643],{"class":514},[490,1464,1469],{"className":1465,"code":1466,"filename":1467,"language":1468,"meta":496,"style":496},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"scripts\": {\n    \"dev\": \"rspeedy dev\",\n    \"dev:noifr\": \"VYUI_IFR=0 rspeedy dev\"\n  }\n}\n","package.json","json",[465,1470,1471,1475,1489,1510,1529,1534],{"__ignoreMap":496},[500,1472,1473],{"class":502,"line":503},[500,1474,577],{"class":510},[500,1476,1477,1480,1483,1485,1487],{"class":502,"line":534},[500,1478,1479],{"class":510},"  \"",[500,1481,1482],{"class":755},"scripts",[500,1484,894],{"class":510},[500,1486,587],{"class":510},[500,1488,1382],{"class":510},[500,1490,1491,1494,1497,1499,1501,1504,1506,1508],{"class":502,"line":555},[500,1492,1493],{"class":510},"    \"",[500,1495,1496],{"class":1031},"dev",[500,1498,894],{"class":510},[500,1500,587],{"class":510},[500,1502,1503],{"class":510}," \"",[500,1505,958],{"class":527},[500,1507,894],{"class":510},[500,1509,615],{"class":510},[500,1511,1512,1514,1517,1519,1521,1523,1526],{"class":502,"line":562},[500,1513,1493],{"class":510},[500,1515,1516],{"class":1031},"dev:noifr",[500,1518,894],{"class":510},[500,1520,587],{"class":510},[500,1522,1503],{"class":510},[500,1524,1525],{"class":527},"VYUI_IFR=0 rspeedy dev",[500,1527,1528],{"class":510},"\"\n",[500,1530,1531],{"class":502,"line":580},[500,1532,1533],{"class":510},"  }\n",[500,1535,1536],{"class":502,"line":593},[500,1537,1159],{"class":510},[461,1539,1540],{},"Two more things make the difference legible on a device without a profiler. The first is a deliberate boot cost in the entry, gated so it only runs where a real app's startup would:",[490,1542,1544],{"className":492,"code":1543,"filename":1005,"language":495,"meta":496,"style":496},"if (!isIfrMainThread()) {\n  const until = Date.now() + 1200\n  while (Date.now() \u003C until) { \u002F* stand in for module eval, store setup, i18n *\u002F }\n}\n",[465,1545,1546,1562,1590,1619],{"__ignoreMap":496},[500,1547,1548,1550,1552,1555,1557,1560],{"class":502,"line":503},[500,1549,1070],{"class":506},[500,1551,1046],{"class":514},[500,1553,1554],{"class":510},"!",[500,1556,821],{"class":571},[500,1558,1559],{"class":514},"()) ",[500,1561,577],{"class":510},[500,1563,1564,1567,1570,1572,1575,1577,1580,1583,1586],{"class":502,"line":534},[500,1565,1566],{"class":755},"  const",[500,1568,1569],{"class":514}," until",[500,1571,766],{"class":510},[500,1573,1574],{"class":514}," Date",[500,1576,998],{"class":510},[500,1578,1579],{"class":571},"now",[500,1581,1582],{"class":583},"() ",[500,1584,1585],{"class":510},"+",[500,1587,1589],{"class":1588},"sbssI"," 1200\n",[500,1591,1592,1595,1597,1600,1602,1604,1606,1608,1610,1612,1614,1617],{"class":502,"line":555},[500,1593,1594],{"class":506},"  while",[500,1596,1046],{"class":583},[500,1598,1599],{"class":514},"Date",[500,1601,998],{"class":510},[500,1603,1579],{"class":571},[500,1605,1582],{"class":583},[500,1607,882],{"class":510},[500,1609,1569],{"class":514},[500,1611,1096],{"class":583},[500,1613,1120],{"class":510},[500,1615,1616],{"class":1012}," \u002F* stand in for module eval, store setup, i18n *\u002F",[500,1618,1065],{"class":510},[500,1620,1621],{"class":502,"line":562},[500,1622,1159],{"class":510},[461,1624,1625,1626,1628],{},"The second is a badge driven by ",[465,1627,686],{},", which is suppressed on the main-thread pass and therefore reads as false on the first frame:",[490,1630,1632],{"className":492,"code":1631,"language":495,"meta":496,"style":496},"const hydrated = ref(false)\nonMounted(() => { hydrated.value = true })\n",[465,1633,1634,1653],{"__ignoreMap":496},[500,1635,1636,1638,1641,1643,1646,1648,1651],{"class":502,"line":503},[500,1637,756],{"class":755},[500,1639,1640],{"class":514}," hydrated ",[500,1642,891],{"class":510},[500,1644,1645],{"class":571}," ref",[500,1647,574],{"class":514},[500,1649,1650],{"class":611},"false",[500,1652,643],{"class":514},[500,1654,1655,1657,1659,1661,1663,1665,1668,1670,1673,1675,1677,1679],{"class":502,"line":534},[500,1656,686],{"class":571},[500,1658,574],{"class":514},[500,1660,824],{"class":510},[500,1662,1060],{"class":755},[500,1664,511],{"class":510},[500,1666,1667],{"class":514}," hydrated",[500,1669,998],{"class":510},[500,1671,1672],{"class":514},"value",[500,1674,766],{"class":510},[500,1676,612],{"class":611},[500,1678,518],{"class":510},[500,1680,643],{"class":514},[461,1682,1683,1684,1687],{},"Launch both builds and watch. With IFR the content paints immediately and the badge holds its pre-hydration state for the length of the spin, and without it the screen stays blank for that whole window before arriving complete. Piping ",[465,1685,1686],{},"__IFR__"," into a second badge leaves a screen recording that labels itself.",[461,1689,1690,1691,1693],{},"Two details keep the harness honest. The marker has to be a text or class difference rather than a ",[465,1692,936],{},", because a structural difference between the passes triggers the rebuild and you end up timing the fallback instead of IFR. List content should come from the index rather than from anything random, for the same reason.",[485,1695,1697],{"id":1696},"vy-ui-under-ifr","Vy UI under IFR",[461,1699,1700,1701,1704,1705,937,1707,1709,1710,1713,1714,1716],{},"Our peer range covers ",[465,1702,1703],{},"vue-lynx@^0.5.1",", so the flag is available to any project on the current release. Every component in ",[465,1706,41],{},[465,1708,46],{}," is written with ",[465,1711,1712],{},"\u003Cscript setup>",", so their lifecycle hooks are the suppressed kind and no component effect fires twice. The IDs behind the accessibility wiring come from ",[465,1715,392],{},", which counts render order rather than generating randomness, so both passes produce the same values.",[461,1718,1719,1720,1723,1724,1727],{},"Main-thread gesture code is the part to watch. IFR keeps the worklet-transformed output on the main thread, and our worklets still depend on the ",[465,1721,1722],{},"includeWorkletPackages"," entry that ",[477,1725,1726],{"href":15},"installation"," covers. That requirement does not change under IFR; it only matters more, because more of your code now evaluates on that thread.",[461,1729,1730],{},"Overlays, sheets, toasts, and anything animated mount after the first paint by definition, so IFR neither helps nor harms them. The screen it speeds up is the static content underneath.",[485,1732,1734],{"id":1733},"related","Related",[1736,1737,1738,1743,1748],"card-group",{},[897,1739,1740],{"icon":426,"title":423,"to":424},[461,1741,1742],{},"The dual-thread model IFR is working around.",[897,1744,1745],{"icon":27,"title":442,"to":443},[461,1746,1747],{},"Where the config in this guide gets picked up.",[897,1749,1750],{"icon":84,"title":433,"to":434},[461,1751,1752],{},"Measuring a first frame where it actually counts.",[1754,1755,1756],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":496,"searchDepth":503,"depth":534,"links":1758},[1759,1760,1761,1762,1763,1764,1766,1767,1768,1769,1770,1771],{"id":487,"depth":534,"text":488},{"id":657,"depth":534,"text":658},{"id":679,"depth":534,"text":680},{"id":713,"depth":534,"text":714},{"id":838,"depth":534,"text":839},{"id":852,"depth":534,"text":1765},"Leave enableElementTemplates alone",{"id":952,"depth":534,"text":953},{"id":1169,"depth":534,"text":1170},{"id":1182,"depth":534,"text":1183},{"id":1316,"depth":534,"text":1317},{"id":1696,"depth":534,"text":1697},{"id":1733,"depth":534,"text":1734},"Vue Lynx 0.5 can render your first screen on the main thread before any background JavaScript runs, which removes the blank frame at launch. The flag, the rules your components have to obey, and what it costs.","md",{},{"icon":348},{"title":1777,"description":1778},"Vue Lynx IFR — tips for painting the first screen before JS boots","Practical notes on Instant First-Frame Rendering in Vue Lynx. Enabling it, keeping the first render deterministic, shelling fetch-driven screens with isIfrMainThread, Element Templates, and the bundle-size trade-off.","x7KjdmjfauzukHAjx7chooyJIkKEHNeBrgBMLro4Fu8",[1781,1783],{"title":407,"path":408,"stem":409,"description":1782,"icon":-1,"children":-1,"navigation":-1},"Background on Lynx, Vue Lynx, and the component libraries built for them — the context around Vy UI rather than its API.",{"title":418,"path":419,"stem":420,"description":1784,"icon":-1,"children":-1,"navigation":-1},"A comparison of the UI component libraries available for Lynx today, covering what each one ships, which framework it targets, and how mature it is.",1785008679509]