Skip to content

PrefabApp.stylesheets Parameter Not Applied in JSON-Based Renderer #424

@schlpbch

Description

@schlpbch

Summary

The stylesheets parameter in PrefabApp works correctly when using PrefabApp.html() to generate a complete HTML page, but the parameter is not applied when the app data is serialized to JSON and rendered by the Prefab JavaScript renderer (as used by FastMCP dev server and other JSON-based implementations).

Environment

  • Library: prefab-ui v0.19.1
  • Context: FastMCP dev server with Prefab renderer
  • Reported By: Aareguru MCP Server Project
  • Date: 2026-04-19

Expected Behavior

When PrefabApp is instantiated with stylesheets=['body { color: red; }'], the stylesheet should be:

  1. ✅ Included in PrefabApp.html() output (WORKS)
  2. ✅ Included in PrefabApp.model_dump() JSON (WORKS)
  3. ❌ Applied by the Prefab JavaScript renderer when loading from JSON (FAILS)

Actual Behavior

The stylesheets parameter:

  1. ✅ IS serialized in model_dump() output
  2. ✅ IS included in HTML when using PrefabApp.html()
  3. ❌ IS NOT applied when Prefab renderer loads the same JSON data

Reproduction Steps

Step 1: Create a PrefabApp with stylesheets

from prefab_ui.app import PrefabApp
from prefab_ui.components import Text, Column

with Column() as view:
    Text('Test')

app = PrefabApp(
    view=view,
    stylesheets=['body { background-color: red; }']
)

Step 2: Verify stylesheets are in JSON

json_data = app.model_dump()
assert 'stylesheets' in json_data
assert json_data['stylesheets'] == ['body { background-color: red; }']
# ✅ PASSES - stylesheets are serialized

Step 3: Verify stylesheets are in HTML

html = app.html()
assert 'background-color: red' in html
# ✅ PASSES - stylesheets are in generated HTML

Step 4: Load JSON in Prefab renderer (FastMCP context)

GET /ui-resource?uri=ui://prefab/tool/xxx/renderer.html
# Returns static HTML template with Prefab renderer

App JSON sent to renderer:
{
  "view": {...},
  "stylesheets": ["body { background-color: red; }"],
  ...
}

Result in browser:
- <style>body { background-color: red; }</style> NOT FOUND in page
- ❌ FAILS - stylesheet not applied

Root Cause

The Prefab JavaScript renderer (renderer.js v0.19.1) appears to:

  1. Receive the stylesheets array in the JSON payload ✓
  2. NOT process this array when rendering the app ✗
  3. NOT inject <style> tags or <link> elements ✗

The stylesheets field is serialized but not acted upon by the client-side renderer.

Evidence

Test 1: Direct HTML Generation

# Works correctly with PrefabApp.html()
html = app.html()
# Output includes: <style>body { color: red; }</style>

Test 2: JSON Serialization

# Stylesheets ARE in the JSON
app.model_dump()['stylesheets']
# Output: ['body { color: red; }']

Test 3: Browser Network Inspection

When Prefab renderer loads the app from JSON:

  • ❌ No <style> tags injected into <head>
  • ❌ No external stylesheet <link> tags created
  • ✅ App renders normally (without the custom styles)

Impact

  • Severity: Medium
  • Scope: Any implementation using Prefab JSON renderer instead of direct HTML generation
  • Affected Users:
    • FastMCP dev server users
    • Any custom Prefab implementations using JSON data binding
    • Applications that need to pass custom stylesheets dynamically

Workarounds

Users can work around this by:

  1. Use PrefabApp.html() if possible (generates complete HTML with styles)
  2. Inject styles via on_mount handler (execute JavaScript to inject <style> tag)
  3. Hardcode styles in the Prefab renderer's base CSS
  4. Use global CSS served separately from the template

Example workaround:

app = PrefabApp(
    view=view,
    stylesheets=['body { color: red; }'],  # Ignored by JSON renderer
    on_mount="const s=document.createElement('style');s.textContent='body{color:red}';document.head.appendChild(s)"
)

Suggested Solution

Option A: Renderer Support (Preferred)

  • Modify renderer.js to process the stylesheets array
  • Inject <style> tags into the page <head> on initialization

Option B: Documentation

  • Clearly document that stylesheets only works with PrefabApp.html()
  • Provide recommended pattern for passing styles to JSON renderer

Option C: New Parameter

  • Add a new inline_styles parameter specifically for JSON renderer use
  • Keep stylesheets for HTML generation only

Additional Context

Where This Occurs

  • FastMCP dev server (fastmcp dev) renders PrefabApp as JSON
  • Any implementation that:
    • Serializes PrefabApp to JSON
    • Sends it to a web client
    • Renders with the Prefab JavaScript renderer

Version Information

  • prefab-ui: 0.19.1
  • Tested with: Prefab renderer from CDN (jsDelivr)
  • Browser: Chrome/Chromium (issue is in JavaScript renderer, not browser-specific)

Related Code

  • prefab_ui/app.py - PrefabApp class
  • prefab_ui.app.renderer.js - JavaScript renderer (not in Python package)
  • src/aareguru_mcp/apps/_constants.py - Our implementation attempting to use stylesheets

Summary for Maintainers

TL;DR: The stylesheets parameter in PrefabApp is serialized to JSON but not processed by the Prefab JavaScript renderer. This works fine for HTML generation (PrefabApp.html()) but fails for JSON-based rendering (FastMCP dev server, etc.).

Impact: Users who need to pass custom CSS to dynamically rendered apps must use workarounds like on_mount JavaScript injection instead of the built-in stylesheets parameter.

Request: Either add renderer support for stylesheets or clearly document this limitation.


Reported: 2026-04-19
Project: Aareguru MCP Server (https://github.com/anthropics/aareguru-mcp)
Contact: schlpbch@gmail.com

Example Code

from prefab_ui.app import PrefabApp
from prefab_ui.components import Text, Column

with Column() as view:
    Text('Test')

app = PrefabApp(
    view=view,
    stylesheets=['body { background-color: red; }']
)

Version Information

Prefab version: 0.19.1
Python version: 3.13.7
Platform: Linux-6.17.0-22-generic-x86_64-with-glibc2.42

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working. Reports of errors, unexpected behavior, or broken functionality.rendererRelated to the TypeScript/React renderer.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions