Factory frontend engineer
Skill nonlinear-xyz/factory-kit/skills/factory-frontend-engineer
Personal Claude Code factory — synthesized cross-build skills, specialist subagents, and slash commands. Phase 0.
npx -y skills add nonlinear-xyz/factory-kit --skill factory-frontend-engineerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when scaffolding any frontend surface that touches lists, forms, drawers, tables, or entity editing. Carries the factory's CRUD conventions — DataTable + drawer with mode union, RowActions primitive, per-context Zod schema variants, query-key naming, format helpers as single source, tier-based heading components, semantic color tokens. Picks Mantine vs shadcn per project criteria. Returns code that fits the house style — not a generic React component.
SKILL.md
6.2 KB, as published. Nobody here has run it
Apply the frontend-engineer specialist workflow. Scaffold UI surfaces grounded in the factory's CRUD conventions, not generic React. Load factory-frontend, factory-design, and factory-stack through the host's skill capability when needed. factory-design owns visual coherence; factory-frontend owns CRUD shape.
How to think (in order)
-
What surface is this? Restate the request in one sentence. Pick one:
- List (queue of entities; filter/sort/paginate)
- Detail (one entity's full view)
- Form (create/edit, including multi-step)
- Dashboard (rollup/chart heavy)
- Hybrid — name it and split into two surfaces if you can.
-
Is this CRUD? If yes, the default shape is DataTable + drawer with mode union. Don't deviate without naming why. The drawer mode is the tagged union
{kind:'closed'}|{kind:'create'}|{kind:'edit'; entity}. The drawer edits only the clicked target; relations open their own drawers. -
Which component library? Check the project's
CLAUDE.mdorDECISIONS.md. If unset:- Mantine when CRUD-heavy / internal tool / form-table dense. Pair with
@mantine/form+schemaResolver. - shadcn when there's a marketing site, design flexibility matters, or Tailwind muscle memory dominates. Pair with
react-hook-form+zodResolver. - Flag the choice in your output if you had to make it.
- Mantine when CRUD-heavy / internal tool / form-table dense. Pair with
-
What primitives already exist? Before writing anything new, check:
src/components/datatable/— DataTable, RowActions, ColumnDef, ValidationRulessrc/lib/format.ts— formatCurrency, formatInteger, formatPercentsrc/components/PageHeader.tsx/CardHeader.tsx/FormSection.tsx— heading tierssrc/features/<sibling>/— peer feature folders for the colocated shape- If a primitive is missing where it should exist, create it first — don't inline. Single source.
-
What's the schema shape? Three Zod variants for a CRUD entity:
- Input schema — server-side strict (UUIDs are UUIDs, no empty strings)
- Form schema — client-side lenient (empty-string defaults,
nullable().or(literal(''))) - Patch schema — partial input for updates (
input.partial()or.pick({})per field) - All three live in
features/<entity>/schema.ts.
-
What's the data path? Default: server action wrapped by TanStack Query mutation. tRPC only if the project already commits to it.
- Action in
features/<entity>/actions.tswith"use server"directive - Hook in
features/<entity>/hooks.tswrapping the action withuseMutation - Query keys:
['entity', 'list', filters]/['entity', 'detail', id] - Invalidate at
['entity']after mutations.
- Action in
-
What conventions must hold?
- Semantic tokens only — consume named tokens (
bg,surface,fg,fg-muted,accent,border, etc. — seefactory-design.md). No hex literals in components, ever. Nodark:variants on individual elements — let CSS-var swap handle modes. - Format helpers from
src/lib/format.ts— never inline currency math. - Tier components — PageHeader / CardHeader / FormSection. Never freeform
<h1>/<h2>. - Empty + error + loading states — required, not optional.
- Feature folders are peers — code in
features/cases/doesn't import fromfeatures/products/. Shared logic goes tolib/.
- Semantic tokens only — consume named tokens (
-
What's the smallest correct change? If asked for a table, build the table — don't redesign the whole space. If a change implies redesigning something else, name it and stop.
Reference: canonical feature folder shape
src/features/<entity>/
├── api.ts # data access (auth-context-agnostic — takes client as arg)
├── actions.ts # server actions ("use server")
├── hooks.ts # TanStack Query wrappers around actions
├── schema.ts # Zod input / form / patch schemas
├── types.ts # types + label maps (STATUS_LABEL, etc.)
├── columns.tsx # makeColumns factory returning ColumnDef[]
├── <Entity>Table.tsx # consumer of DataTable
└── <Entity>Drawer.tsx # consumer of drawer mode union
Output format
When asked to scaffold:
## Restated request
<one sentence>
## Surface + shape
- Surface: <list / detail / form / dashboard>
- Shape: <DataTable + drawer / form-only / etc.>
- Component lib: <Mantine / shadcn — and why if you picked>
## Files to create or modify
<bulleted list with paths>
## Code
<the actual code, organized by file>
## Conventions check
- Format helpers used: <which>
- Semantic colors: <how>
- Empty/loading/error states: <yes/no>
- Cross-feature imports: <none / flagged>
## Open questions
<things the user should confirm>
When asked to review an existing surface, swap "Files to create" → "Issues found" and "Code" → "Suggested diffs."
What you do NOT do
- Don't pick the component library without checking
CLAUDE.md/DECISIONS.mdfirst. Flag if you had to. - Don't inline currency / percent / date math. Use
src/lib/format.ts— create it if missing. - Don't use raw color names (
red,blue). Always semantic tokens. - Don't skip empty / loading / error states. They're required, not optional.
- Don't edit a relation from inside an entity's drawer. Open the relation's own drawer.
- Don't import from a sibling feature folder. Lift to
lib/instead. - Don't build local components first. Extend shared primitives even for single-consumer needs.
When the request is too small for this framework
If the user asks for a one-line color tweak, a copy change, or a single Tailwind class adjustment, just do it directly. The framework is for surface-level or larger.