Create framework-aware UI mockups with feasibility checks. Prevents wasted effort by validating that proposed designs work within the target framework's constraints.
Install
npx skillscat add saajunaid/caddis-plugin/mockup Install via the SkillsCat registry.
Mockup Skill
Purpose
Create visual mockups (HTML/SVG) for UI features with mandatory framework feasibility validation. This skill exists because of a real incident: a beautiful HTML mockup was created for a Streamlit app using position: fixed — which doesn't work in Streamlit's DOM. 24 hours were wasted discovering this.
This skill prevents that class of failure for ANY framework.
When to Use
- Creating a UI mockup for a proposed feature
- Visualizing a design before implementation
- Producing a reference artifact for implementing agents
- When
@ux-designerroutes mockup creation here
Steps
Step 1: Read Project Context
- Read
project-config.md→ identify:- Frontend framework (Streamlit, React, Vue, Angular, Next.js, etc.)
- Brand colors (from profile or placeholder values)
- CSS conventions (scoping method, custom properties, etc.)
- Read
copilot-instructions.md→ identify:- Existing component patterns
- Framework-specific conventions already documented
- If a
chain_idis provided, read the Intent Document fromagent-docs/intents/
Step 2: Framework Feasibility Check (MANDATORY)
Before creating ANY mockup, validate that the proposed design is feasible in the target framework.
Run through this checklist:
| Check | Question | If NO |
|---|---|---|
| DOM Control | Does the framework give you full control over the DOM? | Identify which HTML/CSS features are restricted |
| Positioning | Does position: fixed/absolute work as expected? |
Document the limitation and alternative approach |
| Custom HTML | Can you inject arbitrary HTML/JS? | Identify the framework's component/extension API |
| Event Handling | Can you attach custom JS event listeners? | Document how events work in this framework |
| Styling | Can you use global CSS freely? | Document CSS scoping constraints |
| Third-party Libraries | Can you load external JS/CSS? | Check if air-gapped deployment restricts this |
Known Framework Constraints
| Framework | Key Constraints |
|---|---|
| Streamlit | No position: fixed/absolute (DOM wrapping breaks it). No arbitrary HTML injection without components.html() or declare_component(). CSS is scoped — use st.container(key=) + .st-key- selectors. No external CDN in air-gapped environments. |
| React | JSX required. CSS-in-JS or CSS Modules typical. Virtual DOM diffing may interfere with manual DOM manipulation. |
| Vue | Template syntax. Scoped styles by default. v-html for raw HTML but XSS risk. |
| Gradio | Similar DOM constraints to Streamlit. Limited CSS control. Use gr.HTML() for custom elements. |
| Next.js | SSR considerations. useEffect needed for client-only code. CSS Modules or Tailwind typical. |
If ANY constraint would prevent the proposed design from working:
- STOP — do not create a mockup that can't be implemented
- WARN the user with specific details about what won't work and why
- PROPOSE ALTERNATIVES that work within the framework's constraints
- Get confirmation before proceeding with an alternative approach
Step 3: Create the Mockup
Output format: HTML file (preferred for interactive mockups) or SVG (for static layouts)
Requirements:
- Use brand colors from
project-config.md(never hardcode colors — use CSS custom properties) - Include responsive behavior if applicable
- Add comments explaining key layout decisions
- If the mockup uses workarounds for framework constraints, document them clearly in comments
HTML mockup template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{Feature Name} — Mockup</title>
<style>
/* Brand colors from project-config.md */
:root {
--brand-primary: {<BRAND_PRIMARY>};
--brand-dark: {<BRAND_DARK>};
--brand-light: {<BRAND_LIGHT>};
/* Additional colors from profile */
}
/* Mockup styles */
/* ... */
</style>
</head>
<body>
<!-- MOCKUP: {Feature description} -->
<!-- FRAMEWORK: {Target framework} -->
<!-- CONSTRAINTS: {Any framework constraints that shaped this design} -->
<!-- ALTERNATIVES: {If using a workaround, what was the original approach and why it wouldn't work} -->
<!-- Mockup content -->
</body>
</html>Step 3b: Implementation-Annotated Mockup (MANDATORY for handoff to implementing agents)
When the mockup will be handed off to @implement, @frontend-developer, or @streamlit-developer, embed implementation annotations throughout the HTML so the implementing agent knows exactly what to build without guessing.
Annotation Types
Use these four comment patterns consistently:
1. Component annotations — Which framework component implements this visual element:
<!-- React: <KpiFlipCard product="broadband" data={surveys.broadband}
trendData={trend.historicalNPS.byProduct.broadband} /> -->
<!-- React: <ResponsiveContainer width="100%" height={260}>
<AreaChart data={trendData}><Area type="monotone" dataKey="nps" ... /></AreaChart>
</ResponsiveContainer> -->
<!-- React: import { ScoreChip, DeltaBadge, SparkBar, TrendDot } from '@/components/table-cells' -->2. Data source annotations — Which JSON key / API response field provides the data:
<!-- DATA-SOURCE: surveys.broadband.nps, surveys.broadband.responses -->
<!-- DATA-SOURCE: trend.historicalNPS.byProduct.broadband (array of monthly values) -->
<!-- DATA-SOURCE: ceoInsight.headline, ceoInsight.keyFindings[] (objects with title, detail) -->3. Implementation notes — Broader guidance for the implementing agent:
<!-- IMPLEMENTATION NOTE [DATA-SOURCE]: This section uses hardcoded mock values for
layout reference. React implementation must fetch period-filtered data from the
/api/nps/overview endpoint and compute all KPIs dynamically. -->
<!-- IMPLEMENTATION NOTE [CHART]: Use Recharts AreaChart with gradient fill.
Spread CHART_DEFAULTS from chartTheme.ts. No axes/grid for sparkline variant. -->
<!-- IMPLEMENTATION NOTE [ANIMATION]: Use framer-motion rotateY for card flip.
duration: 0.52, ease: [0.4, 0.2, 0.2, 1]. backfaceVisibility: "hidden". -->4. Styling annotations — Which design tokens, CSS vars, or Tailwind classes to use:
<!-- STYLE: bg-surface-card (var(--surface-card)), shadow-card, rounded-lg (var(--r-lg)) -->
<!-- STYLE: Fill color uses var(--status-red) for detractor, var(--status-green) for promoter -->
<!-- STYLE: Tailwind: text-ink-primary font-heading text-2xl font-bold -->Annotation Placement Rules
- Place component annotations directly above or inside the HTML element that the component replaces
- Place data source annotations on the element that displays the data value
- Place implementation notes at the top of each major section (tab, panel, card group)
- Place styling annotations on elements where the visual appearance matters and the token name isn't obvious from the CSS
- Every hardcoded value in the mockup (numbers, text, colors) that will be dynamic in production MUST have a data source annotation
Example: Annotated KPI Card
<!-- React: <KpiFlipCard product="broadband" data={surveys.broadband}
trendData={trend.historicalNPS.byProduct.broadband} color={COLORS.broadband} /> -->
<!-- DATA-SOURCE: surveys.broadband.nps (current score), surveys.broadband.responses (count) -->
<!-- STYLE: var(--surface-card) bg, var(--shadow-card) shadow, 3px left border using COLORS.broadband -->
<div class="kpi-card">
<div class="kpi-score">+32</div> <!-- DATA-SOURCE: surveys.broadband.nps -->
<div class="kpi-delta">▲ 2.1</div> <!-- DATA-SOURCE: deriveMom(trend.historicalNPS.byProduct.broadband) -->
<div class="kpi-responses">1,247 responses</div> <!-- DATA-SOURCE: surveys.broadband.responses -->
<div class="sparkline">
<!-- React: <Sparkline data={trend.historicalNPS.byProduct.broadband}
color={COLORS.broadband} height={72} /> -->
<!-- IMPLEMENTATION NOTE [CHART]: Recharts AreaChart, no axes/grid/tooltip,
gradient fill from color at opacity 0.3 to opacity 0. -->
</div>
</div>Completeness Check
Before saving the mockup, verify:
- Every visual section has at least one component annotation
- Every dynamic value has a data source annotation with the exact JSON path
- Every chart/graph has an implementation note specifying the chart library and config
- The implementing agent can build the feature using ONLY the mockup + annotations (no guessing)
Step 4: Write Artifact
- Save the mockup file to
agent-docs/ux/mockups/{feature-slug}.html(or.svg) - Add YAML header to a companion markdown file or embed as HTML comment:
agent: ux-designer created: {date} status: current chain_id: {chain_id if provided} approval: pending framework: {target framework} feasibility_warnings: {list any constraints encountered} - Update
agent-docs/ARTIFACTS.mdmanifest with the new entry
Step 5: Report
Provide:
- Path to the mockup file
- Framework feasibility summary (what was checked, any warnings)
- Implementation notes for the agent that will build this (which API/component to use, what CSS approach works)
- If alternatives were chosen, explain why the original approach wouldn't work
Framework Feasibility Quick Reference
Streamlit-Specific
| Want to do | Don't use | Instead use |
|---|---|---|
| Floating element (chat widget, FAB) | position: fixed/absolute |
declare_component() with custom HTML/JS |
| Custom styled container | Global CSS | st.container(key="name") + .st-key-name selector |
| Modal/overlay | z-index + absolute positioning |
st.dialog() (Streamlit 1.33+) or st.modal() |
| Sidebar content | Custom sidebar HTML | st.sidebar API |
| Custom header | Fixed position header | st.container() at top + CSS with st.container(key=) |
| External JavaScript | <script src="cdn..."> |
Bundle locally for air-gapped; use components.html() |
React-Specific
| Want to do | Watch out for | Recommended approach |
|---|---|---|
| Direct DOM manipulation | React re-renders will overwrite | Use refs (useRef) or state-driven rendering |
| Global styles | May conflict with component styles | CSS Modules, styled-components, or Tailwind |
| Third-party widgets | jQuery plugins fight React | Find React-native alternatives or wrap in useEffect |
Important Notes
- This skill is designed to be loaded by
@ux-designeror@frontend-developeragents - The framework constraint tables should be extended as new frameworks and gotchas are discovered
- Always check
project-config.mdfor the deployment environment — air-gapped deployments restrict external dependencies