Protocol UI is a systematic AI-powered component generation system for ReScript/React projects. It features:
- DSPy-inspired architecture for component generation
- Automated theming system with one-command color switching
- Type-safe validation and ReScript compilation
- Design system integration with semantic color management
Switch color schemes with one command:
node scripts/theme.js "#1f2937" corporate
node scripts/theme.js "#059669" emeraldnpm run dev- start development serverrescript- compile ReScript filesrescript -w- watch mode for developmentnpm run build- production build
Generate components using the AI system:
node generate-component.jsDesignSystem.res- design tokens and color utilitiesThemeContext.res- theme managementColorPalette.res- automated color palette generationTailwindSafelist.res- auto-generated Tailwind classes
AppText.res- text component with semantic colorsAppButton.res- button component with variants
ReScriptGenerator.res- core generation logic- Pattern learning and validation system
// Standard component pattern
@react.component
let make = (~children, ~variant=#primary, ~onClick=?) => {
let classes = switch variant {
| #primary => backgroundColorToClass(Primary)
| #secondary => backgroundColorToClass(Secondary)
}
<button className=classes onClick={onClick->Option.getOr(_ => ())}>
{children}
</button>
}Use pattern matching for components that render different elements:
@react.component
let make = (~children, ~tag=#p, ~color=Primary) => {
let colorClass = colorToClass(color)
switch tag {
| #h1 => <h1 className=colorClass dataTestId="AppText">{children}</h1>
| #h2 => <h2 className=colorClass dataTestId="AppText">{children}</h2>
| #p => <p className=colorClass dataTestId="AppText">{children}</p>
}
}- Use
~propsyntax for labeled arguments - Access colors via
DesignSystem.colorToClass(Primary) - Use
dataTestId(camelCase) for test attributes - Pattern match with polymorphic variants:
[#primary | #secondary]
- Never mix async/await with Promise.resolve wrapping
- Let ReScript infer Promise return types - avoid explicit
Promise.t<T>in async functions - Use
awaitoutside switch expressions - ReScript limitation requires:let x = await fn(); switch x { ... } - Return values directly in async function bodies
- Consistent error handling - use Result pattern, not exceptions when possible
// ✅ CORRECT - Clean composition
let asyncFn = async () => {
try {
let result = await someOperation()
Ok(result) // Return directly
} catch {
| exn => Error("Failed") // Return directly
}
}This project demonstrates practical functional programming in ReScript:
- Type-safe composition without syntactic overhead
- Mathematical thinking for API design
- Monadic patterns using built-in Result types
- Pure functions with predictable composition
The approach balances mathematical rigor with practical accessibility.