From ripple-plugin
Sets up @ripple/ui (Unit4's Ripple design system) in the current project, or generates a self-contained HTML prototype using Ripple tokens. Use when the user wants to install Ripple, scaffold a new Ripple project, add Ripple to an existing project, fix a broken Ripple installation, or create an HTML prototype with the Ripple design system.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ripple-plugin:rippleThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Set up the Ripple design system (@ripple/ui) in the current project, or create a standalone HTML prototype.
Set up the Ripple design system (@ripple/ui) in the current project, or create a standalone HTML prototype.
Before doing anything, ask:
"Are you a developer setting up Ripple in a React project, or do you want to create a quick HTML prototype using Ripple's look and feel — no coding required?"
Check the current directory:
package.json → New project. Ask: "Are you already inside your project folder, or should I create one?" Then follow Flow A.package.json exists, @ripple/ui already in node_modules → Already installed. Follow Flow C.package.json exists, no @ripple/ui → Existing project. Follow Flow B.If the user is already inside their project folder, scaffold into the current directory:
npm create vite@latest . -- --template react-ts
npm install --legacy-peer-deps
npm install https://github.com/VascoA09/Ripple --legacy-peer-deps
If the user wants a new folder created, ask for a project name then run:
npm create vite@latest [project-name] -- --template react-ts
cd [project-name]
npm install --legacy-peer-deps
npm install https://github.com/VascoA09/Ripple --legacy-peer-deps
Then make these file changes:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import '@ripple/ui/style.css'
import './index.css'
import App from './App'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<div data-theme="light">
<App />
</div>
</StrictMode>
)
/* Ripple reset — do not add :root variables here */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: var(--font-family-base); color: var(--text); background: var(--bg-canvas); -webkit-font-smoothing: antialiased; }
#root { min-height: 100svh; }
/* Add prototype-specific styles here — do not redefine Ripple tokens */
import { StandardNavigation, Unit4Logo, Button, Input, Tag, Badge, Card, CardHeader, CardTitle, CardContent } from '@ripple/ui'
import { LayoutDashboard } from 'lucide-react'
import ripplePkg from '../node_modules/@ripple/ui/package.json'
export default function App() {
return (
<StandardNavigation
nav={{
logo: <Unit4Logo />,
productName: 'My App',
globalNavItems: [
{ id: 'home', label: 'Home', icon: <LayoutDashboard size={20} />, selected: true, onClick: () => {} },
],
}}
>
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
minHeight: '100%',
gap: 'var(--spacing-100)',
padding: 'var(--spacing-200)',
}}>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 'var(--spacing-75)', textAlign: 'center' }}>
<Unit4Logo width={74} height={42} />
<h1 className="typography-heading-l" style={{ margin: 0 }}>Welcome to Ripple</h1>
<p className="typography-body" style={{ margin: 0, color: 'var(--text-soft)' }}>Unit4's design system for product UI</p>
</div>
<Card style={{ width: '100%', maxWidth: '400px' }}>
<CardHeader>
<CardTitle as="h2">Get started</CardTitle>
</CardHeader>
<CardContent>
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--spacing-150)' }}>
<Input label="Email" placeholder="[email protected]" />
<div style={{ display: 'flex', gap: 'var(--spacing-50)' }}>
<Button variant="fill">Primary</Button>
<Button variant="outline">Secondary</Button>
</div>
<div style={{ display: 'flex', gap: 'var(--spacing-50)', alignItems: 'center' }}>
<Tag color="blue">Design</Tag>
<Tag color="green">System</Tag>
<Badge color="primary">3</Badge>
</div>
</div>
</CardContent>
</Card>
<p className="typography-caption" style={{ margin: 0 }}>
@ripple/ui v{ripplePkg.version}
</p>
</div>
</StandardNavigation>
)
}
npm install https://github.com/VascoA09/Ripple --legacy-peer-deps
Then:
Find the CSS entry files — check src/index.css and src/App.css for :root variable blocks. Remove any that define --text, --bg, --border or similar — they clash with Ripple tokens.
Find the main entry file — check src/main.tsx or src/main.jsx. Add this import before any other CSS:
import '@ripple/ui/style.css'
Find the root wrapper — in main.tsx, add data-theme="light" to the outermost div wrapping the app. If there's no wrapper div, add one.
Report every file changed.
Check that node_modules/@ripple/ui/dist/style.css exists.
node_modules/@ripple/ui/package.json and confirm ready.npm cache clean --force && npm install https://github.com/VascoA09/Ripple --legacy-peer-deps.This flow is for non-developers who want a ready-to-open HTML file that looks like a real Ripple UI.
Ask ONE question:
"What would you like to prototype? For example: a login page, a dashboard, a form, a list view, a settings screen — or describe what you have in mind."
Wait for the answer before proceeding.
Fetch the compiled Ripple stylesheet and embed it inline in the HTML so the file is fully self-contained and works without internet access.
Fetch from:
https://raw.githubusercontent.com/VascoA09/Ripple/main/dist/style.css
If that fails, try:
https://cdn.jsdelivr.net/gh/VascoA09/Ripple@main/dist/style.css
If both fail, embed a minimal set of Ripple-compatible CSS variables as a fallback (see Fallback tokens below).
Create a self-contained .html file named after the prototype (e.g. login.html, dashboard.html).
Required structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>[Prototype name]</title>
<style>
/* === RIPPLE CSS (embedded) === */
[paste fetched CSS here]
/* === Page reset === */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: var(--font-family-base); color: var(--text); background: var(--bg-canvas); -webkit-font-smoothing: antialiased; }
</style>
</head>
<body data-theme="light">
<!-- prototype content here -->
</body>
</html>
Key rules for HTML prototypes:
data-theme="light" must always be on <body>:root CSS variables — use only var(--token-name) from Ripplevar(--spacing-50) through var(--spacing-400)var(--text), var(--text-soft), var(--bg-surface), var(--bg-canvas), var(--border)typography-heading-l, typography-heading-m, typography-body, typography-captionReference HTML patterns for common Ripple components:
<button style="background: var(--color-primary); color: var(--text-on-primary); border: none; border-radius: var(--radius-m); padding: var(--spacing-75) var(--spacing-150); font-family: var(--font-family-base); font-size: var(--font-size-m); cursor: pointer;">
Button label
</button>
<button style="background: transparent; color: var(--color-primary); border: 1px solid var(--color-primary); border-radius: var(--radius-m); padding: var(--spacing-75) var(--spacing-150); font-family: var(--font-family-base); font-size: var(--font-size-m); cursor: pointer;">
Button label
</button>
<div style="display: flex; flex-direction: column; gap: var(--spacing-25);">
<label style="font-size: var(--font-size-s); color: var(--text-soft);">Label</label>
<input type="text" placeholder="Placeholder" style="border: 1px solid var(--border); border-radius: var(--radius-m); padding: var(--spacing-75) var(--spacing-100); font-family: var(--font-family-base); font-size: var(--font-size-m); color: var(--text); background: var(--bg-surface); outline: none;" />
</div>
<div style="background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-l); padding: var(--spacing-200);">
<h2 class="typography-heading-m" style="margin: 0 0 var(--spacing-100);">Card title</h2>
<!-- card content -->
</div>
<nav style="background: var(--bg-surface); border-bottom: 1px solid var(--border); padding: 0 var(--spacing-200); height: 56px; display: flex; align-items: center; gap: var(--spacing-150);">
<span class="typography-heading-m" style="margin: 0;">App name</span>
<a href="#" style="color: var(--text-soft); text-decoration: none; font-size: var(--font-size-m);">Home</a>
<a href="#" style="color: var(--text-soft); text-decoration: none; font-size: var(--font-size-m);">Settings</a>
</nav>
<span style="background: var(--color-blue-subtle); color: var(--color-blue); border-radius: var(--radius-full); padding: var(--spacing-25) var(--spacing-75); font-size: var(--font-size-s);">Label</span>
Save the file to the workspace folder. Then tell the user:
"Your prototype is ready — just double-click the file to open it in your browser. No installs needed."
:root {
--font-family-base: 'Inter', system-ui, sans-serif;
--font-size-s: 12px; --font-size-m: 14px; --font-size-l: 16px;
--text: #1a1a2e; --text-soft: #6b7280; --text-on-primary: #ffffff;
--bg-canvas: #f4f5f7; --bg-surface: #ffffff;
--border: #e5e7eb;
--color-primary: #0f62fe;
--color-blue: #0f62fe; --color-blue-subtle: #dbeafe;
--color-green: #16a34a; --color-green-subtle: #dcfce7;
--radius-m: 6px; --radius-l: 10px; --radius-full: 999px;
--spacing-25: 2px; --spacing-50: 4px; --spacing-75: 6px;
--spacing-100: 8px; --spacing-150: 12px; --spacing-200: 16px;
--spacing-300: 24px; --spacing-400: 32px;
}
--legacy-peer-deps (React flows)@ripple/ui/style.css — never @ripple/ui/dist/style.css (React flows)data-theme="light" is required on the root wrapper (all flows)lucide-react installs automatically with Ripple — no separate install needed (React flows):root variables — they override Ripple tokens (React flows):root variables in HTML prototypes — use Ripple tokens only (Flow D)React flows: bullet list of what was done + next step (npm run dev) + reminder to use Ripple tokens. Full docs: https://github.com/VascoA09/Ripple/blob/main/SETUP.md
HTML prototype flow: confirm the file was saved, tell the user to double-click to open it, and offer to adjust any section or add more screens.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub vascoa09/ripple-plugin --plugin ripple-plugin