frontend-development
SKILL.md
Frontend Development
Purpose
Implement React components and pages that follow designs, handle state properly, and provide good user experience.
When to Use
- UI component development
- Page implementation
- State management
- Form handling
Prerequisites
- Wireframes/designs available
- Component specs defined
- API contracts known
- Design system (if any)
Process
Step 1: Review Design
Understand:
- Layout requirements
- Component breakdown
- Interactions
- Responsive behavior
Step 2: Implement Components
Component structure:
- Props interface
- State management
- Event handlers
- Render logic
Step 3: Handle State
State patterns:
- Local state (useState)
- Server state (React Query)
- Form state (React Hook Form)
- Global state (Context/Zustand)
Step 4: Style Components
Styling approach:
- Tailwind CSS
- Component library
- Responsive design
- Accessibility
Step 5: Write Tests
Test types:
- Unit tests (logic)
- Component tests (rendering)
- Integration tests (flows)
Inputs
| Input | Type | Required | Description |
|---|---|---|---|
| wireframes | Images | Yes | UI designs |
| component_specs | Markdown | Yes | Component details |
| api_spec | YAML | Yes | API contracts |
Outputs
| Output | Type | Description |
|---|---|---|
| components/ | TSX | React components |
| pages/ | TSX | Page components |
| hooks/ | TypeScript | Custom hooks |
StudyAbroad-Specific Considerations
- Multi-step application form
- Search with filters
- Document upload UI
- Status dashboards
Integration Points
- Design Agent: UI specifications
- Test Manager: Component tests
- API Implementation: Data fetching
Examples
// src/components/ApplicationCard/ApplicationCard.tsx
import { FC } from 'react'
import { Link } from 'react-router-dom'
import { Application } from '@/types'
import { StatusBadge } from '../StatusBadge'
import { ProgressBar } from '../ProgressBar'
import { formatDate, daysUntil } from '@/utils/date'
interface ApplicationCardProps {
application: Application
variant?: 'full' | 'compact'
}
export const ApplicationCard: FC<ApplicationCardProps> = ({
application,
variant = 'full'
}) => {
const { program, status, progress, submittedAt } = application
const daysLeft = program.deadline ? daysUntil(program.deadline) : null
const isUrgent = daysLeft !== null && daysLeft <= 7 && status === 'draft'
if (variant === 'compact') {
return (
<Link
to={`/applications/${application.id}`}
className="flex items-center justify-between p-4 bg-white rounded-lg
shadow-sm hover:shadow-md transition-shadow"
>
<div className="flex items-center gap-3">
<span className="text-2xl">🎓</span>
<div>
<p className="font-medium">{program.name}</p>
<p className="text-sm text-gray-500">{program.university.name}</p>
</div>
</div>
<div className="flex items-center gap-4">
{status === 'draft' && (
<span className="text-sm text-gray-500">{progress}%</span>
)}
<StatusBadge status={status} />
</div>
</Link>
)
}
return (
<div className="bg-white rounded-lg shadow-sm border p-6">
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-3">
<span className="text-3xl">🎓</span>
<div>
<h3 className="font-semibold text-lg">{program.university.name}</h3>
<p className="text-gray-600">{program.name}</p>
<p className="text-sm text-gray-500">{program.degreeLevel}</p>
</div>
</div>
<StatusBadge status={status} />
</div>
{status === 'draft' && (
<div className="mb-4">
<div className="flex justify-between text-sm mb-1">
<span className="text-gray-600">Progress</span>
<span className="font-medium">{progress}%</span>
</div>
<ProgressBar value={progress} />
</div>
)}
<div className="flex items-center justify-between text-sm">
{status === 'draft' && daysLeft !== null && (
<p className={isUrgent ? 'text-red-600 font-medium' : 'text-gray-500'}>
{isUrgent && '⚠️ '}
Deadline: {formatDate(program.deadline)} ({daysLeft} days)
</p>
)}
{status === 'submitted' && submittedAt && (
<p className="text-gray-500">
Submitted: {formatDate(submittedAt)}
</p>
)}
<div className="flex gap-2">
{status === 'draft' ? (
<Link
to={`/applications/${application.id}/edit`}
className="px-4 py-2 bg-blue-600 text-white rounded-lg
hover:bg-blue-700 transition-colors"
>
Continue
</Link>
) : (
<>
<Link
to={`/applications/${application.id}`}
className="px-4 py-2 border border-gray-300 rounded-lg
hover:bg-gray-50 transition-colors"
>
View
</Link>
<Link
to={`/applications/${application.id}/status`}
className="px-4 py-2 border border-gray-300 rounded-lg
hover:bg-gray-50 transition-colors"
>
Track Status
</Link>
</>
)}
</div>
</div>
</div>
)
}
// src/components/ApplicationCard/ApplicationCard.test.tsx
import { render, screen } from '@testing-library/react'
import { BrowserRouter } from 'react-router-dom'
import { ApplicationCard } from './ApplicationCard'
const mockApplication = {
id: 'app-1',
status: 'draft',
progress: 60,
program: {
name: 'MSc Computer Science',
degreeLevel: 'master',
deadline: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
university: { name: 'TU Munich' }
}
}
const renderCard = (props = {}) => {
return render(
<BrowserRouter>
<ApplicationCard application={mockApplication} {...props} />
</BrowserRouter>
)
}
describe('ApplicationCard', () => {
it('renders university and program name', () => {
renderCard()
expect(screen.getByText('TU Munich')).toBeInTheDocument()
expect(screen.getByText('MSc Computer Science')).toBeInTheDocument()
})
it('shows progress bar for draft applications', () => {
renderCard()
expect(screen.getByText('60%')).toBeInTheDocument()
expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '60')
})
it('shows Continue button for draft', () => {
renderCard()
expect(screen.getByRole('link', { name: /continue/i })).toBeInTheDocument()
})
it('shows View and Track buttons for submitted', () => {
renderCard({
application: { ...mockApplication, status: 'submitted', progress: 100 }
})
expect(screen.getByRole('link', { name: /view/i })).toBeInTheDocument()
expect(screen.getByRole('link', { name: /track status/i })).toBeInTheDocument()
})
it('shows urgent warning when deadline is soon', () => {
renderCard()
expect(screen.getByText(/⚠️/)).toBeInTheDocument()
})
})
Validation
- Matches wireframes
- Components tested
- Responsive design
- Accessibility compliant
- State managed properly
Weekly Installs
1
Repository
vihang-hub/inte…rameworkGitHub Stars
1
First Seen
3 days ago
Security Audits
Installed on
amp1
cline1
openclaw1
opencode1
cursor1
kimi-cli1