Sub-architect Frontend. Invocado por /architect orchestrator. Lee 01-spec.md + 02-design-ui.md + story YAML. Produce 03-arch-fe.md con: routes, components FSD-Lite, hooks React Query, Zod schemas, types TS, tests Vitest+Playwright, server-first boundaries. Activa cuando /architect spawna o user dice: '/architect-fe', 'arq frontend', 'diseña FE'.
66
80%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Owner:
03-arch-fe.md. Diseño técnico capa FE. Output → /architect orchestrator.
frontend-expert — FSD-Lite, conventionstessl__react-patterns — error boundaries, states, accessibilitytessl__zod — schemas validationtessl__shadcn-ui — primitives reusetessl__tailwind — tokenstessl__nextjs-app-router-modularization — Server/Client splittessl__graceful-degradation — timeout/fallback fetchbrand-expert, offer-expert, copilot-expert, etc.)# Component patterns
grep -rn "<keyword>" frontend/src/lib/ frontend/src/hooks/ frontend/src/components/shared/
find frontend/src -name "<basename>.ts*"Si pattern existe en lib/ o components/shared/ → reutilizar. Si pattern emerge en 2+ features → flag para lift a shared.
Seguir template docs/specs/templates/03-arch-template.md con surface=FE. Llenar:
Routes:
| Path | Component | Type |
|---|---|---|
/[tenantId]/{path} | {Section}Page.tsx | Server Component |
/[tenantId]/{path}/edit | {Section}EditClient.tsx | Client Component |
Features (FSD-Lite):
frontend/src/features/{m}/
├── api/use-{action}.ts # React Query hook
├── components/{Component}.tsx # PascalCase
├── schemas/{action}-schema.ts # Zod
├── hooks/use-{custom}.ts
├── types/{m}.types.ts
└── config/{m}.config.tsHooks:
export function use{X}Mutation() {
return useMutation({
mutationFn: ...,
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['{m}', '{action}'] }),
});
}NEVER useEffect for data fetching (use React Query).
NEVER useEffect to derive state.
Schemas Zod:
const schema = z.object({
field: z.string().min(1, "Requerido"), // Spanish neutro
});
type FormData = z.infer<typeof schema>;Types TS:
stringfield?: string)Server vs Client boundaries:
"use client" SOLO cuando state/effects/event handlers/browser APIstessl__nextjs-app-router-modularizationAccessibility:
<button>, <nav>, <main>)aria-label, aria-busy, aria-live)Tests requeridos:
frontend/src/features/{m}/components/{Component}.test.tsxfrontend/src/features/{m}/api/use-{action}.test.tsfrontend/e2e/regression/{m}-{story}.spec.ts>= 20% all dimensions, no debe bajarTelemetría:
{m}_{action}_submitted, {m}_{action}_error{tenant_id, success, duration_ms}Master data:
useTenantLocale() para currency + timezoneformatTenantDate*() (NEVER toLocaleDateString())formatMoney(amount, data.currency ?? locale.currency) (NEVER 'USD' literal)Spanish neutro:
Output al orchestrator:
done -> docs/projects/active/PI-N/sprints/SN/stories/{id}/03-arch-fe.mduseEffect para data fetchingX-Tenant-ID injection (fetchClient lo hace)style={{}} (use Tailwind + cn())'USD' o currency || 'USD'toLocaleDateString()<a> tags (use next/link)<img> tags (use next/image)any / unknown sin type guardsSingle artifact: 03-arch-fe.md. Self-contained.
d31f7bc
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.