
Rails Application Ui Blocks
- 200 installs
- 191 repo stars
- Updated July 24, 2026
- pproenca/dot-skills
rails-application-ui-blocks: A skill for development. This provides functionality for development workflows.
Key points
- rails-application-ui-blocks
Rails Application Ui Blocks by the numbers
- 200 all-time installs (skills.sh)
- +6 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,988 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pproenca/dot-skills --skill rails-application-ui-blocksAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 200 |
|---|---|
| repo stars | ★ 191 |
| Last updated | July 24, 2026 |
| Repository | pproenca/dot-skills ↗ |
How do I use rails-application-ui-blocks for development tasks?
Use rails-application-ui-blocks for development tasks
Who is it for?
Best when you're working on backend & apis and need structured help with rails-application-ui-blocks.
Skip if: Teams with no backend & apis needs, or anyone wanting a generic chat assistant without this specific workflow.
When should I use this skill?
When you need to use rails-application-ui-blocks for development tasks, or when rails-application-ui-blocks: a skill for development. this provides functionality for development workflows.
What you get
Structured output aligned to rails-application-ui-blocks: rails-application-ui-blocks.
Files
Rails Application UI Blocks
Use this skill to choose, adapt, and integrate premium UI blocks from templates/application-ui into Rails views.
Workflow
1. Determine mode:
- new-page for brand new features/pages
- refactor-page for existing views/partials
2. Identify constraints first:
- Required interactions (Turbo Frames/Streams, Stimulus targets/actions, form semantics)
- Accessibility constraints (labels, keyboard flow, ARIA)
- Existing component boundaries (partials, helpers, shared layouts)
3. Pick candidate blocks from catalog:
- Read
references/selection-playbook.md - Query
references/template-catalog.json
4. Integrate minimally:
- Keep existing routes/controllers/domain logic unchanged
- Replace markup in thin steps (shell first, then sections, then micro-components)
5. Verify:
- Ensure no loss of behavior, accessibility, or test coverage
- Keep existing design tokens and class conventions where required by project standards
Selection Order
For new-page: 1. Start with ui.page-examples.* to anchor page structure. 2. Choose shell from ui.application-shells.*. 3. Add page/section headings from ui.headings.*. 4. Add core body blocks (ui.forms.*, ui.lists.*, ui.data-display.*, ui.feedback.*). 5. Finish with navigation and overlay details (ui.navigation.*, ui.overlays.*).
For refactor-page: 1. Preserve current information architecture and interaction contracts. 2. Map each existing UI region to one candidate catalog block. 3. Replace one region at a time and run relevant tests. 4. Extract repeated markup into partials only after reuse is proven.
Guardrails
- Do not change controllers/models/policies unless explicitly requested.
- Do not remove
data-controller,data-action,data-turbo-*,aria-*, or form field names without replacement. - Prefer adapting blocks to project styles over introducing conflicting visual systems.
- Avoid block insertion that duplicates existing design-system components when native components already solve the same need.
Output Expectations
When completing a task with this skill, include:
- Selected catalog IDs (for traceability)
- Source template paths used
- Any behavior/accessibility deltas introduced
- What was intentionally not replaced and why
Resources
references/selection-playbook.md- Decision rules for what template families to check first, and when not to use them.
references/template-catalog.json- Canonical block IDs with aliases and source paths.
scripts/build_template_catalog.py- Regenerates the catalog after template updates.
Maintenance
Regenerate the catalog when files under templates/application-ui change:
python3 .agents/skills/rails-application-ui-blocks/scripts/build_template_catalog.py \
--root .interface:
display_name: "Rails Application UI Blocks"
short_description: "Compose and refactor Rails UI using premium application-ui blocks"
default_prompt: "Select and adapt premium blocks from templates/application-ui for this Rails UI task."
{
"version": "1.0.0",
"organization": "Community",
"technology": "Ruby on Rails + Tailwind CSS",
"date": "February 2026",
"abstract": "Compose and refactor Rails backend UI using premium blocks from templates/application-ui. Provides a canonical catalog with normalized IDs (ui.<domain>.<collection>.<variant>), a selection playbook for new-page and refactor workflows, and a catalog build script so block discovery stays current while preserving accessibility and Turbo/Stimulus behavior.",
"references": [
"https://tailwindcss.com/plus/ui-blocks/application-ui",
"https://tailwindcss.com/docs",
"https://guides.rubyonrails.org/layouts_and_rendering.html",
"https://turbo.hotwired.dev/handbook/introduction",
"https://stimulus.hotwired.dev/"
]
}
Selection Playbook
Use this playbook to choose premium blocks consistently for Rails backend UI work.
1. Choose the Path
new-page: Build a new feature screen.refactor-page: Rework an existing page/partial with premium blocks.
2. New Page Decision Order
1. Start with ui.page-examples.* to set structure and pacing. 2. Select an application shell from ui.application-shells.*. 3. Add page and section headers from ui.headings.*. 4. Fill primary content with:
ui.forms.*for input-heavy flowsui.lists.*for repeated recordsui.data-display.*for read-heavy metrics/details
5. Add movement and overlays:
ui.navigation.*for movement/contextui.overlays.*for temporary focus interactions
6. Add feedback states from ui.feedback.*.
3. Refactor Decision Order
1. Preserve existing routes, params, DOM hooks, and server-rendering flow. 2. Partition the page into regions:
- shell
- header
- primary content
- secondary content
- actions/overlays
3. Map each region to candidate IDs from template-catalog.json. 4. Replace one region per change to reduce regression risk. 5. Run tests and verify accessibility after each region replacement.
4. When to Avoid Premium Blocks
- Avoid blocks that require behavior your page does not have (extra tabs, fake KPIs, placeholder controls).
- Avoid full-shell replacements when only one component is problematic.
- Avoid changing form names, IDs, or Turbo/Stimulus hooks just to match template markup.
- Avoid visual drift that conflicts with the app's established design tokens/components.
5. Catalog Query Patterns
- Search by domain/collection:
rg -n '"id": "ui.forms\\.' .agents/skills/rails-application-ui-blocks/references/template-catalog.json- Search by intent keyword:
rg -n 'breadcrumb|empty state|command palette|sidebar' .agents/skills/rails-application-ui-blocks/references/template-catalog.json- Inspect a specific candidate's source path:
rg -n '"id": "ui.navigation.navbars.with-search"' .agents/skills/rails-application-ui-blocks/references/template-catalog.json6. Integration Rules
- Keep semantics first: headings, form labels, table relationships, button purpose.
- Keep behavior first: existing Turbo frames/streams and Stimulus contracts remain stable.
- Prefer partial extraction only after repeated use is evident.
- Document selected catalog IDs in implementation notes or PR descriptions.
#!/usr/bin/env python3
"""Build a canonical catalog for premium Rails UI blocks."""
from __future__ import annotations
import argparse
import json
import re
from collections import defaultdict
from datetime import datetime, timezone
from pathlib import Path
STOPWORDS = {"and", "with", "without", "in", "on", "for", "to", "of", "by", "a", "an", "the"}
DOMAIN_RULES = {
"application-shells": (
"Use for top-level page layout decisions such as sidebar, stacked, or multi-column shells.",
"Avoid for isolated components; prefer focused block families when only a subsection changes.",
),
"data-display": (
"Use for read-only metrics, calendars, and structured key-value content.",
"Avoid when the primary goal is data entry or complex inline editing.",
),
"elements": (
"Use for micro-components like buttons, badges, avatars, and dropdown controls.",
"Avoid as full-page scaffolding; pair with layout or shell blocks first.",
),
"feedback": (
"Use for alerts and empty states to communicate status, warnings, or no-data moments.",
"Avoid as a substitute for core content regions or navigation.",
),
"forms": (
"Use for form controls, form layout patterns, and authentication-oriented form composition.",
"Avoid when interaction is read-only; use data-display or lists instead.",
),
"headings": (
"Use for page, section, and card heading patterns with actions and metadata.",
"Avoid when no heading structure is needed or content is purely decorative.",
),
"layout": (
"Use for structural wrappers (cards, containers, dividers, list containers, media objects).",
"Avoid when semantic content blocks are needed first; pick lists/forms/data-display before wrappers.",
),
"lists": (
"Use for repeated dataset rendering such as tables, feeds, stacked lists, and grid lists.",
"Avoid when one-off content is better represented as cards or form sections.",
),
"navigation": (
"Use for user movement and context controls (tabs, navbars, breadcrumbs, pagination).",
"Avoid for primary content display or domain-specific business widgets.",
),
"overlays": (
"Use for modals, drawers, and transient notifications that sit above base content.",
"Avoid for persistent layout sections; overlays should be temporary and dismissible.",
),
"page-examples": (
"Use as end-to-end reference blueprints when starting a new page or major refactor.",
"Avoid direct copy-paste without adapting routes, semantics, and existing component boundaries.",
),
}
COLLECTION_ALIASES = {
"sign-in-and-registration": ["auth forms", "authentication", "login forms", "registration forms"],
"command-palettes": ["quick actions", "search command", "command menu"],
"modal-dialogs": ["modal", "dialog"],
"navbars": ["top navigation", "top nav"],
"sidebar-navigation": ["side navigation", "side nav"],
"vertical-navigation": ["vertical nav"],
"empty-states": ["no data state", "zero state"],
"stats": ["kpi", "metrics"],
"description-lists": ["key value", "details list"],
"stacked-lists": ["list rows", "vertical list"],
"grid-lists": ["card grid", "tile list"],
}
def normalize_collection(raw_collection: str) -> str:
normalized = re.sub(r"-\d+$", "", raw_collection)
normalized = re.sub(r"\d+-(components|examples)$", "", normalized)
normalized = re.sub(r"-+$", "", normalized)
return normalized
def normalize_variant(filename_stem: str) -> str:
variant = filename_stem.split("--", 1)[0]
variant = re.sub(r"-\d+$", "", variant)
return variant
def tokenize_slug(value: str) -> list[str]:
words = [part for part in value.split("-") if part]
filtered = [word for word in words if word not in STOPWORDS]
return filtered or words
def dedupe(values: list[str]) -> list[str]:
seen = set()
result = []
for value in values:
if value and value not in seen:
seen.add(value)
result.append(value)
return result
def source_priority(path: str) -> tuple[int, int, str]:
raw_collection = Path(path).parts[3]
normalized = normalize_collection(raw_collection)
if raw_collection == normalized:
score = 0
elif raw_collection.endswith("-002"):
score = 1
elif re.search(r"\d+-(components|examples)$", raw_collection):
score = 2
else:
score = 3
return score, len(raw_collection), raw_collection
def build_aliases(domain: str, collection: str, variant: str) -> list[str]:
variant_phrase = variant.replace("-", " ")
collection_phrase = collection.replace("-", " ")
domain_phrase = domain.replace("-", " ")
aliases = [
variant_phrase,
f"{collection_phrase} {variant_phrase}",
f"{domain_phrase} {collection_phrase} {variant_phrase}",
]
aliases.extend(COLLECTION_ALIASES.get(collection, []))
return dedupe(aliases)
def build_tags(domain: str, collection: str, variant: str) -> list[str]:
tags = [domain, collection]
tags.extend(tokenize_slug(collection))
tags.extend(tokenize_slug(variant))
return dedupe(tags)
def discover_repo_root(start: Path) -> Path:
for parent in [start, *start.parents]:
if (parent / "templates" / "application-ui").exists():
return parent
return start
def parse_arguments() -> argparse.Namespace:
script_path = Path(__file__).resolve()
guessed_root = discover_repo_root(script_path)
default_output = script_path.parent.parent / "references" / "template-catalog.json"
parser = argparse.ArgumentParser(description="Build canonical template catalog.")
parser.add_argument(
"--root",
type=Path,
default=guessed_root,
help="Repository root that contains templates/application-ui.",
)
parser.add_argument(
"--templates-dir",
default="templates/application-ui",
help="Template directory relative to --root.",
)
parser.add_argument(
"--output",
type=Path,
default=default_output,
help="Output JSON path. Relative paths are resolved from --root.",
)
return parser.parse_args()
def main() -> int:
args = parse_arguments()
root = args.root.resolve()
templates_dir = (root / args.templates_dir).resolve()
output = args.output
if not output.is_absolute():
output = (root / output).resolve()
if not templates_dir.exists():
raise SystemExit(f"Templates directory not found: {templates_dir}")
grouped_paths: dict[str, list[str]] = defaultdict(list)
entries_meta: dict[str, dict[str, str]] = {}
html_paths = sorted(path for path in templates_dir.rglob("*.html") if path.is_file())
for html_path in html_paths:
relative = html_path.relative_to(root).as_posix()
parts = Path(relative).parts
if len(parts) < 5:
continue
domain = parts[2]
raw_collection = parts[3]
collection = normalize_collection(raw_collection)
variant = normalize_variant(Path(parts[-1]).stem)
block_id = f"ui.{domain}.{collection}.{variant}"
grouped_paths[block_id].append(relative)
entries_meta[block_id] = {
"domain": domain,
"collection": collection,
"variant": variant,
}
items = []
for block_id in sorted(grouped_paths.keys()):
metadata = entries_meta[block_id]
all_paths = sorted(grouped_paths[block_id], key=source_priority)
source_path = all_paths[0]
alternate_paths = all_paths[1:]
domain = metadata["domain"]
collection = metadata["collection"]
variant = metadata["variant"]
use_when, avoid_when = DOMAIN_RULES.get(
domain,
(
"Use when this block fits the current UI region and interaction goal.",
"Avoid when introducing this block would conflict with current semantics or behavior.",
),
)
items.append(
{
"id": block_id,
"domain": domain,
"collection": collection,
"variant": variant,
"source_path": source_path,
"alternate_source_paths": alternate_paths,
"aliases": build_aliases(domain, collection, variant),
"tags": build_tags(domain, collection, variant),
"use_when": use_when,
"avoid_when": avoid_when,
}
)
payload = {
"version": "1.0",
"generated_at": datetime.now(timezone.utc).isoformat(),
"source_root": str(templates_dir.relative_to(root).as_posix()),
"total_source_files": len(html_paths),
"total_catalog_items": len(items),
"items": items,
}
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(json.dumps(payload, indent=2) + "\n")
print(f"Catalog written to {output}")
print(f"Source files: {payload['total_source_files']}")
print(f"Catalog items: {payload['total_catalog_items']}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Related skills
FAQ
What does rails-application-ui-blocks do?
rails-application-ui-blocks: A skill for development. This provides functionality for development workflows.
When should I use rails-application-ui-blocks?
When you need to use rails-application-ui-blocks for development tasks, or when rails-application-ui-blocks: a skill for development. this provides functionality for development workflows.
What are the main capabilities?
rails-application-ui-blocks.