Why a2ui's JSON-Driven Layout Schema Breaks Down in Production Modal Stacks A developer evaluating the a2ui-project/a2ui generative UI framework found its JSON layout schema breaks down for nested modal stacks, as TailwindCSS utility classes fail to cascade into React portals and focus management collapses when modals are chained. The developer patched the React adapter to inject data-focus-scope attributes, but the fix requires maintaining a fork that must be manually reconciled with upstream changes between versions like v0.8.3 and v0.9.1. When evaluating a2ui-project/a2ui for a conversational dashboard rebuild, the pitch was clean: backend agents stream JSON layout descriptors, and the React adapter hydrates them into live components. No manual createElement chains, no brittle template strings. The repository ships adapters for React, Angular, Lit, Flutter, SwiftUI, and Jetpack Compose—universal generative UI. The reality hit during our first modal implementation. a2ui's layout schema handles flat component trees elegantly, but once you introduce nested modals with focus trapping and portal rendering , the abstraction starts bleeding through the seams. Our agent streams this layout descriptor: { "type": "modal", "id": "confirm-delete", "backdrop": true, "children": { "type": "box", "className": "bg-white rounded-lg shadow-xl p-6 max-w-md", "children": { "type": "text", "content": "Delete 47 items?" }, { "type": "button", "variant": "danger", "label": "Confirm" } } } The React adapter wraps this in a Radix Dialog.Root . Problem: TailwindCSS utility classes don't cascade into React portals unless you explicitly configure tailwind.config.js to scan portal roots. The modal renders, but bg-white and shadow-xl vanish—the dialog appears as unstyled gray blocks. Force Tailwind to scan portal containers: // tailwind.config.js module.exports = { content: './src/ / .{js,jsx,ts,tsx}', './node modules/@a2ui/react-adapter/ / .js', // Critical: scan React portal mount points './public/index.html' , theme: { extend: {} } }; But now you've coupled your build pipeline to a2ui's internal DOM structure. When the adapter changes its portal strategy observed between v0.8.3 and v0.9.1 , styles break silently in production. Agent streams a second modal "Are you sure?" while the first is still open. a2ui's React adapter chains Dialog.Root components, but focus management collapses : Tab inside the second modal. Escape key dismisses both modals simultaneously. Root cause: a2ui's layout schema has no explicit focus scope boundaries . The JSON descriptor treats modals as generic containers, delegating focus control entirely to the component library Radix, in this case . When you nest portals, Radix's FocusScope gets confused by React's reconciliation order. We patched the adapter to inject data-focus-scope attributes: js // Custom React adapter override import { Dialog } from '@radix-ui/react-dialog'; import { useEffect, useRef } from 'react'; function A2UIModal { descriptor, children } { const scopeRef = useRef null ; useEffect = { if scopeRef.current { scopeRef.current.focus ; } }, ; return