A Jinja2 component library for creating reusable, production-ready server-rendered UI components in Python.

Install

mkdir -p .claude/skills/jx && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15423" && unzip -o skill.zip -d .claude/skills/jx && rm skill.zip

Installs to .claude/skills/jx

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Use this skill for anything Jx — the Python/Jinja2 component library. Covers BOTH (a) library mechanics and integration AND (b) authoring production-ready UI components. Trigger this skill on any mention of Jx, `.jx` files, "Jinja components" in a Python web app context, or requests to build/create UI components for such an app.
330 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Load .jx component files from folders
  • Render components into HTML strings
  • Collect CSS and JS assets from component trees
  • Define typed props with default values for components
  • Manage component attributes for root elements
  • Validate component files for errors

How it works

A Catalog loads .jx files from specified folders and renders them into an HTML string, automatically collecting and deduplicating CSS/JS assets from the imported component tree.

Inputs & outputs

You give it
catalog.render("page.jx", user=user, title="Home")
You get back
HTML string

When to use jx

  • Create reusable UI components
  • Build server-rendered views
  • Manage UI assets
  • Integrate components into Python apps

About this skill

Jx — Jinja2 component library

Jx is a Python package that lets you build server-rendered UIs from reusable component files (.jx). A Catalog loads components from one or more folders and renders them with explicit imports, typed props, an attrs pass-through, and a per-component CSS/JS asset system.

Mental model

Catalog("components/")  ──►  loads .jx files
       │
       ├── catalog.render("page.jx", **kwargs)  ──►  HTML string
       │       └── walks the imported component tree
       │           └── collects assets (CSS/JS) automatically
       │
       └── catalog.add_folder(path, prefix="ui")  ──►  more component sources

A component file has up to four parts (all optional except the template):

{#import "./icon.jx" as Icon #}     {# imports — PascalCase aliases #}
{#css card.css #}                    {# per-component assets #}
{#js card.js #}
{#def title, subtitle="" #}          {# typed props with defaults #}

<div {{ attrs.render(class="card") }}>
  <Icon name="star" />
  <h3>{{ title }}</h3>
  {{ content }}                      {# main slot #}
</div>

Quick reference

Install: uv add jx (or pip install jx).

Create a catalog:

from jx import Catalog
catalog = Catalog("components/", auto_reload=app.debug)
html = catalog.render("page.jx", user=user, title="Home")

Component file:

  • {#def name, count=0, items: list = [] #} — required props have no default; types are runtime-checked for primitives.
  • {#import "path.jx" as Name #} — alias must be PascalCase. Three flavors: absolute ("button.jx"), relative ("./sibling.jx"), prefixed ("@ui/button.jx").
  • {#css ... #} / {#js ... #} — comma-separated list of files (relative URLs, absolute paths, or full URLs).

Using a component: HTML-tag syntax, PascalCase, props with key="literal" or key={{ expr }}. Booleans support shorthand: <Input required /> is required={{ true }}.

attrs collects every attribute not declared in {#def}. Render onto the root element with {{ attrs.render(class="default") }}class merges, other attrs override.

Slots for multiple content areas:

{% slot header %}default{% endslot %}   {# in component #}
{% fill header %}custom{% endfill %}    {# at call site #}

Assets are collected from the whole tree, deduplicated, in import order. Render with {{ assets.render() }} or split via assets.render_css() / assets.render_js(module=True, defer=True).

Validate: jx check myapp.setup:catalog (or path/to/file.py:catalog). Catches missing imports, used-but-not-imported tags, typos with "did you mean".

When to load which reference

The compact summary above is enough for many tasks. Pull a reference file when the user's question is squarely in that area — don't preload them.

If the user is asking about…Read
Building a UI component (button, card, modal, dropdown, form, table, layout, navigation, accordion, toast, etc.) — design choices, accessibility, native-HTML-first, color mode, when to use JS, the authoring checklistreference/authoring.md (always pair with reference/patterns.md if the user asks for a specific category we already have a recipe for)
Copy-paste recipes for buttons, modals (<dialog>), dropdowns (Popover API), form inputs, data tables, sidebar layoutsreference/patterns.md
Catalog options (jinja_env, extensions, filters, globals, asset_resolver), add_folder prefixes, render vs render_string, introspection (get_signature, list_components), collect_assetsreference/catalog.md
Component anatomy in depth, prop types and defaults, slot vs content vs prop tradeoffs, naming conventions, the dash-to-underscore rulereference/components.md
attrs.render / set / setdefault / add_class / prepend_class / remove_class, class merging rules, forwarding attrs to a child component, conditional attributesreference/attrs.md
Declaring CSS/JS, asset URL strategies (relative, absolute, build-tool), collection order, deduplication, asset_resolver for installable packagesreference/assets.md
Wiring Jx into Flask / Django / FastAPI / htmx, sharing a Jinja env, passing request, CSRF, URL helpers, partial responses for htmxreference/frameworks.md
Running jx check, JSON output, programmatic check_all, the VSCode extension (Go-to-Definition, diagnostics, snippets)reference/tools.md

Idioms worth remembering

  • Component classes first. When you call attrs.render(class="Card"), the component's own classes are emitted before anything the caller passed. Callers extend; they don't replace.
  • attrs is for HTML elements, not component tags. <Button attrs={{ attrs }} /> is the way to forward a parent's attrs into a child component — <Button {{ attrs.render() }} /> does NOT work because component tags are preprocessed.
  • Underscores in attribute names become dashes at render time: data_user_iddata-user-id, aria_labelaria-label, hx_gethx-get. Useful for data-*, aria-*, htmx, Alpine, etc.
  • Boolean attrs: True renders the attribute name alone (disabled); False removes it entirely.
  • Auto-reload off in production. Catalog(auto_reload=False) skips the file-mtime check on every render.
  • _get_random_id(prefix) is a built-in global — useful for components that need stable-but-unique IDs (popovers, label-for, etc.) without forcing the caller to pass one.
  • Components are fragments. Don't emit <!DOCTYPE> / <html> / <body> from a leaf component — that belongs to a single layout.jx.

When not to use it

  • When the user's question is about authoring checklist details
  • When the user's question is about copy-paste recipes for UI elements
  • When the user's question is about advanced catalog options

Limitations

  • Prop types are runtime-checked only for primitives
  • Component tags are preprocessed, affecting attribute forwarding
  • Component files are fragments and should not emit full HTML document structures

How it compares

This workflow renders server-side UI components with explicit imports and typed props, unlike manual HTML templating.

Compared to similar skills

jx side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
jx (this skill)03moNo flagsIntermediate
add-new-setting-field17moNo flagsIntermediate
python-pro234moNo flagsAdvanced
debugging-streamlit75moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

add-new-setting-field

tsukumijima

【設定追加時は必ず参照】KonomiTV に新しい設定 (v-switch/v-select など) を追加する際の必須手順。SettingsStore.ts / Settings.ts / config.py / Settings/*.vue への追加が必要

12

python-pro

sickn33

Master Python 3.12+ with modern features, async programming, performance optimization, and production-ready practices. Expert in the latest Python ecosystem including uv, ruff, pydantic, and FastAPI. Use PROACTIVELY for Python development, optimization, or advanced Python patterns.

2358

debugging-streamlit

streamlit

Debug Streamlit frontend and backend changes using make debug with hot-reload. Use when testing code changes, investigating bugs, checking UI behavior, or needing screenshots of the running app.

733

telegram-dev

2025Emma

Telegram 生态开发全栈指南 - 涵盖 Bot API、Mini Apps (Web Apps)、MTProto 客户端开发。包括消息处理、支付、内联模式、Webhook、认证、存储、传感器 API 等完整开发资源。

232

podcast-generation

microsoft

Generate AI-powered podcast-style audio narratives using Azure OpenAI's GPT Realtime Mini model via WebSocket. Use when building text-to-speech features, audio narrative generation, podcast creation from content, or integrating with Azure OpenAI Realtime API for real audio output. Covers full-stack implementation from React frontend to Python FastAPI backend with WebSocket streaming.

13

pyzig

atopile

How the Zig↔Python binding layer works (pyzig), including build-on-import, wrapper generation patterns, ownership rules, and where to add new exported APIs.

12

Search skills

Search the agent skills registry