Use when implementing a frontend task in the Next.js 15 Feature-Based architecture: adding a feature, creating a component, implementing a page, adding a Zustand store, or fixing a frontend bug. Defines technical standards and file structure — NOT the testing methodology (use test-driven-development for TDD discipline) or execution framework (use executing-plans for task sequencing).
How this skill is triggered — by the user, by Claude, or both
Slash command
/fullstack-project-skills:frontend-feature-devThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implements a single task (new feature, new component, new page, bug fix) within the Next.js Feature-Based architecture. Every task ends with updated documentation, passing tests, and updated Storybook stories.
Implements a single task (new feature, new component, new page, bug fix) within the Next.js Feature-Based architecture. Every task ends with updated documentation, passing tests, and updated Storybook stories.
**`app/` is orchestration only — no business logic lives there.** Pages (`page.tsx`) and layouts (`layout.tsx`) may only: fetch data (Server Components), compose feature components, and pass data as props. Business logic, state, and UI implementation belong exclusively in `src/features/[feature]/`. Never add `'use client'` to `app/` files without an ADR.Using useEffect + fetch as the primary data fetching pattern when a Server Component can fetch the data at render time. Server Components are the default — use them. Client Components ('use client') are for interactivity, subscriptions, and browser APIs only.
CLAUDE.md — confirm feature exists in the Module/Feature MapCLAUDE.md — understand its current state, exports, dependenciesnpm run build — no TypeScript errors, no lint errorsnpm run test — all tests greendocker compose build — Docker image still buildsCLAUDE.mdCLAUDE.md Module/Feature Mapdigraph frontend_feature {
rankdir=TB;
node [shape=box, style=rounded];
A [label="Read CLAUDE.md\n(root + feature)"];
B [label="Determine Level\n& Component Boundary"];
C [label="Server or\nClient Component?", shape=diamond];
D [label="Async Server Component\nFetch in service fn"];
E [label="Client Component\n'use client'"];
F [label="shadcn/ui\ncomponent exists?", shape=diamond];
G [label="npx shadcn@latest add\n[component]"];
H [label="Build custom\non shadcn base"];
I [label="Zustand store\nneeded?", shape=diamond];
J [label="Feature store\nvs global store"];
K [label="Implement + Zod\nvalidation"];
L [label="Tests (Vitest+RTL)\nStorybook stories"];
M [label="npm run build\nnpm run test\ndocker compose build"];
N [label="Update CLAUDE.md\n& Feature Map"];
O [label="Commit"];
A -> B -> C;
C -> D [label="data fetching"];
C -> E [label="interactive"];
D -> F; E -> F;
F -> G [label="yes"];
F -> H [label="no"];
G -> I; H -> I;
I -> J [label="yes"];
I -> K [label="no"];
J -> K -> L -> M -> N -> O;
}
Read root CLAUDE.md and the target feature's CLAUDE.md. If the feature doesn't exist, create its directory with its CLAUDE.md first.
| Level | Structure |
|---|---|
| 1 | components/, exports/ (if consumed by others). No services/, no state. |
| 2 | components/, services/, hooks/, stores/ (if needed), schemas/, __tests__/, stories/, exports/ |
| 3 | Level 2 + multiple services, complex stores, third-party adapters |
Default: Server Component. Use async/await, fetch data in services/ functions, pass results as props.
// features/products/services/get-products.ts
export async function getProducts(): Promise<Product[]> {
const res = await fetch('/api/products', { cache: 'no-store' });
const data: unknown = await res.json();
return ProductListSchema.parse(data); // Always validate with Zod
}
Switch to Client Component ONLY when you need:
window, localStorage)useState, useEffect, custom hooks)Never put 'use client' at the feature root — push it down to the leaf component that actually needs it.
Every response from an external API (backend or third-party) must be validated with a Zod schema. No raw response.json() cast to a TypeScript type.
// features/products/schemas/product.schema.ts
import { z } from 'zod';
export const ProductSchema = z.object({
id: z.number(),
name: z.string().min(1),
price: z.number().positive(),
});
export type Product = z.infer<typeof ProductSchema>;
Before building a custom component, check if shadcn/ui has one: Button, Input, Card, Dialog, Form, Select, Table, Tabs, Sheet, etc. Install with:
npx shadcn@latest add [component-name]
Components install to src/shared/ui/ (configured in components.json). Customize via Tailwind utility classes and CSS variables from shared/styles/globals.css — never hardcode color or spacing values.
features/[feature]/stores/infrastructure/stores/useStore((s) => s.field) — never subscribe to the whole storeexports/server.ts or exports/client.ts — never from internal pathsindex.ts files that mix Server and Client components// features/auth/components/__tests__/LoginForm.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LoginForm } from '../LoginForm';
it('shows error when email is invalid', async () => {
render(<LoginForm />);
await userEvent.type(screen.getByLabelText('Email'), 'not-an-email');
await userEvent.click(screen.getByRole('button', { name: /sign in/i }));
expect(screen.getByText(/invalid email/i)).toBeInTheDocument();
});
Test: Client Components, custom hooks, Zustand stores, Zod schemas.
Do NOT test: Server Components directly (test their services/ functions instead), real API calls.
Every new or modified UI component needs a story. Storybook is configured with experimentalRSC: true so Next.js-specific hooks work without extra mocking.
// features/products/components/stories/ProductCard.stories.tsx
import type { Meta, StoryObj } from '@storybook/nextjs';
import { ProductCard } from '../ProductCard';
const meta: Meta<typeof ProductCard> = { component: ProductCard };
export default meta;
export const Default: StoryObj<typeof ProductCard> = {
args: { name: 'Widget', price: 29.99 },
};
npm run build # TypeScript errors + lint violations fail the build
npm run test # All Vitest tests green
docker compose build # Docker image must still compile
npm run storybook # Storybook starts without errors (manual check)
Documentation (ALWAYS update before closing the task):
src/features/[feature]/CLAUDE.md — update Purpose, Components, State, API Consumption, Exports sectionsCLAUDE.md Module/Feature Map — update Estado and any endpoint changesdocs/ADR/NNN-title.md — if a significant technical decision was made (e.g., added a third-party library, changed state strategy)'use client' only when unavoidableapp/ orchestrates, features implement — no business logic in pages or layoutsThis skill activates during the frontend implementation phase (within each plan task). Superpowers handles the TDD methodology (test-driven-development) and the execution framework (executing-plans). This skill handles the technical standards: feature-based structure, Server/Client boundary, shadcn/ui, Zustand, Zod, Vitest+RTL, Storybook, and Docker.
When both are active:
If Superpowers is not installed, this skill works independently including its own testing instructions (without strict TDD enforcement).
Both skills may activate when building UI components or pages.
The frontend-design skill handles visual aesthetics: typography, color, motion, and spatial composition.
This skill handles architecture and technical standards: file structure, Server/Client boundary, state management, testing, and Docker.
When both are active, they complement each other — frontend-design guides how things look, this skill guides how things are structured and tested.
npx claudepluginhub juan-apscreativas/fullstack-project-skills --plugin fullstack-project-skillsBuilds React/Next.js web frontends: components, pages, design systems, state management, typed API clients. Uses structured phases and engagement modes.
Builds React 19 components and Next.js 15 apps with responsive layouts, client-side state management using Zustand, and server components. Optimizes performance, accessibility, and data fetching.
Enforces Suspense-first data fetching, feature-based code organization, and strict TypeScript discipline for React applications. Use when creating components, pages, adding features, or fetching data.