agentsclimarketplace

Symbiote components

Skill rnd-pro/stitch-skills/skills/symbiote-components

Agent skills for Stitch MCP, Project Graph MCP, and Symbiote.js component generation.

Install
npx -y skills add rnd-pro/stitch-skills --skill symbiote-components

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Converts Stitch designs into modular Symbiote.js 3.x components using triple-file architecture, CSS custom properties, and Project Graph MCP validation.

SKILL.md

11.5 KB, as published. Nobody here has run it

Stitch to Symbiote Components

You are a frontend engineer focused on transforming Stitch designs into clean Symbiote.js 3.x components. You follow a modular triple-file architecture and use Project Graph MCP tools for automated quality checks.

Key references:

  • Official API: AI_REFERENCE.md
  • Quick reference: resources/symbiote-3x-reference.md (at project root)
  • Global styles: resources/global-styles-template.md (at project root)

Package Boundaries

Use the package that owns the contract you are consuming:

  • @symbiotejs/[email protected] — core component runtime, Symbiote, html, css, PubSub, AppRouter, SSR primitives, and WebMCP-capable runtime metadata.
  • [email protected] — reusable UI components, graph/layout/provider metadata, tokens, rules, schemas, custom-elements.json, and WebMCP UI descriptors.
  • [email protected] — runtime engines, workflow execution, handlers, packs, persistence, and server/runtime CLI contracts.

Do not introduce symbiote-node for new projects. Treat it as a terminal migration facade only when maintaining a legacy consumer that explicitly tests compatibility.

Retrieval and Networking

  1. Namespace discovery: Run list_tools to find the Stitch MCP prefix (e.g., mcp_StitchMCP_).
  2. Metadata fetch: Call [prefix]get_screen to retrieve the design JSON.
  3. Asset download: Use web_fetch or read_url_content to download HTML from htmlCode.downloadUrl.
  4. Visual audit: Check screenshot.downloadUrl to confirm the design intent and layout details.

Architectural Rules

Triple-File Standard (MANDATORY)

Every component MUST be split into exactly three files:

src/components/TaskCard/
├── TaskCard.js       — Class logic only (extends Symbiote)
├── TaskCard.tpl.js   — Template (html tagged template)
└── TaskCard.css.js   — Styles (css tagged template)

Core Conventions

  • Custom Elements: Every component is a Custom Element registered with .reg('tag-name')
  • ESM only: Use import/export. Never require()
  • No Tailwind: Use native CSS with custom properties (design tokens from DESIGN.md)
  • No BEM: Use custom tag names and attribute selectors as CSS selectors
  • No wrapper divs: The custom tag IS the wrapper element
  • No CSS frameworks: Pure CSS with modern nesting
  • JSDoc in English: Document in JSDoc, no TypeScript files
  • Template outside class: MyComp.template = html\...`` — NEVER inside the class body

Style Mapping

  • Extract colors, spacing, and typography from the Stitch HTML <head> or inline styles
  • Map all values to CSS custom properties defined in DESIGN.md (or create them if missing)
  • Use rootStyles for Light DOM components by default
  • Use shadowStyles / Shadow DOM only when real isolation is required: third-party CSS containment, hostile or unknown markup, embedded previews/demos, or browser API encapsulation
  • If the issue is styling, themes, selector conflicts, or uncertainty, first solve it with Symbiote bindings, CSS custom properties, slots, context, provider tokens, and component composition before choosing Shadow DOM

Data Decoupling

  • Move all static text, image URLs, and list data into separate data files
  • Use local init$ for component-specific state
  • Use * prefix + ctx attribute for shared context between sibling components
  • Use named context (PubSub.registerCtx) for global application state (APP/prop syntax)
  • See resources/symbiote-3x-reference.md for PubSub and Shared Context patterns

Element References

  • Use ${{ref: 'name'}} in templates for DOM element access
  • Access via this.ref.name in renderCallback()
  • Prefer state bindings over direct DOM manipulation

Slots (Light DOM)

  • Import slotProcessor from @symbiotejs/symbiote/core/slotProcessor.js
  • Add in constructor: this.templateProcessors.add(slotProcessor)
  • Use <slot name="header"></slot> and <slot></slot> in templates
  • See resources/symbiote-3x-reference.md for full example

WebMCP Metadata

Use WebMCP documentation for agents in bounded, contract-level form. Component metadata should describe names, descriptions, input schemas, SSR class, visibility, and permission hints. Do not turn WebMCP descriptors into long prose docs or hidden policy systems.

Component Template

Use resources/component-template.js as a starting point. Replace StitchComponent with the actual component name.

Template File Pattern (Component.tpl.js)

import { html } from '@symbiotejs/symbiote';

export const template = html`
  <header>
    <h2>{{title}}</h2>
    <span>{{description}}</span>
  </header>
  <div ${{onclick: 'onAction'}}>
  </div>
`;

NOTE: Light DOM slots require explicit slotProcessor setup in v3.x:

import { slotProcessor } from '@symbiotejs/symbiote/core/slotProcessor.js';
constructor() { super(); this.templateProcessors.add(slotProcessor); }

Styles File Pattern (Component.css.js)

import { css } from '@symbiotejs/symbiote';

export const styles = css`
  my-component {
    display: block;
    padding: var(--spacing-md);
    background: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);

    & header {
      margin-block-end: var(--spacing-sm);
    }

    & h2 {
      font-size: var(--font-size-lg);
      font-weight: var(--font-weight-semibold);
      color: var(--color-text);
    }

    &:hover {
      box-shadow: var(--shadow-md);
      transition: box-shadow var(--transition-fast);
    }

    &[hidden] {
      display: none !important;
    }
  }
`;

Logic File Pattern (Component.js)

import Symbiote from '@symbiotejs/symbiote';
import { template } from './Component.tpl.js';
import { styles } from './Component.css.js';

export class MyComponent extends Symbiote {
  init$ = {
    title: '',
    description: '',
    // Event handlers: init$ arrow functions checked first, then class methods as fallback
    onAction: () => {
      console.log('Action triggered');
    },
  };
}

MyComponent.template = template;
MyComponent.rootStyles = styles;
MyComponent.reg('my-component');

Key v3.x Features

Event handler resolution: For on* bindings, Symbiote first looks in init$, then falls back to class methods:

class MyComponent extends Symbiote {
  init$ = { onClick: () => console.log('via init$') };
  onSubmit() { console.log('via class method fallback'); }
}

Computed properties (+ prefix, auto-tracked):

init$ = {
  a: 1,
  b: 2,
  '+sum': () => this.$.a + this.$.b, // recalculates when a or b change
};

Element references (ref):

MyComponent.template = html`
  <input ${{ref: 'nameInput'}}>
  <button ${{ref: 'submitBtn', onclick: 'onSubmit'}}>Submit</button>
`;
// In renderCallback: this.ref.nameInput.focus();

Dev mode (enable during development):

Symbiote.devMode = true; // warns about unresolved bindings, missing ctx, etc.

Exit animations (animateOut):

import { animateOut } from '@symbiotejs/symbiote';
// Sets [leaving] attribute, waits for CSS transitionend, then removes element
my-item {
  transition: opacity 0.3s;
  &[leaving] { opacity: 0; }
}

Execution Steps

  1. Read DESIGN.md: If exists, load the CSS custom properties and component patterns.
  2. Download Stitch HTML: Fetch the HTML source from the screen's htmlCode.downloadUrl.
  3. Analyze structure: Identify repeating UI patterns, sections, and interactive elements.
  4. Plan components: Map each pattern to a Symbiote component with a custom element tag name.
  5. Create data layer: Extract static content into data files or named contexts.
  6. Draft components: Create each component using the triple-file structure.
  7. Wire entry point: Create a root component (e.g., app-root) that composes all sub-components.
  8. Validate with Project Graph MCP (see resources/project-graph-workflow.md at project root):
    • get_skeleton(path) — verify all components appear, check structure
    • get_full_analysis(path) — target Health Score ≥ 80
    • check_custom_rules(path) — auto-detects Symbiote, applies convention rules
    • get_dead_code(path) — cleanup unused exports after refactoring
    • get_undocumented(path) — verify JSDoc coverage
  9. Add test annotations to interactive handlers:
    /**
     * @test click: Click the action button
     * @expect visual: Status badge changes color
     */
    
  10. Run test checklist:
  • get_pending_tests(path) — list all @test/@expect annotations
  • Execute each test step (browser tool for UI)
  • mark_test_passed(testId) / mark_test_failed(testId, reason)
  • get_test_summary(path) — verify all tests pass
  1. Visual verify: Compare the assembled page against the Stitch screenshot.

Conversion Rules: Stitch HTML → Symbiote

HTML Structure

Stitch HTMLSymbiote Equivalent
<div class="card"><ui-card> (Custom Element)
<div class="card-header">Remove wrapper if unnecessary, use <header> inside template
class="text-lg font-bold"CSS: font-size: var(--font-size-lg); font-weight: var(--font-weight-bold);
class="bg-blue-500"CSS: background: var(--color-primary);
class="rounded-lg"CSS: border-radius: var(--radius-lg);
class="shadow-md"CSS: box-shadow: var(--shadow-md);
class="p-4"CSS: padding: var(--spacing-md);
class="flex gap-4"CSS: display: flex; gap: var(--spacing-md);
class="hidden"Attribute binding: ${{'@hidden': 'isHidden'}}
onclick="..."Binding: ${{onclick: 'handlerName'}}

Interactivity

PatternSymbiote Implementation
Show/Hide${{'@hidden': '!isVisible'}} in template, isVisible in init$
Dynamic text{{propertyName}} in template
Click handler${{onclick: 'onClickHandler'}} → method in class or init$
List rendering${{itemize: 'items'}} with <template> inside (use ^ for parent handlers)
Custom item tag${{itemize: 'items', 'item-tag': 'my-item'}} (inside binding block, not HTML attribute)
Form input${{oninput: 'onInput'}} with ref for value

Troubleshooting

  • Styles not applied: Ensure rootStyles is set OUTSIDE the class body
  • Template not rendering: Ensure template is assigned via the static setter, not inside the class
  • Events not firing in lists: Use ^ prefix for parent handlers in itemize templates: ${{onclick: '^parentHandler'}}
  • Hidden not working: Add &[hidden] { display: none !important; } if component has custom display

Quality Checklist

Before delivering, verify all items from resources/architecture-checklist.md:

  • Triple-file split for every component
  • No Tailwind classes anywhere
  • All colors use CSS custom properties
  • All spacing uses CSS custom properties
  • Custom tag name selectors (no BEM classes)
  • Native CSS nesting used
  • No unnecessary wrapper divs
  • Template assigned outside class body
  • Event handlers properly bound
  • Project Graph MCP analysis passes

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.