Contributing to BoseUI
We welcome contributions from developers, motion designers, and UI enthusiasts. Whether you're crafting a new kinetic interaction, tuning spring curves, or fixing documentation, here is everything you need to build and ship with confidence.
The 4 Architecture Principles
Components inside src/components/ui/ must be clean primitives with zero internal test HUDs, sliders, or prop changers.
Custom test states, interactive controls, and playground wrappers belong exclusively in src/components/docs/preview.tsx.
Every prop accepted by your TypeScript interface must be documented in your accompanying <Name>.meta.ts file.
Always use useReducedMotion() to respect accessibility settings. Use tactile spring physics over linear easings.
Step 1: Local Setup
Clone the repository and install dependencies
| 1 | # 1. Fork the repo on GitHub, then clone your fork |
| 2 | git clone https://github.com/<your-username>/bose-ui.git |
| 3 | cd bose-ui |
| 4 | |
| 5 | # 2. Add upstream remote |
| 6 | git remote add upstream https://github.com/Theb0se/bose-ui.git |
| 7 | |
| 8 | # 3. Install dependencies |
| 9 | npm install |
| 10 | |
| 11 | # 4. Start local development server |
| 12 | npm run dev |
Step 2: Scaffold Your Component
Use our automated generator to create boilerplate files in seconds
| 1 | # Scaffold your new component files in one command: |
| 2 | npm run component:new KineticCard |
| 3 | |
| 4 | # This automatically creates: |
| 5 | # ├── src/components/ui/KineticCard.tsx (Pure UI component) |
| 6 | # └── src/components/ui/KineticCard.meta.ts (Metadata & props schema) |
Step 3: Author the Component Primitive
Write clean, production-ready React in src/components/ui/KineticCard.tsx
| 1 | "use client"; |
| 2 | |
| 3 | import React from "react"; |
| 4 | import { motion, useReducedMotion } from "framer-motion"; |
| 5 | import { cn } from "@/lib/utils"; |
| 6 | |
| 7 | export interface KineticCardProps { |
| 8 | /** Card title */ |
| 9 | title?: string; |
| 10 | /** Explanatory description */ |
| 11 | description?: string; |
| 12 | /** Spring physics stiffness (default: 300) */ |
| 13 | stiffness?: number; |
| 14 | /** Spring physics damping (default: 25) */ |
| 15 | damping?: number; |
| 16 | /** Custom classes */ |
| 17 | className?: string; |
| 18 | children?: React.ReactNode; |
| 19 | } |
| 20 | |
| 21 | export function KineticCard({ |
| 22 | title, |
| 23 | description, |
| 24 | stiffness = 300, |
| 25 | damping = 25, |
| 26 | className, |
| 27 | children, |
| 28 | }: KineticCardProps) { |
| 29 | const shouldReduceMotion = useReducedMotion(); |
| 30 | |
| 31 | return ( |
| 32 | <motion.div |
| 33 | whileHover={shouldReduceMotion ? undefined : { y: -4, scale: 1.01 }} |
| 34 | transition={{ type: "spring", stiffness, damping }} |
| 35 | className={cn( |
| 36 | "relative overflow-hidden rounded-2xl border border-neutral-200/80 bg-white p-6 shadow-sm", |
| 37 | "dark:border-neutral-800/80 dark:bg-neutral-950 dark:text-white", |
| 38 | className |
| 39 | )} |
| 40 | > |
| 41 | {title && <h3 className="text-base font-semibold">{title}</h3>} |
| 42 | {description && ( |
| 43 | <p className="mt-1 text-xs text-neutral-500 dark:text-neutral-400"> |
| 44 | {description} |
| 45 | </p> |
| 46 | )} |
| 47 | {children} |
| 48 | </motion.div> |
| 49 | ); |
| 50 | } |
| 51 | |
| 52 | export default KineticCard; |
Step 4: Author the Metadata Contract
Document props, features, and accessibility in KineticCard.meta.ts
| 1 | import type { PulseComponentMeta } from "../../types/component"; |
| 2 | |
| 3 | export const kineticCardMeta: PulseComponentMeta = { |
| 4 | title: "Kinetic Card", |
| 5 | description: "Physics-driven surface with responsive spring elevation and dynamic lighting.", |
| 6 | tagline: "Tactile surface with micro-elevation mechanics", |
| 7 | category: "Cards", |
| 8 | badges: ["Kinetic", "Spring Physics", "Micro-interaction"], |
| 9 | createdAt: "2026-10-10", |
| 10 | keywords: ["card", "kinetic", "spring", "motion", "elevation"], |
| 11 | features: [ |
| 12 | "Sub-pixel spring elevation on hover with inertia dampening", |
| 13 | "Zero runtime lock-in with native shadcn CLI distribution", |
| 14 | "Respects prefers-reduced-motion accessibility standards", |
| 15 | ], |
| 16 | accessibility: [ |
| 17 | "Graceful degradation when prefers-reduced-motion is active", |
| 18 | "WCAG AA compliant contrast ratios across dark and light modes", |
| 19 | ], |
| 20 | props: [ |
| 21 | { |
| 22 | name: "title", |
| 23 | type: "string", |
| 24 | defaultValue: "undefined", |
| 25 | description: "Optional title heading", |
| 26 | required: false, |
| 27 | }, |
| 28 | { |
| 29 | name: "description", |
| 30 | type: "string", |
| 31 | defaultValue: "undefined", |
| 32 | description: "Primary description copy", |
| 33 | required: false, |
| 34 | }, |
| 35 | { |
| 36 | name: "stiffness", |
| 37 | type: "number", |
| 38 | defaultValue: "300", |
| 39 | description: "Spring physics stiffness tension", |
| 40 | required: false, |
| 41 | }, |
| 42 | { |
| 43 | name: "damping", |
| 44 | type: "number", |
| 45 | defaultValue: "25", |
| 46 | description: "Spring physics damping coefficient", |
| 47 | required: false, |
| 48 | }, |
| 49 | ], |
| 50 | usageCode: `import { KineticCard } from "@/components/ui/KineticCard"; |
| 51 | |
| 52 | export function Example() { |
| 53 | return ( |
| 54 | <KineticCard |
| 55 | title="Predictive Scaling" |
| 56 | description="Autonomous workload balancing based on real-time traffic surges." |
| 57 | /> |
| 58 | ); |
| 59 | }`, |
| 60 | }; |
| 61 | |
| 62 | export default kineticCardMeta; |
Step 5: Register in Central Preview Switchboard
Customize how the component displays in documentation stages inside src/components/docs/preview.tsx
| 1 | // Inside src/components/docs/preview.tsx: |
| 2 | import { KineticCard } from "@/components/ui/KineticCard"; |
| 3 | |
| 4 | // Add a case matching your kebab-case slug: |
| 5 | case "kinetic-card": |
| 6 | return ( |
| 7 | <div className="w-full max-w-md p-4"> |
| 8 | <KineticCard |
| 9 | title="Predictive Scaling" |
| 10 | description="Autonomous workload balancing based on real-time traffic surges." |
| 11 | className={className} |
| 12 | /> |
| 13 | </div> |
| 14 | ); |
Step 6: Sync, Test & Build
Verify TypeScript types, update the shadcn registry, and build static pages
| 1 | # 1. Run typecheck to verify types |
| 2 | npm run typecheck |
| 3 | |
| 4 | # 2. Sync the registry, sitemaps, and analyze props |
| 5 | npm run sync |
| 6 | |
| 7 | # 3. Test the static production build |
| 8 | npm run build |
Pull Request Checklist
- Component is a pure primitive without internal test HUDs or state sliders.
- All props in TypeScript interface are documented in
.meta.ts. - Preview case added to
preview.tsxfor documentation staging. useReducedMotion()is supported for users with motion sensitivities.npm run typecheckandnpm run syncpass with 100% health.