Agent skill

Building Streamlit Custom Components V2

by iusztinpaul in iusztinpaul/designing-real-world-ai-agents-workshop

Builds bidirectional Streamlit Custom Components v2 (CCv2) using st.components.v2.component.

Apache-2.0Auto-check passedFrontend & Design

Install Building Streamlit Custom Components V2

skills CLI
$ npx skills add iusztinpaul/designing-real-world-ai-agents-workshop --skill building-streamlit-custom-components-v2 -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install iusztinpaul/designing-real-world-ai-agents-workshop building-streamlit-custom-components-v2 --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/iusztinpaul/designing-real-world-ai-agents-workshop.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2 .claude/skills/building-streamlit-custom-components-v2 && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
building-streamlit-custom-components-v2
GitHub stars
512
Token cost
~2.8k tokens
SKILL.md length
1,027 words
Files
5 (incl. references)
Skills in repo
23
Repo updated
First seen
Licence
Apache-2.0

At a glance

Builds bidirectional Streamlit Custom Components v2 (CCv2) using st.components.v2.component.

  • Works in 4 steps: Python registers a component with… → The mount callable mounts the component… → The frontend default export runs with ({… → …
  • Authoring inline HTML/CSS/JS components
  • SKILL.md covers CRITICAL: CCv2 only — NEVER…, When to use, Read next (pick the minimum… and Quick decision: inline vs…, plus 8 more sections
  • Calls streamlit and python

What it does

Building Streamlit Custom Components V2 is an agent skill from iusztinpaul/designing-real-world-ai-agents-workshop. Builds bidirectional Streamlit Custom Components v2 (CCv2) using st.components.v2.component. Use when authoring inline HTML/CSS/JS components or packaged components (manifest assetdir, js/css globs), wiring state/trigger callbacks, theming via --st- CSS variables, or bundling with Vite / component-template v2.

Its SKILL.md is about 2.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 5 other files, including reference files (for example `references/packaged-components.md`, `references/state-sync.md` and `references/theme-css-variables.md`).

It sits in Frontend & Design, covering Theming and dark mode and Design tokens. It works with Streamlit, Vite and Python. The repository describes itself as: Hands-on workshop: Build a multi-agent AI system from scratch — Deep Research Agent + Writing Workflow served as MCP servers. Includes code, slides, and video. The licence is Apache-2.0.

When your agent uses it

  • Authoring inline HTML/CSS/JS components
  • Packaged components (manifest assetdir
  • Wiring state/trigger callbacks
  • Theming via --st- CSS variables

Example prompts

  • “Use the building-streamlit-custom-components-v2 skill to build bidirectional Streamlit Custom Components v2 (CCv2) using st.components.v2.component”
  • “/building-streamlit-custom-components-v2”

Requirements

  • Python 3

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Python registers a component with st.components.v2.component(...) and gets back a mount callable.
  2. The mount callable mounts the component in the app with data=..., layout (width, height), and optional on__change callbacks.
  3. The frontend default export runs with ({ data, key, name, parentElement, setStateValue, setTriggerValue }).
  4. The component returns a result object whose attributes correspond to state keys and trigger keys.

What it can do on your machine

Read from SKILL.md and the folder at commit ea4f6e9. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • streamlit
    • python

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • docs.streamlit.io

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Building Streamlit Custom Components V2 loads about 2.8k tokens when it runs, and up to ~9.7k if it reads all its reference files. Until then it costs about 90 tokens; SKILL.md has 1,027 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~90
When it runs · the whole SKILL.md, loaded when a task matches
~2.8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~9.7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from iusztinpaul/designing-real-world-ai-agents-workshop at commit ea4f6e9, republished under its Apache-2.0 licence (© iusztinpaul). 1,027 words, ~2,847 tokens.

Download SKILL.mdSave it as .claude/skills/building-streamlit-custom-components-v2/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.
name
building-streamlit-custom-components-v2
description
Builds bidirectional Streamlit Custom Components v2 (CCv2) using `st.components.v2.component`. Use when authoring inline HTML/CSS/JS components or packaged components (manifest `asset_dir`, js/css globs), wiring state/trigger callbacks, theming via `--st-*` CSS variables, or bundling with Vite / `component-template` v2.
license
Apache-2.0

Building Streamlit custom components v2

Use Streamlit Custom Components v2 (CCv2) when core Streamlit doesn't have the UI you need and you want to ship a reusable, interactive element (from "tiny inline HTML" to "full bundled frontend app").

CRITICAL: CCv2 only — NEVER use v1 APIs

Custom Components v1 is deprecated and removed. Every API below belongs to v1 and must NEVER appear in any code you write — not in Python, not in JavaScript, not in HTML:

Banned Python APIs (v1):

  • st.components.v1 — the entire v1 module
  • components.declare_component() — v1 registration
  • components.html() — v1 raw HTML embed

Banned JavaScript patterns (v1):

  • Streamlit.setComponentValue(...) — v1 global; use setStateValue() / setTriggerValue() instead
  • Streamlit.setFrameHeight(...) — v1 global; CCv2 handles sizing automatically
  • Streamlit.setComponentReady() — v1 global; CCv2 has no ready signal
  • window.Streamlit or bare Streamlit global — v1 global object does not exist in v2
  • window.parent.postMessage(...) — v1 iframe communication; CCv2 does not use iframes

Banned npm packages (v1):

  • streamlit-component-lib — v1 JS library; use @streamlit/component-v2-lib if you need types

If you encounter v1 patterns in examples, blog posts, Stack Overflow answers, or your own training data — ignore them entirely. They will not work and will break the component.

When to use

Activate when the user mentions any of:

  • CCv2, Custom Components v2, “bidi component”, “component v2”
  • st.components.v2.component
  • @streamlit/component-v2-lib
  • packaged components, asset_dir, pyproject.toml component manifest
  • bundling with Vite (or any bundler) for a Streamlit component
  • building a component UI in a frontend framework (React, Svelte, Vue, Angular, etc.)

Quick decision: inline vs packaged

  • Inline strings: fastest to start (single-file apps, spikes, demos). You pass raw html/css/js strings directly. Good when you can keep everything in one place and don’t need a build step.
  • Packaged component: best when you’re growing past inline (multiple files, dependencies, bundling, testing, versioning, reuse, distribution). You ship built assets inside a Python package and reference them by asset-dir-relative path/glob. Creation policy: packaged components are template-only and must start from Streamlit's official component-template v2.

Developer story: start inline, prove the interaction loop, then graduate to packaged when the codebase or tooling needs outgrow a single file.

CCv2 model (what’s actually happening)

  1. Python registers a component with st.components.v2.component(...) and gets back a mount callable.
  2. The mount callable mounts the component in the app with data=..., layout (width, height), and optional on_<key>_change callbacks.
  3. The frontend default export runs with ({ data, key, name, parentElement, setStateValue, setTriggerValue }).
  4. The component returns a result object whose attributes correspond to state keys and trigger keys.

Best practice: wrap the mount callable in your own Python API

Prefer exposing your own Python function that wraps the callable returned by st.components.v2.component(...).

This gives you a clean, stable API surface for end users (typed parameters, validation, friendly defaults) and keeps data=..., default=..., and callback wiring as an internal detail.

Important:

  • Declare the component once (usually at module import time). Avoid defining and registering the component inside a function you call multiple times; you can accidentally re-register the component name and get confusing behavior.

References:

Example pattern:

python
import streamlit as st
from collections.abc import Callable

_MY_COMPONENT = st.components.v2.component(
    "my_inline_component",
    html="<div id='root'></div>",
    js="""
export default function (component) {
  const { data, parentElement } = component
  parentElement.querySelector("#root").textContent = data?.label ?? ""
}
""",
)


def my_component(
    label: str,
    *,
    key: str | None = None,
    on_value_change: Callable[[], None] | None = None,
    on_submitted_change: Callable[[], None] | None = None,
):
    # Callbacks are optional, but if you want result attributes to always exist,
    # provide (even empty) callbacks.
    if on_value_change is None:
        on_value_change = lambda: None
    if on_submitted_change is None:
        on_submitted_change = lambda: None

    return _MY_COMPONENT(
        data={"label": label},
        key=key,
        on_value_change=on_value_change,
        on_submitted_change=on_submitted_change,
    )

Inline quickstart (state + trigger)

Reminder: use ONLY v2 APIs. Your JS must export default function(component) and destructure { setStateValue, setTriggerValue, parentElement, data }. NEVER use Streamlit.setComponentValue(), window.Streamlit, or any v1 pattern.

This is the minimum "bidi loop":

  • JS → Python: emit updates via setStateValue(...) (persistent) and setTriggerValue(...) (event)
  • Python → JS: re-hydrate UI via data=... on every run
python
import streamlit as st

HTML = """<input id="txt" /><button id="btn" type="button">Submit</button>"""

JS = """\
export default function (component) {
  const { data, parentElement, setStateValue, setTriggerValue } = component

  const input = parentElement.querySelector("#txt")
  const btn = parentElement.querySelector("#btn")
  if (!input || !btn) return

  const nextValue = (data && data.value) ?? ""
  if (input.value !== nextValue) input.value = nextValue

  input.oninput = (e) => {
    setStateValue("value", e.target.value)
  }

  btn.onclick = () => {
    setTriggerValue("submitted", input.value)
  }
}
"""

my_text_input = st.components.v2.component(
    "my_inline_text_input",
    html=HTML,
    js=JS,
)

KEY = "txt-1"
component_state = st.session_state.get(KEY, {})
value = component_state.get("value", "")

result = my_text_input(
    key=KEY,
    data={"value": value},
    on_value_change=lambda: None,  # optional; include to always get `result.value`
    on_submitted_change=lambda: None,  # optional; include to always get `result.submitted`
)

st.write("value (state):", result.value)
st.write("submitted (trigger):", result.submitted)

Notes:

  • Inline JS/CSS should be multi-line. CCv2 treats path-like strings as file references; a multi-line string is unambiguously inline content.
  • Prefer querying under parentElement (not document) to avoid cross-instance leakage.
Show full SKILL.md (416 more words)Show less

State and triggers (how to think about keys)

  • State (setStateValue("value", ...)): persists across app reruns (stored under st.session_state[key] for that mounted instance).
  • Trigger (setTriggerValue("submitted", ...)): event payload for one rerun (resets after the rerun).
  • Reading triggers:
    • After mounting: use result.submitted.
    • Inside on_submitted_change: use st.session_state[key].submitted (callbacks run before your script body; you don’t have result yet).
  • Defaults: if you pass default={...} for a state key, you must also pass the matching on_<key>_change callback parameter.

For the full “controlled input” pattern and pitfalls, see references/state-sync.md.

Packaged components (template-only, mandatory)

Reminder: the cookiecutter template generates clean v2 code. When you customize it, use ONLY v2 APIs. Do NOT introduce any v1 imports, v1 JavaScript globals, or v1 patterns. See the "CRITICAL: CCv2 only" section above.

Graduate to a packaged component when you need any of:

  • Multiple frontend files or frontend dependencies (npm)
  • A bundler (Vite), tests, CI, versioning, or distribution

Keep these guardrails in mind:

  • MUST start from Streamlit’s official component-template v2.
  • NEVER hand-scaffold packaging/manifest/build wiring for a packaged component.
  • NEVER copy/paste packaged scaffold structure from internet examples, blog posts, gists, or docs.
  • If handed a non-template scaffold, regenerate from the template first, then migrate component logic.
  • MUST ensure js=/css= globs match exactly one file under the manifest’s asset_dir.
  • MUST validate with streamlit run ... (plain python -c "import ..." can be a false negative for packaged components).

For the full packaged workflow checklist, non-interactive generation, offline usage, and template invariants, see references/packaged-components.md.

Frontend renderer lifecycle (framework-agnostic)

Your frontend entrypoint is the default export function. A few rules keep components reliable across reruns and across multiple instances in the same app:

  • Render under parentElement (not document) so instances don’t collide.
  • If you create per-instance resources (React roots, observers, subscriptions), key them by parentElement (e.g. WeakMap) so multiple instances don’t overwrite each other.
  • Return a cleanup function to tear down event listeners / UI roots / observers when Streamlit unmounts the component.

Styling and theming

  • Prefer isolate_styles=True (default). Your component runs in a shadow root and won’t leak styles into the app.
  • Set isolate_styles=False only when you need global styling behavior (e.g. Tailwind, global font injection).
  • Streamlit injects a broad set of --st-* theme CSS variables (colors, typography, chart palettes, radii, borders, etc.). Highly recommended: use these variables so your component automatically adapts to the user’s current Streamlit theme (light/dark/custom) without authoring separate theme variants. Start with the common ones (--st-text-color, --st-primary-color, --st-secondary-background-color) and refer to the full list when you need it:

Troubleshooting and gotchas

Start here when something “should work” but doesn’t:

© iusztinpaul, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 4 other files (references) in .agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2 of iusztinpaul/designing-real-world-ai-agents-workshop.

  • SKILL.md
  • references/packaged-components.md
  • references/state-sync.md
  • references/theme-css-variables.md
  • references/troubleshooting.md

Open the folder on GitHubat commit ea4f6e9

Compare with similar skills

Building Streamlit Custom Components V2 next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Building Streamlit Custom Components V2 compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Building Streamlit Custom Components V2 this skilliusztinpaul/designing-real-world-ai-agents-workshop512—~2.8kAutomated safety check: PassApache-2.0
Tailwind Theme Builderjezweb/claude-skills1.1k1 repos~3.2kAutomated safety check: PassMIT
Tailwind V4 Shadcnever-works/ever-works1622 repos~3.8kAutomated safety check: PassMIT
Shadcn Tailwind UILiarMTTT/TavernWeave154—~1.7kAutomated safety check: PassCustom licence
Tailwind V4 Shadcnsecondsky/claude-skills227—~4kAutomated safety check: PassMIT
TailwindcssMadAppGang/claude-code285—~3.2kAutomated safety check: PassMIT

Similar skills

  • Tailwind Theme Builder

    jezweb/claude-skills

    Set up Tailwind v4 + shadcn/ui themed UI with dark mode. An agent skill from jezweb/claude-skills.

    1.1k GitHub starsUsed in 1 repo~3.2k tokens
    Frontend & DesignAuto-check passed
  • Tailwind V4 Shadcn

    ever-works/ever-works

    Production-tested setup for Tailwind CSS v4 with shadcn/ui, Vite, and React.

    162 GitHub starsUsed in 2 repos~3.8k tokens
    Frontend & DesignAuto-check passed
  • Shadcn Tailwind UI

    LiarMTTT/TavernWeave

    Build, restyle, or review accessible React interfaces that use shadcn/ui, Radix UI primitives, and Tailwind CSS.

    154 GitHub stars~1.7k tokensUpdated 6 days ago
    Frontend & DesignAuto-check passed
  • Tailwind V4 Shadcn

    secondsky/claude-skills

    | Production-tested setup for Tailwind CSS v4 with shadcn/ui, Vite, and React.

    227 GitHub stars~4k tokensUpdated 12 days ago
    Frontend & DesignAuto-check passed
  • Tailwindcss

    MadAppGang/claude-code

    TailwindCSS v4 patterns with CSS-first configuration using @theme, @source, and modern CSS features.

    285 GitHub stars~3.2k tokensUpdated 6 mo ago
    Frontend & DesignAuto-check passed
  • Chakra UI v3 Builder

    chakra-ui/chakra-ui

    Builds responsive, accessible Chakra UI v3 components and layouts, sets up Chakra in new or existing projects, and designs themes with tokens, semantic tokens and recipes.

    41k GitHub stars~3.1k tokensUpdated 4 days ago
    Frontend & DesignAuto-check passed

More from iusztinpaul/designing-real-world-ai-agents-workshop

All 23 skills in this repo
  • Building Streamlit Chat UI

    iusztinpaul/designing-real-world-ai-agents-workshop

    Building chat interfaces in Streamlit. An agent skill from iusztinpaul/designing-real-world-ai-agents-workshop.

    512 GitHub stars~1.4k tokensUpdated 4 mo ago
    Auto-check passed
  • Building Streamlit Dashboards

    iusztinpaul/designing-real-world-ai-agents-workshop

    Building dashboards in Streamlit. An agent skill from iusztinpaul/designing-real-world-ai-agents-workshop.

    512 GitHub stars~1.1k tokensUpdated 4 mo ago
    Auto-check passed
  • Building Streamlit Multipage Apps

    iusztinpaul/designing-real-world-ai-agents-workshop

    Building multi-page Streamlit apps. An agent skill from iusztinpaul/designing-real-world-ai-agents-workshop.

    512 GitHub stars~1.6k tokensUpdated 4 mo ago
    Auto-check passed
  • Choosing Streamlit Selection Widgets

    iusztinpaul/designing-real-world-ai-agents-workshop

    Choosing the right Streamlit selection widget. An agent skill from iusztinpaul/designing-real-world-ai-agents-workshop.

    512 GitHub stars~1.1k tokensUpdated 4 mo ago
    Auto-check passed
  • Connecting Streamlit To Snowflake

    iusztinpaul/designing-real-world-ai-agents-workshop

    Connecting Streamlit apps to Snowflake. An agent skill from iusztinpaul/designing-real-world-ai-agents-workshop.

    512 GitHub stars~1.3k tokensUpdated 4 mo ago
    Auto-check passed
  • Creating Streamlit Themes

    iusztinpaul/designing-real-world-ai-agents-workshop

    Creating and customizing Streamlit themes. An agent skill from iusztinpaul/designing-real-world-ai-agents-workshop.

    512 GitHub stars~3.7k tokensUpdated 4 mo ago
    Auto-check passed

Questions about Building Streamlit Custom Components V2

What does Building Streamlit Custom Components V2 do?

Builds bidirectional Streamlit Custom Components v2 (CCv2) using st.components.v2.component. Building Streamlit Custom Components V2 is an agent skill from iusztinpaul/designing-real-world-ai-agents-workshop.component.

When should I use Building Streamlit Custom Components V2?

Building Streamlit Custom Components V2 fits situations like: authoring inline HTML/CSS/JS components; packaged components (manifest assetdir; wiring state/trigger callbacks; theming via --st- CSS variables.

How do I install Building Streamlit Custom Components V2 in Claude Code?

Run `npx skills add iusztinpaul/designing-real-world-ai-agents-workshop --skill building-streamlit-custom-components-v2 -a claude-code`. Or copy the skill folder (.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2 in iusztinpaul/designing-real-world-ai-agents-workshop) into .claude/skills/building-streamlit-custom-components-v2 in your project. Claude Code loads it when a task matches its description.

How do I install Building Streamlit Custom Components V2 in Codex?

Run `npx skills add iusztinpaul/designing-real-world-ai-agents-workshop --skill building-streamlit-custom-components-v2 -a codex`. Or copy the skill folder (.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2 in iusztinpaul/designing-real-world-ai-agents-workshop) into .agents/skills/building-streamlit-custom-components-v2 in your project. Codex loads it when a task matches its description.

Can I use Building Streamlit Custom Components V2 in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add iusztinpaul/designing-real-world-ai-agents-workshop --skill building-streamlit-custom-components-v2 -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/building-streamlit-custom-components-v2, .gemini/skills/building-streamlit-custom-components-v2, .github/skills/building-streamlit-custom-components-v2 and .opencode/skills/building-streamlit-custom-components-v2 in your project.

What does Building Streamlit Custom Components V2 need to run?

Going by SKILL.md and its folder, Building Streamlit Custom Components V2 needs the command-line tools its instructions call (streamlit and python). Our summary lists: Python 3.

Does Building Streamlit Custom Components V2 access the network?

SKILL.md names 1 domain. As links in the text: docs.streamlit.io. This is read from the text; nothing was executed.

Is Building Streamlit Custom Components V2 safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Building Streamlit Custom Components V2 use?

Building Streamlit Custom Components V2 is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Building Streamlit Custom Components V2 use?

About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 6.9k tokens, read only when the agent opens those files.

What are the alternatives to Building Streamlit Custom Components V2?

Skills that share tags, products or a category with Building Streamlit Custom Components V2: Tailwind Theme Builder (jezweb/claude-skills, 1.1k stars), Tailwind V4 Shadcn (ever-works/ever-works, 162 stars), Shadcn Tailwind UI (LiarMTTT/TavernWeave, 154 stars) and Tailwind V4 Shadcn (secondsky/claude-skills, 227 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Building Streamlit Custom Components V2?

iusztinpaul (a GitHub user) maintains it in iusztinpaul/designing-real-world-ai-agents-workshop, which has 512 GitHub stars. The repository holds 23 skills in this directory. The repository was last updated on June 3, 2026.

Source: iusztinpaul/designing-real-world-ai-agents-workshop on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.