home / skills / srbhr / resume-matcher / frontend-dev

frontend-dev skill

/.agents/skills/frontend-dev

This skill helps you create and modify Next.js pages, React components, and Tailwind styles following Swiss International Style.

npx playbooks add skill srbhr/resume-matcher --skill frontend-dev

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.5 KB
---
name: frontend-dev
description: |
  Frontend development agent for Resume Matcher. Handles Next.js pages, React components, Tailwind CSS with Swiss International Style, API integration, hooks, and i18n. Use when creating or modifying frontend code.
metadata:
  author: resume-matcher
  version: "1.0.0"
allowed-tools: Bash(npm:*) Bash(npx:*) Read
---

# Frontend Development Agent

> Use when creating or modifying Next.js pages, React components, Tailwind CSS styles, API integration, hooks, or i18n.

## Before Writing Code

1. Read `docs/agent/architecture/frontend-workflow.md` for user flow
2. Read `docs/agent/design/style-guide.md` for Swiss International Style (**REQUIRED**)
3. Read `docs/agent/coding-standards.md` for conventions
4. Check existing components in `apps/frontend/components/` for patterns

## Non-Negotiable Rules

1. **Swiss International Style** - ALL UI changes must follow it
2. **`rounded-none`** everywhere - no rounded corners, ever
3. **Hard shadows** - `shadow-[4px_4px_0px_0px_#000000]`, never soft shadows
4. **Run `npm run lint`** before committing
5. **Run `npm run format`** before committing
6. **Enter key handling** on all textareas

## Project Structure

```
apps/frontend/
├── app/                 # Next.js pages
│   ├── dashboard/       # Main dashboard
│   ├── builder/         # Resume builder
│   ├── tailor/          # AI tailoring
│   ├── print/           # PDF print view
│   └── settings/        # User settings
├── components/          # Reusable UI components
├── lib/                 # API client, utilities, i18n
├── hooks/               # Custom React hooks
└── messages/            # i18n translations (en, es, zh, ja)
```

## Swiss International Style Quick Reference

| Element | Value |
|---------|-------|
| Canvas bg | `#F0F0E8` / `bg-[#F0F0E8]` |
| Ink text | `#000000` |
| Hyper Blue | `#1D4ED8` / `text-blue-700` |
| Signal Green | `#15803D` / `text-green-700` |
| Alert Red | `#DC2626` / `text-red-600` |
| Headers | `font-serif` |
| Body | `font-sans` |
| Labels | `font-mono text-sm uppercase tracking-wider` |
| Borders | `rounded-none border-2 border-black` |
| Shadows | `shadow-[4px_4px_0px_0px_#000000]` |
| Hover | `hover:translate-y-[1px] hover:translate-x-[1px] hover:shadow-none` |

### Anti-Patterns (NEVER use)

- `rounded-*` (except `rounded-none`)
- Gradients or blur shadows
- Colors outside the palette
- Pastel or soft colors
- Decorative icons without function

## Patterns

### New Component

```tsx
'use client';

interface MyComponentProps {
  title: string;
  onAction: () => void;
}

export function MyComponent({ title, onAction }: MyComponentProps) {
  return (
    <div className="bg-white border-2 border-black shadow-[4px_4px_0px_0px_#000000] p-6">
      <h3 className="font-serif text-xl mb-4">{title}</h3>
      <button
        onClick={onAction}
        className="rounded-none border-2 border-black px-4 py-2 bg-blue-700 text-white shadow-[2px_2px_0px_0px_#000000] hover:translate-y-[1px] hover:translate-x-[1px] hover:shadow-none transition-all"
      >
        Action
      </button>
    </div>
  );
}
```

### Textarea (Enter key fix)

```tsx
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
  if (e.key === 'Enter') e.stopPropagation();
};

<textarea
  onKeyDown={handleKeyDown}
  className="w-full rounded-none border-2 border-black p-3 font-sans"
/>
```

### Bundle Optimization

```tsx
// Direct icon import (NOT barrel import)
import FileText from 'lucide-react/dist/esm/icons/file-text';

// Dynamic import for heavy components
import dynamic from 'next/dynamic';
const PDFViewer = dynamic(() => import('./PDFViewer'), { ssr: false });
```

### API Integration

```tsx
import { api } from '@/lib/api';

async function loadResumes() {
  // Use Promise.all for independent fetches
  const [resumes, jobs] = await Promise.all([
    api.get('/api/v1/resumes'),
    api.get('/api/v1/jobs'),
  ]);
  return { resumes, jobs };
}
```

### i18n

```tsx
import { useTranslations } from '@/lib/i18n';

export function MyComponent() {
  const { t } = useTranslations();
  return <h1>{t('dashboard.title')}</h1>;
}
```

## Checklist Before Committing

- [ ] `npm run lint` passes
- [ ] `npm run format` run
- [ ] `rounded-none` on all elements
- [ ] Hard shadows (no soft shadows)
- [ ] Swiss color palette only
- [ ] Correct typography (serif headers, mono labels, sans body)
- [ ] Textareas have Enter key handler
- [ ] Icons imported directly (not barrel)
- [ ] Heavy components use `next/dynamic`
- [ ] Independent fetches use `Promise.all()`

Overview

This skill is a frontend development agent tailored for the Resume Matcher app. It guides creation and modification of Next.js pages, React components, Tailwind CSS styled in Swiss International Style, API integration, hooks, and i18n. Use it to implement consistent UI, performance-minded patterns, and accessibility-minded behavior for resume tools.

How this skill works

The agent inspects project structure under apps/frontend and follows the provided workflow, style guide, and coding standards. It generates or updates components, pages, hooks, and API clients while enforcing Swiss International Style rules (colors, typography, borders, hard shadows) and project conventions like direct icon imports and dynamic loading for heavy pieces. It also validates textarea Enter handling, linting, and formatting requirements before finalizing changes.

When to use it

  • Creating new Next.js pages (app/) for dashboard, builder, tailor, print, or settings
  • Building or refactoring reusable React components in components/
  • Applying Swiss International Style and Tailwind classes consistently
  • Integrating with backend APIs via lib/api and optimizing fetches with Promise.all
  • Adding i18n strings or using useTranslations hooks
  • Implementing or updating custom hooks in hooks/

Best practices

  • Follow Swiss International Style: palette, serif headers, sans body, mono labels, no rounded corners
  • Use rounded-none everywhere and apply hard shadow class shadow-[4px_4px_0px_0px_#000000]
  • Import icons directly from their ESM path and use next/dynamic for heavy components
  • Use Promise.all for independent API calls and centralize API client usage in lib/api
  • Ensure all textareas stop Enter key propagation and add tests or manual checks for keyboard behavior
  • Run npm run lint and npm run format before committing; keep commits small and focused

Example use cases

  • Create a resume preview component that matches the Swiss palette and uses hard shadows and border-2 styles
  • Add an AI tailoring page under tailor/ with dynamic import for heavy visualization components
  • Refactor a form component to include Enter key handling on textareas and consistent typography classes
  • Integrate job and resume fetches using Promise.all and the central api client
  • Add i18n translations and consume them via useTranslations for multilingual UI

FAQ

What if a design request uses rounded corners or custom gradients?

Decline or refactor to match the Swiss International Style: replace rounded corners with rounded-none and remove gradients, using the approved palette and hard shadows instead.

How should I import icons or heavy libraries?

Import icons directly from their ESM path (avoid barrel imports) and load heavy components with next/dynamic and ssr: false when appropriate.