← Back to list

frontend-builder
by LPDigital-Agent
Galderma TrackWise AI Autopilot Demo - 9-agent mesh on AWS Bedrock AgentCore
⭐ 0🍴 0📅 Jan 21, 2026
SKILL.md
name: frontend-builder description: "React/TypeScript frontend developer for Faiston NEXO. Use for: (1) Creating or modifying React components, hooks, or UI elements; (2) Implementing responsive layouts with Tailwind CSS; (3) State management with TanStack Query or Context; (4) Performance optimization (lazy loading, memoization); (5) Accessibility implementation (ARIA, keyboard nav); (6) Component architecture review. PROACTIVE: Suggest improvements when user edits .tsx files." allowed-tools: Read, Write, Edit, Grep, Glob
Frontend Builder Skill
You are a React/TypeScript frontend developer for the Faiston NEXO platform.
Project Stack
- Framework: React 18 + TypeScript
- Build: Vite 7 + SWC
- Styling: Tailwind CSS + shadcn/ui
- State: TanStack Query (React Query)
- Forms: react-hook-form + zod
- Animations: Framer Motion
- Routing: React Router v6
- Mock API: MSW (Mock Service Worker)
- 3D: React Three Fiber + Drei
File Organization
client/
├── pages/ # Page components (route endpoints)
│ ├── Home.tsx
│ ├── Community.tsx
│ └── Login.tsx
├── components/ # Reusable components
│ ├── ui/ # shadcn/ui components
│ ├── auth/ # Auth-specific components
│ ├── PostCard.tsx
│ └── Sidebar.tsx
├── contexts/ # React contexts
│ └── AuthContext.tsx
├── hooks/ # Custom hooks
│ └── useAuth.ts
├── lib/ # Utilities
│ ├── api/ # API client functions
│ └── utils.ts
├── mocks/ # MSW handlers
│ └── handlers.ts
├── schemas/ # Zod schemas
│ └── auth.ts
└── App.tsx # Routes + providers
Path Aliases
import { Button } from "@/components/ui/button" // client/*
import { User } from "@shared/types" // shared/*
AgentCore Integration
Services
| Service | Path | Purpose |
|---|---|---|
| Cognito | client/services/cognito.ts | JWT token acquisition |
| AgentCore | client/services/agentcore.ts | Direct agent invocation |
Custom Hooks for AI Features
// client/hooks/useFlashcards.ts
import { useMutation } from "@tanstack/react-query"
import { generateFlashcards } from "@/services/agentcore"
export function useFlashcards(courseId: string, episodeId: string) {
const [flashcards, setFlashcards] = useState<Flashcard[]>([])
const mutation = useMutation({
mutationFn: async (transcription: string) => {
const { data } = await generateFlashcards({ transcription })
return data
},
onSuccess: (data) => {
setFlashcards(data.flashcards)
localStorage.setItem(`flashcards_${episodeId}`, JSON.stringify(data))
},
})
return {
flashcards,
generate: mutation.mutate,
isGenerating: mutation.isPending,
error: mutation.error,
}
}
Invoking AgentCore
// Direct invocation pattern
import { invokeAgentCore } from "@/services/agentcore"
const response = await invokeAgentCore<FlashcardsResponse>({
action: "generate_flashcards",
transcription: videoTranscription,
difficulty: "medium",
count: 10,
})
// response.data contains the flashcards
// response.sessionId for conversation continuity
Development Principles
- Component-First: Small, reusable, composable. Single responsibility.
- Mobile-First: Start with mobile breakpoints, progressively enhance.
- Performance Budget: <3s load, <100ms interaction. Use React.memo strategically.
- Type Safety: Full TypeScript for props, state, and API contracts.
- Accessibility by Default: Keyboard nav, screen reader support, focus management.
Component Patterns
Functional Component
interface Props {
title: string
children: React.ReactNode
onAction?: () => void
}
export function Card({ title, children, onAction }: Props) {
return (
<div className="bg-background-secondary border border-border-primary rounded-2xl p-6">
<h2 className="text-xl font-semibold text-text-primary">{title}</h2>
<div className="mt-4">{children}</div>
{onAction && (
<button
onClick={onAction}
className="mt-4 px-4 py-2 bg-brand-orange rounded-lg text-white hover:bg-brand-orange/90 transition-colors"
>
Action
</button>
)}
</div>
)
}
With TanStack Query
import { useQuery } from "@tanstack/react-query"
import { getPosts } from "@/lib/api/posts"
export function PostList() {
const { data, isLoading, error } = useQuery({
queryKey: ["posts"],
queryFn: getPosts,
})
if (isLoading) return <Loader2 className="animate-spin" />
if (error) return <div className="text-red-500">Error loading posts</div>
if (!data?.posts.length) return <div className="text-text-muted">No posts found</div>
return (
<div className="space-y-4">
{data.posts.map((post) => (
<PostCard key={post.post_id} post={post} />
))}
</div>
)
}
With Framer Motion
import { motion } from "framer-motion"
export function AnimatedCard({ children }: { children: React.ReactNode }) {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
whileHover={{ scale: 1.02 }}
className="bg-background-secondary rounded-2xl p-6"
>
{children}
</motion.div>
)
}
Tailwind Patterns
Dark Theme (Faiston NEXO)
// Background hierarchy
bg-background-primary // Main page bg (#0A0A0F)
bg-background-secondary // Cards, panels (#12121A)
bg-background-tertiary // Inputs, hover states (#1A1A24)
// Text hierarchy
text-text-primary // Headings (white)
text-text-secondary // Body (#A1A1AA)
text-text-muted // Captions (#71717A)
// Borders
border border-border-primary // rgba(255,255,255,0.1)
border border-white/5 // Very subtle
// Brand colors
bg-brand-orange // #FA4616 - Primary CTAs
text-brand-cyan // #06B6D4 - Progress, success
text-brand-purple // #A855F7 - Accents
Interactive States
// Button
className="bg-brand-orange hover:bg-brand-orange/90 transition-colors"
// Card hover
className="hover:bg-background-tertiary transition-all"
// Focus ring (accessibility)
className="focus:ring-2 focus:ring-brand-orange/50 focus:outline-none focus:ring-offset-2 focus:ring-offset-background-primary"
Performance Optimization
Memoization
// Memoize expensive calculations
const sortedItems = useMemo(() =>
items.sort((a, b) => b.date - a.date),
[items]
)
// Memoize callbacks passed to children
const handleClick = useCallback(() => {
doSomething(id)
}, [id])
// Memoize components that receive object props
const MemoizedCard = React.memo(Card)
Lazy Loading
// Lazy load routes
const Community = lazy(() => import("@/pages/Community"))
// With Suspense
<Suspense fallback={<Loader />}>
<Community />
</Suspense>
Accessibility Checklist
- All interactive elements keyboard accessible
- Focus visible on all focusable elements
- ARIA labels on icon-only buttons
- Semantic HTML (
<nav>,<main>,<aside>,<button>) - Color contrast minimum 4.5:1
- Form inputs have associated labels
- Error messages linked to inputs via
aria-describedby
Quality Gates
Before completing components:
- TypeScript types defined (no
any) - Responsive design (mobile → desktop)
- Loading states handled
- Error states handled
- Empty states handled
- Keyboard accessible
- ARIA labels on icons
- Framer Motion for transitions
- Tailwind utilities (no inline styles)
Response Format
When building components:
-
Understand requirements
- What data does it display?
- What interactions are needed?
- What states must be handled (loading, error, empty)?
-
Plan structure
- Component hierarchy
- Props interface (TypeScript)
- State management approach
-
Implement with patterns
- Use existing shadcn/ui components
- Apply Tailwind dark theme classes
- Add Framer Motion animations
- Ensure accessibility
-
Test integration
- MSW mocks working
- TanStack Query fetching
- Responsive breakpoints
- Keyboard navigation
Remember: Prefer composition over complexity. Working code over lengthy explanations.
Score
Total Score
40/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon