π¨ UI-First Builder Skill
name: ui-first-builder description: Build user interfaces first, then add logic - the visual-first development approach
π― Purpose
Develop applications by creating the UI first with mock data, then gradually adding real functionality.
π When to Use
- Starting new features
- Rapid prototyping
- Getting stakeholder feedback early
- When requirements are unclear
π§ UI-First Workflow
βββββββββββββββββββ
β 1. MOCKUP β β Wireframe/Design
ββββββββββ¬βββββββββ
βΌ
βββββββββββββββββββ
β 2. STATIC UI β β HTML/CSS with mock data
ββββββββββ¬βββββββββ
βΌ
βββββββββββββββββββ
β 3. COMPONENTS β β Break into reusable parts
ββββββββββ¬βββββββββ
βΌ
βββββββββββββββββββ
β 4. INTERACTIONS β β Add click handlers, forms
ββββββββββ¬βββββββββ
βΌ
βββββββββββββββββββ
β 5. REAL DATA β β Connect to APIs
ββββββββββ¬βββββββββ
βΌ
βββββββββββββββββββ
β 6. POLISH β β Animations, edge cases
βββββββββββββββββββ
π Step-by-Step Guide
Step 1: Create Mockup
- Sketch the UI layout
- Identify key components
- Define user flow
- Get initial feedback
Step 2: Static UI with Mock Data
// Mock data first
const mockUsers = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },
];
// Static component
function UserList() {
return (
<div className="user-list">
{mockUsers.map(user => (
<div key={user.id} className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
))}
</div>
);
}
Step 3: Extract Components
// UserCard component
function UserCard({ user }) {
return (
<div className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
}
// UserList uses UserCard
function UserList({ users }) {
return (
<div className="user-list">
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
Step 4: Add Interactions
function UserCard({ user, onSelect }) {
return (
<div
className="user-card"
=> onSelect(user)}
>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
}
Step 5: Connect Real Data
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/users')
.then(res => res.json())
.then(data => {
setUsers(data);
setLoading(false);
});
}, []);
if (loading) return <LoadingSpinner />;
return (
<div className="user-list">
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
Step 6: Polish
// Add animations, error states, empty states
function UserList() {
const { users, loading, error } = useUsers();
if (loading) return <Skeleton count={5} />;
if (error) return <ErrorMessage error={error} />;
if (users.length === 0) return <EmptyState />;
return (
<motion.div className="user-list" layout>
{users.map(user => (
<motion.div
key={user.id}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
<UserCard user={user} />
</motion.div>
))}
</motion.div>
);
}
π¨ Component Patterns
Card Pattern
function Card({ children, header, footer }) {
return (
<div className="card">
{header && <div className="card-header">{header}</div>}
<div className="card-body">{children}</div>
{footer && <div className="card-footer">{footer}</div>}
</div>
);
}
List Pattern
function List({ items, renderItem, emptyMessage }) {
if (items.length === 0) {
return <p>{emptyMessage}</p>;
}
return (
<ul className="list">
{items.map((item, index) => (
<li key={item.id || index}>{renderItem(item)}</li>
))}
</ul>
);
}
β UI-First Checklist
- Mockup reviewed and approved
- Static UI matches design
- Components are reusable
- All states handled (loading, error, empty)
- Interactions feel responsive
- Mobile responsive
- Animations smooth
π Related Skills
design-mastery- Design patternsvision-to-code- Convert designstesting- Test UI components