Skip to content

[docs] Document skeletons for a fragment's own reruns - #17955

Open
lukasmasuch wants to merge 2 commits into
developfrom
docs/fragment-rerun-skeletons-in-skill
Open

lukasmasuch wants to merge 2 commits into
developfrom
docs/fragment-rerun-skeletons-in-skill

Conversation

@lukasmasuch

@lukasmasuch lukasmasuch commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Describe your changes

The embedded developing-with-streamlit skill now documents the two-block skeleton pattern for a fragment's own reruns. This is option A of change 1 in the layout-first loading spec (spec PR #17756), and it adds no new API.

A fragment's own rerun, such as a run_every refresh or a widget inside the fragment, runs only the fragment body. It never re-enters the with st.skeleton(height=...) block around the call, so without a second block the old chart just fades as stale for the whole rerun.

  • dashboards.md: adds the live_orders example with both blocks. The outer block sizes the first load, and the inner with st.skeleton() covers the fragment's own reruns. The inner block needs no height when it's the body's first element. A card that draws its own controls first gives the inner block the content's height, because the controls end the outer skeleton.
  • layouts.md, performance.md, and the templates README.md: one or two sentences each that say a block around the call covers only full-app runs, and that point to dashboards.md.

The runnable app templates need no changes: the dashboard-metrics and dashboard-compute chart cards already use the inner block with a height, which matches the controls case.

Testing Plan

  • Documentation-only change, so no new tests.
  • Manual check of the documented snippet against a frontend built from develop, using Playwright. The app is the live_orders example with a 2s uncached load and run_every="5s":
    • First load: a single 340px skeleton appears at 0.28s (the inner block stays hidden under the outer one), and the chart replaces it at 2.4s. The card height (414px) and the footer position stay the same throughout.
    • Each refresh: the overlay becomes visible about 0.6s after the refresh starts, and it clears when the chart updates. The same chart instance stays mounted, and its size doesn't change.
    • Variant with a st.segmented_control drawn before a height-less inner block: the outer skeleton ends at once, the inner skeleton shows at 40px, and the card grows by 300px when the chart arrives. That's why the docs ask for a height in this case.

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

🤖 Generated with Claude Code

Agent metrics
Type Name Count
skill checking-changes 1
skill finalizing-pr 1
skill sharing-pr-agent-artifacts 1
subagent fixing-pr 1
subagent general-purpose 2

A skeleton around a fragment's call covers only full-app runs. A
fragment whose own reruns can be slow wraps its body in a second
with st.skeleton(), as option A of the layout-first loading spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lukasmasuch lukasmasuch added impact:users PR changes affect end users change:docs PR contains documentation change labels Nov 10, 2026
@snyk-io

snyk-io Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-17955/streamlit-1.67.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts

@sfc-gh-lmasuch sfc-gh-lmasuch added the ai-final-review If applied to PR or issue will run AI review workflow with the latest generation of AI models. label Nov 10, 2026
@sfc-gh-lmasuch
sfc-gh-lmasuch marked this pull request as ready for review November 10, 2026 11:21
@lukasmasuch

Copy link
Copy Markdown
Collaborator Author

Added Agent Docs

  • two-block-skeleton-verification.md: Playwright check of the documented two-block pattern against develop. It covers the first load, run_every refreshes, and the case where controls are drawn before the inner block. It links the test app and the measurement script.

@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Nov 10, 2026
@greptile-apps

greptile-apps Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Low impact] This documentation-only PR appears safe to merge.

Summary

Documents how two st.skeleton() blocks cover full-app runs and a fragment's own reruns.

  • Fragment guides show skeletons for both full-app runs and fragment reruns.

No actionable issues found in the changes since the previous review.

Reviews (2) · Last reviewed commit: "Address AI review wording on fragment-re..." · Reviewed by Greptile

@github-actions github-actions Bot removed the ai-review If applied to PR or issue will run AI review workflow label Nov 10, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

PR #17955 changes only documentation, in the bundled developing-with-streamlit agent skill. It documents a two-block st.skeleton pattern for parallel fragments whose own reruns can be slow, such as run_every refreshes or widget interactions inside the fragment:

  • An outer with st.skeleton(height=...) around the fragment call sizes the card on the first, full-app load.
  • An inner with st.skeleton() inside the fragment body covers the fragment's own reruns. That rerun never re-enters the outer block.

references/dashboards.md gets a new live_orders example and explains when the inner block needs a height: when the card draws its controls inside the fragment before the slow content. references/layouts.md, references/performance.md, and assets/templates/apps/README.md each get a short cross-reference. No runtime, API, or template code changes.

All four reviewers (claude-opus-5-5-high, gemini-4-argon-medium, gpt-5.6-luna-xhigh, grok-4.7-medium) completed their reviews and approved. None raised a blocking issue. The remaining feedback is optional wording polish, plus one small fix to the example snippet.

Product Alignment

The PR adds no product API, configuration, or UI. It does change guidance that ships with the library and that coding agents use to generate user apps, so its effect on users is indirect. It combines existing primitives (st.skeleton and @st.fragment(parallel=..., run_every=...)), which fits "Design for Composition" ($19), "Preserve the User's Context" ($51), and "Start Minimal" ($4).

The linked layout-first loading spec is pinned to a commit that isn't on develop. All reviewers who discussed it agreed that this doesn't block the PR: it is a small docs clarification of behavior that already ships, and it adds no public surface.

The change also follows lib/streamlit/.agents/skills/AGENTS.md:

  • The pattern is easy to misuse and unlikely to be in an agent's training data, so it earns a short addition to the existing "Layout-first loading" section rather than a new page.
  • The other files get only brief pointers.
  • There are no version stamps.
  • Every file stays under 500 lines. performance.md is at 499 lines, but this PR replaces one line with one line, so it doesn't grow.

Code Quality

The reviewers agreed that the change is proportionate and well placed. The full pattern lives in dashboards.md, and the other files point to it. Two reviewers independently checked the documented behavior against the frontend, and I confirmed their findings:

  • getLoadingBlockState marks a loading block as pending during a fragment run only when the block belongs to the running fragment. The outer block, created by the main script, therefore doesn't cover the fragment's own reruns.
  • Skeletons don't count as visible content, and useSkeletonSlot / PendingSkeletonContext skip a nested skeleton while an enclosing one is pending. The inner block therefore stays hidden on a full-app run.
  • Previous content stays mounted under the overlay, so on a fragment rerun the inner block needs no height when it is the body's first element.
  • The claim that "the templates need no changes" holds. The dashboard-metrics and dashboard-compute chart cards already draw their controls inside the fragment and pass height=CHART_HEIGHT to the inner skeleton.

The reviewers' findings were only small clarity points, and they are covered in the inline comments. The most practical one is that the new snippet calls load_live_orders() without the def ...: ... stub that the section gives load_revenue and load_orders, so a copied example fails with a NameError.

Performance

No runtime impact, because only Markdown changes. The recommended pattern adds one nested loading block per fragment, which is negligible. The frontend already handles nested loading blocks, and the half-second grace period before a skeleton shows is unchanged.

Test Coverage

No unit or E2E tests apply to a docs-only change. Existing skill checks (scripts/check_skill_file_size.py and lib/tests/streamlit/web/skills_test.py) cover file size and integrity. The PR body describes a manual Playwright check of the snippet against develop that covers three cases:

  • the first load
  • run_every overlay refreshes without a resize
  • the short default-height skeleton that appears when controls are drawn before a height-less inner block

The reviewers agreed this is the right check for this change. Existing tests such as test_run_every_parallel_fragment_reruns_sequentially already cover the combination of parallel=True and run_every.

Backwards Compatibility

No impact. Only bundled Markdown guidance changes. Agents may start adding a second with st.skeleton() inside fragments that rerun on their own. That addition uses the current API and is harmless.

Security & Risk

No security-sensitive areas are touched: there are no new dependencies, HTML, execution paths, or network calls. The only risk is that an agent misreads the height rule, and the inline suggestions on dashboards.md lines 206 and 208 address that.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/.agents/skills/developing-with-streamlit/references/dashboards.md: Markdown guidance and an example snippet only.
    • lib/streamlit/.agents/skills/developing-with-streamlit/references/layouts.md, references/performance.md, assets/templates/apps/README.md: one- or two-sentence doc edits.
  • Suggested external_test focus areas: None. Routing, auth, websocket, embedding, asset serving, storage, cross-origin behavior, and security headers are all unchanged.
  • Confidence: High (all four reviewers agree)
  • Assumptions and gaps: None. The diff contains no executable code.

Accessibility

Not applicable, because no frontend code changes. The new st.bar_chart example includes an alt description (alt="Orders per minute"), and existing skeletons stay decorative (aria-hidden) unless spinner text labels them.

Readability

The line-specific wording findings for dashboards.md, layouts.md, performance.md, and the templates README.md are in the inline comments. Three reviewers made overlapping points about the height rule in dashboards.md. The Gemini review found no readability issues.

PR title: [docs] Document skeletons for a fragment's own reruns stands on its own, follows the [type] Description format, and fits the length limit. No change needed.

PR description: It leads with the change and the reason. There are two optional points, raised by several reviewers:

  • "This is option A of change 1 in the layout-first loading spec" is internal shorthand that only makes sense next to a spec that isn't on develop. Suggested rewrite: "The embedded developing-with-streamlit skill now documents a second st.skeleton for a fragment's own reruns. This adds no API and uses only the blocks that exist today, as proposed in the layout-first loading spec."
  • "The templates need no changes" can sound contradictory, since assets/templates/apps/README.md is changed. Suggested rewrite: "The runnable app templates need no changes: the dashboard-metrics and dashboard-compute chart cards already use the inner block with a height."

Recommendations

  1. Add a def load_live_orders(): ... stub to the new dashboards.md example so it runs when copied.
  2. Optionally, tighten the dashboards.md height rule so that "no height" clearly applies only when the inner block is the fragment body's first element. This also removes the tension with the "Give each skeleton the content's height" bullet.
  3. Optionally, apply the remaining wording suggestions in the inline comments and the PR-description rewrites above.

Verdict

APPROVED: All four reviewers approved. The documentation accurately describes how the frontend already handles skeletons during fragment runs, adds no runtime or API risk, and leaves only optional wording and example polish.


This is an automated AI review consolidated by claude-opus-5-5-high from reviews by claude-opus-5-5-high, gemini-4-argon-medium, gpt-5.6-luna-xhigh, and grok-4.7-medium. Please verify the feedback and use your judgment.

This review also includes 7 inline comment(s) on specific code lines.

@github-actions github-actions Bot removed the ai-final-review If applied to PR or issue will run AI review workflow with the latest generation of AI models. label Nov 10, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This documentation-only PR updates the bundled developing-with-streamlit skill to teach the two-block st.skeleton() pattern for slow fragment-only reruns. references/dashboards.md adds a live_orders example. In it, an outer with st.skeleton(height=...) around the fragment call sizes the first load, and an inner with st.skeleton() inside the fragment covers run_every refreshes and widget reruns inside the fragment. references/layouts.md, references/performance.md, and assets/templates/apps/README.md each gain a short pointer to the same guidance. The app templates themselves are unchanged, because their chart cards already use a heighted inner skeleton when controls are drawn first.

Review status: 2 of 4 expected reviews completed (gpt-5.6-terra-xhigh and grok-4.7-xhigh). Both approved. gemini-4-argon-medium and claude-opus-5-5-high failed to complete review.

Both reviewers independently checked the guidance against the runtime on develop and found it accurate:

  • A fragment-only rerun does not re-enter a skeleton wrapped around the call.
  • A nested skeleton does not end the outer block.
  • A skeleton without a height overlays the previously mounted content at its current size.
  • Controls drawn before the inner block end the outer skeleton, so the inner block then needs an explicit height. This matches dashboard-metrics and dashboard-compute.

Product Alignment

This PR does not change product behavior. It touches no public API, configuration option, CLI surface, rendered UI, default, or error message. The embedded skill is user-facing guidance, but it documents how existing st.fragment and st.skeleton features compose rather than adding a capability.

Both reviewers noted that the layout-first loading spec linked in the PR body (commit 562dae0, open as #17756) is not merged into develop, so it does not count as approved product direction. Both agreed this does not block the PR, since there is no new surface to spec. The documented pattern also fits the API design principles: it starts minimal and adds no parameter ($4), composes existing commands ($19), and preserves the user's context during slow reruns ($51).

Code Quality

The edits stay inside the existing layout-first sections and the cross-references next to them. They add no new reference page or SKILL.md route, which follows the embedded-skill rule to extend an existing section for behavior agents are likely to miss. All edited files stay under the 500-line skill limit, though references/performance.md is now at 499 lines, so the next addition there will need a trim or a split. The example correctly uses parallel=True with run_every and sets the chart's alt text.

The one substantive finding is a consistency gap between the new "inner block needs no height" sentence and the existing "To keep the layout stable" checklist in dashboards.md. It is covered inline.

Performance

No runtime or frontend code changes, so backend and frontend hot paths are untouched. Apps that adopt the pattern add one skeleton block inside a fragment, which goes through the existing skeleton path (previous content stays mounted, with a 500 ms grace period before the overlay). Both reviewers agreed there is no performance concern.

Test Coverage

No tests were added or changed. Both reviewers agreed this is appropriate for a documentation-only change. The underlying behavior (skeletons preserving prior content, skeleton slots for parallel fragments, sequential fragment reruns) is already covered by existing tests on develop. The PR description also records a manual Playwright check of the documented snippet, covering first load, a run_every refresh, and controls drawn before the inner skeleton.

Backwards Compatibility

There are no breaking changes. The text is additive, existing apps are unaffected, and the skill does not promote any deprecated API.

Security & Risk

No security-sensitive surface is touched. The diff is Markdown in the bundled agent skill. The only risk is inaccurate guidance, and both reviewers verified the text against current behavior.

External test recommendation

  • Recommend external_test: No (both reviewers agreed)
  • Triggered categories: None
  • Evidence:
    • references/dashboards.md: skill prose and an example only, with no server, client, or protocol change.
    • references/layouts.md, references/performance.md, assets/templates/apps/README.md: one-sentence cross-references with no routing, embedding, asset, storage, or security-header impact.
  • Suggested external_test focus areas: None.
  • Confidence: High
  • Assumptions and gaps: This assumes the four-file diff is the complete change.

Accessibility

No frontend changes. The new example sets alt text on its chart, and st.skeleton stays out of the accessibility tree unless spinner text labels it.

Readability

The GPT reviewer found no readability issues. The Grok reviewer proposed the optional wording improvements below. None of them block merge.

lib/streamlit/.agents/skills/developing-with-streamlit/references/dashboards.md

  • Line 191: The rule comes after the mechanism, and "fades as stale" does not say that Streamlit marks the old content stale. Suggested rewrite that leads with the rule:

    A skeleton around the call covers full-app runs only. A fragment-only rerun, such as a run_every refresh or a widget interaction inside the fragment, runs the fragment body and skips that block. Streamlit then marks the old content stale until the rerun finishes. When those reruns can be slow, wrap the body in a second with st.skeleton():

  • Line 208: One paragraph covers three outcomes: where the controls go, why the outer skeleton ends, and why the inner block needs a height. A short lead sentence followed by a two-item list would scan faster.

lib/streamlit/.agents/skills/developing-with-streamlit/references/layouts.md

  • Line 362: The new rule is appended to an already long paragraph, and "doesn't re-enter a block" is harder to picture than "skips." Suggested standalone sentence:

    A fragment-only rerun skips a with st.skeleton() wrapped around the call. Put a second with st.skeleton() inside the fragment body to cover those reruns (see dashboards.md).

lib/streamlit/.agents/skills/developing-with-streamlit/assets/templates/apps/README.md

  • Lines 159–162: "its widgets" doesn't parallel "run_every refreshes," and "when nothing is drawn before it" doesn't make clear this is about the inner block. Suggested rewrite using the same terms as dashboards.md:

    The skeleton around the call covers only full-app runs. If the fragment's own reruns can be slow, such as a run_every refresh or a widget interaction inside the fragment, add a second with st.skeleton() inside the fragment around the slow part. Omit that block's height when it is the body's first element.

PR title and description

  • Title: Both reviewers found [docs] Document skeletons for a fragment's own reruns clear and correctly formatted.
  • Description: GPT found it clear. Grok noted that the opening relies on "option A of change 1" and a blob URL for commit 562dae0, which exists only on the unmerged spec branch. It suggested linking the spec PR (#17756) and leading with the change itself.

Recommendations

  1. Resolve the conflict between the "inner block needs no height" sentence and the "Give each skeleton the content's height" checklist bullet in dashboards.md, and state that a nested skeleton does not end the outer block (see inline comment).
  2. Optional: apply the readability rewrites above for dashboards.md, layouts.md, and the templates README.md.
  3. Optional (follow-up): references/charts.md still recommends a timer chart in @st.fragment(run_every=...) wrapped in a single st.skeleton(height=...). A one-clause pointer to the two-block pattern would reach agents that only open that page. Its existing link to dashboards.md already reaches the new section, so this can wait.

Verdict

APPROVED: Both completed reviews approve. The PR accurately documents an existing, composable loading pattern without changing Streamlit behavior or adding API surface, and the remaining notes are non-blocking wording and consistency improvements.


This is an automated AI review consolidated by claude-opus-5-5-high from reviews by gpt-5.6-terra-xhigh and grok-4.7-xhigh. gemini-4-argon-medium and claude-opus-5-5-high failed to complete review. Please verify the feedback and use your judgment.

This review also includes 2 inline comment(s) on specific code lines.

Stub load_live_orders in the dashboards.md example, say that the inner
skeleton doesn't end the outer one, scope the no-height rule to an inner
block that is the body's first element (also in the checklist bullet),
and name dashboard-compute next to dashboard-metrics. Split the
layouts.md pointer into its own paragraph with a section name, and use
the imperative in performance.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 10, 2026 11:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:docs PR contains documentation change impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants