public-rules
Public engineering rules from Fabrica for coding agents, with versioned groups projects can adopt and customize.
Go techs/go
Add operation and identifier context to errors at boundariesMEDIUM
1.0.0 techs/go/errors-include-useful-diagnostic-data
Comment struct fields whose meaning the type does not showMEDIUM
1.0.0 techs/go/comment-non-obvious-struct-fields
Expose error identity only for contract errorsMEDIUM
1.0.0 techs/go/errors-use-contract-errors-deliberately
Give text and its parsed form one ownerMEDIUM
1.0.0 techs/go/one-owner-for-text-and-parsed-form
Separate package documentation from file headersLOW
1.0.0 techs/go/comments-package-doc-vs-file-header
Goose techs/goose
Keep the SQL migration directory for migration files onlyMEDIUM
1.0.0 techs/goose/migrations-directory-contains-only-sql
JavaScript techs/javascript
Avoid layout thrashingMEDIUM
1.0.0 techs/javascript/avoid-layout-thrashing
Await only on paths that need the resultMEDIUM
1.0.0 techs/javascript/await-only-on-paths-that-need-the-result
Defer non-critical browser work to idle timeMEDIUM
1.0.0 techs/javascript/defer-non-critical-work-to-idle-time
Keep dynamic import and file paths statically analyzableMEDIUM
1.0.0 techs/javascript/keep-import-and-file-paths-analyzable
Mark scroll-related listeners passive when they never cancel scrollingMEDIUM
1.0.0 techs/javascript/use-passive-scroll-and-touch-listeners
Start independent asynchronous work concurrentlyHIGH
1.0.0 techs/javascript/start-independent-async-work-concurrently
Version and minimize data in browser storageMEDIUM
1.0.0 techs/javascript/version-and-minimize-browser-storage
Playwright techs/playwright
Scope locators by test id, then select controls by role and nameMEDIUM
1.0.0 techs/playwright/domain-scope-and-user-facing-locators
Synchronize with auto-waiting actions and web-first assertionsMEDIUM-HIGH
1.0.0 techs/playwright/auto-waiting-actions-and-web-first-assertions
React techs/react
Accept ref as a prop in React 19LOW
1.0.0 techs/react/react19-no-forwardref
Authenticate and authorize inside every Server ActionCRITICAL
1.0.0 techs/react/server-auth-actions
Avoid copying props to stateHIGH
1.0.0 techs/react/official-avoid-copying-props-to-state
Avoid loading large barrel filesMEDIUM
1.0.0 techs/react/bundle-barrel-imports
Avoid unnecessary EffectsHIGH
1.0.0 techs/react/official-avoid-unnecessary-effects
Build complex components from composable partsMEDIUM
1.0.0 techs/react/architecture-compound-components
Compose independent server data fetches as siblingsHIGH
1.0.0 techs/react/server-parallel-fetching
Create explicit component variants instead of boolean mode propsMEDIUM
1.0.0 techs/react/architecture-explicit-variants
Deduplicate per-request server work with cacheMEDIUM
1.0.0 techs/react/server-cache-react
Do not define components inside componentsHIGH
1.0.0 techs/react/rerender-no-inline-components
Follow the Rules of HooksHIGH
1.0.0 techs/react/official-follow-rules-of-hooks
Give every interactive element a role and an accessible nameHIGH
1.0.0 techs/react/accessibility-roles-and-names
Give repeated and persistent surfaces stable test idsMEDIUM
1.0.0 techs/react/testing-ship-stable-e2e-scope-test-ids
Hint critical resources with React DOM resource APIsMEDIUM
1.0.0 techs/react/rendering-resource-hints
Initialize expensive state lazilyLOW-MEDIUM
1.0.0 techs/react/rerender-lazy-state-init
Keep components and Hooks pureHIGH
1.0.0 techs/react/official-keep-components-and-hooks-pure
Keep input responsive by marking non-urgent updatesMEDIUM
1.0.0 techs/react/rerender-mark-non-urgent-updates
Keep non-critical scripts off the critical pathMEDIUM-HIGH
1.0.0 techs/react/bundle-defer-non-critical-scripts
Keep request data out of shared module stateHIGH
1.0.0 techs/react/server-no-shared-module-state
Keep values that do not affect rendering in refsMEDIUM
1.0.0 techs/react/rerender-use-ref-transient-values
Lift shared component state into a provider behind an interfaceMEDIUM
1.0.0 techs/react/state-lift-shared-state-into-providers
Load heavy optional code on demandHIGH
1.0.0 techs/react/bundle-load-heavy-code-on-demand
Memoize deliberatelyMEDIUM
1.0.0 techs/react/rerender-memoize-deliberately
Name Effect and non-trivial Hook callbacksLOW
1.0.0 techs/react/hooks-name-callbacks
Name generic components by capability, not by first callerMEDIUM
1.0.0 techs/react/generic-components-by-capability
Pass only the data Client Components useMEDIUM
1.0.0 techs/react/server-minimize-serialized-props
Read the latest callbacks in Effects without resubscribingMEDIUM
1.0.0 techs/react/effects-read-latest-values-without-resubscribing
Render client-only preferences without a flash or hydration errorMEDIUM
1.0.0 techs/react/rendering-hydration-no-flicker
Reuse request-independent server data across requestsMEDIUM
1.0.0 techs/react/server-reuse-request-independent-data
Run app-wide initialization once per app loadLOW-MEDIUM
1.0.0 techs/react/advanced-init-once
Run post-response work after the responseMEDIUM
1.0.0 techs/react/server-after-nonblocking
Share client data requests through a caching data layerMEDIUM-HIGH
1.0.0 techs/react/client-share-data-requests
Skip off-screen rendering work in long listsMEDIUM
1.0.0 techs/react/rendering-content-visibility
Stream slow data behind Suspense boundariesMEDIUM-HIGH
1.0.0 techs/react/async-suspense-boundaries
Subscribe to and depend on only the values you useMEDIUM
1.0.0 techs/react/rerender-depend-on-narrow-values
Suppress only expected hydration mismatchesLOW-MEDIUM
1.0.0 techs/react/rendering-hydration-suppress-warning
Use a boolean condition for conditional renderingLOW-MEDIUM
1.0.0 techs/react/rendering-conditional-render
Use Activity to hide UI that should keep its stateMEDIUM
1.0.0 techs/react/rendering-activity
Use functional updates when new state depends on old stateMEDIUM
1.0.0 techs/react/rerender-functional-setstate
TanStack Query techs/tanstack-query
Define hierarchical query keys and options in factoriesMEDIUM
1.0.0 techs/tanstack-query/qk-factory-pattern
Derive component views of query data with a stable selectLOW-MEDIUM
1.0.0 techs/tanstack-query/perf-select-transform
Derive infinite query page params from the server's responseMEDIUM
1.0.0 techs/tanstack-query/inf-page-params
Fetch a dynamic set of queries with useQueriesMEDIUM
1.0.0 techs/tanstack-query/parallel-use-queries
Invalidate or update every query a mutation changesHIGH
1.0.0 techs/tanstack-query/mut-invalidate-queries
Key each query by every input it usesHIGH
1.0.0 techs/tanstack-query/qk-include-dependencies
Make offline behavior explicitLOW-MEDIUM
1.0.0 techs/tanstack-query/offline-behavior
Make optimistic updates reversible, and decide them onceMEDIUM-HIGH
1.0.0 techs/tanstack-query/mut-optimistic-updates
Pass the query's AbortSignal to the requestMEDIUM
1.0.0 techs/tanstack-query/query-cancellation
Prefetch likely next data on user intentMEDIUM
1.0.0 techs/tanstack-query/pf-intent-prefetch
Prefetch on the server and hydrate the query cacheMEDIUM-HIGH
1.0.0 techs/tanstack-query/ssr-dehydration
Read mutation state from other components with useMutationStateLOW-MEDIUM
1.0.0 techs/tanstack-query/mut-mutation-state
Reset query errors when an error boundary retriesHIGH
1.0.0 techs/tanstack-query/err-error-boundaries
Set staleTime from how fast data changesMEDIUM
1.0.0 techs/tanstack-query/cache-stale-time
Use initialData only for complete dataMEDIUM
1.0.0 techs/tanstack-query/cache-placeholder-vs-initial
TanStack Router techs/tanstack-router
Load route data in loaders, in parallelHIGH
1.0.0 techs/tanstack-router/load-use-loaders
Mask modal routes with the resource's canonical URLLOW
1.0.0 techs/tanstack-router/nav-route-masks
Provide shared dependencies through typed router contextHIGH
1.0.0 techs/tanstack-router/ctx-router-context
Register the router and read route data through typed route APIsMEDIUM
1.0.0 techs/tanstack-router/ts-route-type-inference
Set app-wide navigation behavior in router defaultsMEDIUM
1.0.0 techs/tanstack-router/router-default-options
Split route components out of the main bundleMEDIUM
1.0.0 techs/tanstack-router/split-route-code
Throw notFound for missing resources and render it with notFoundComponentMEDIUM-HIGH
1.0.0 techs/tanstack-router/err-not-found
Use Link for navigation users can open, and redirect in the routerMEDIUM
1.0.0 techs/tanstack-router/nav-link-component
Validate search params with defaults at the routeHIGH
1.0.0 techs/tanstack-router/search-validation
With TanStack Query, load route data into the Query cacheHIGH
1.0.0 techs/tanstack-router/load-ensure-query-data
TypeScript techs/typescript
Annotate types at module boundaries and where they narrowMEDIUM
1.0.0 techs/typescript/annotate-types-at-boundaries
Avoid silencing the type checkerHIGH
1.0.0 techs/typescript/avoid-silencing-the-type-checker
Comment the role, the result, and the hidden constraintMEDIUM
1.0.0 techs/typescript/comment-role-result-and-constraints
Declare constants with as const, and satisfies when a type existsMEDIUM
1.0.0 techs/typescript/declare-constants-with-as-const
Distinguish null from undefinedLOW
1.0.0 techs/typescript/distinguish-null-from-undefined
Follow consistent naming conventionsLOW
1.0.0 techs/typescript/use-consistent-naming
Generate service types from their contractsHIGH
1.0.0 techs/typescript/generate-service-types-from-contracts
Import types with import typeMEDIUM
1.0.0 techs/typescript/separate-type-imports
Make properties and parameters required, and name themMEDIUM-HIGH
1.0.0 techs/typescript/require-properties-and-name-parameters
Model distinct states as discriminated unionsMEDIUM
1.0.0 techs/typescript/model-variants-as-discriminated-unions
Narrow unknown values before useHIGH
1.0.0 techs/typescript/narrow-unknown-values
Prefer literal unions over enumsMEDIUM
1.0.0 techs/typescript/prefer-literal-unions-over-enums
Prefer type aliases over interfacesLOW
1.0.0 techs/typescript/prefer-type-aliases
Preserve caller-owned dataMEDIUM
1.0.0 techs/typescript/preserve-caller-owned-data
Use Boolean() for explicit boolean coercionLOW
1.0.0 techs/typescript/use-boolean-for-explicit-boolean-coercion
Use named exportsLOW
1.0.0 techs/typescript/use-named-exports
Use one array type syntaxLOW
1.0.0 techs/typescript/use-generic-array-types
Use predictable file namesLOW
1.0.0 techs/typescript/use-predictable-file-names
Use template literal types for patterned stringsLOW-MEDIUM
1.0.0 techs/typescript/use-template-literal-types-for-patterned-strings
Zustand techs/zustand
Create stores once, outside renderHIGH
1.0.0 techs/zustand/create-stores-at-module-scope
Define typed state and named actionsMEDIUM-HIGH
1.0.0 techs/zustand/define-typed-state-and-named-actions
Keep each store focused on one domainMEDIUM
1.0.0 techs/zustand/keep-stores-domain-focused
Keep store state serializableMEDIUM
1.0.0 techs/zustand/keep-store-state-serializable
Persist only safe, versioned stateHIGH
1.0.0 techs/zustand/persist-only-safe-versioned-state
Rehydrate persisted stores after React hydrationHIGH
1.0.0 techs/zustand/rehydrate-persisted-stores-after-hydration
Reset stores between tests and test actions directlyMEDIUM
1.0.0 techs/zustand/test-actions-and-reset-stores
Subscribe with narrow, stable selectorsHIGH
1.0.0 techs/zustand/subscribe-with-selectors
Update store state functionally and immutablyHIGH
1.0.0 techs/zustand/use-functional-and-immutable-updates
Use Zustand only for shared client stateHIGH
1.0.0 techs/zustand/use-zustand-only-for-shared-client-state
Code design practices/code-design
Express operations as meaningful stepsMEDIUM
1.0.0 practices/code-design/express-operations-as-meaningful-steps
Organize code by featureMEDIUM
1.0.0 practices/code-design/organize-code-by-feature
Separate pure computation from effectsMEDIUM
1.0.0 practices/code-design/separate-pure-computation-from-effects
Concurrency practices/concurrency
Honor cancellation and deadlines across every blocking stageHIGH
1.0.0 practices/concurrency/honor-cancellation-across-blocking-stages
Keep shared resources alive until their users finishHIGH
1.0.0 practices/concurrency/keep-shared-resources-alive-until-users-finish
Performance practices/performance
Optimize measured hot paths by removing repeated workMEDIUM
1.0.0 practices/performance/optimize-measured-hot-paths
READMEs practices/readmes
Give a quick start that runs as writtenMEDIUM-HIGH
1.0.0 practices/readmes/give-a-quick-start-that-runs-as-written
Keep the README an entry point, and link to the full documentationMEDIUM
1.0.0 practices/readmes/keep-the-readme-an-entry-point
Match the README's presentation to the product's tierMEDIUM
1.0.0 practices/readmes/match-presentation-to-product-tier
Open with what the product does for the readerMEDIUM
1.0.0 practices/readmes/open-with-what-the-product-does
State what the product does not doMEDIUM
1.0.0 practices/readmes/state-what-the-product-does-not-do
Testing practices/testing
Choose tests by risk and costHIGH
1.0.0 practices/testing/choose-tests-by-risk
Cover empty inputs and boundariesMEDIUM
1.0.0 practices/testing/cover-boundary-cases
Keep tests independentMEDIUM-HIGH
1.0.0 practices/testing/keep-tests-independent
Name tests for the behavior and the conditionLOW
1.0.0 practices/testing/name-tests-for-behavior-and-condition
Reproduce bugs with regression testsHIGH
1.0.0 practices/testing/test-bug-fixes-before-fixing
Run focused tests while iterating, and the full suite before finishingLOW-MEDIUM
1.0.0 practices/testing/run-focused-tests-while-iterating
Test at the lowest layer that proves the behaviorMEDIUM-HIGH
1.0.0 practices/testing/test-at-the-lowest-layer
Test observable behaviorHIGH
1.0.0 practices/testing/test-observable-behavior