Install
openclaw skills install @demark-pro/effector-ecosystemUse when designing, reviewing, generating, or refactoring React frontend applications built with Feature-Sliced Design, effector, effector-react, Farfetched, contracts, patronum, atomic-router, effector-storage, forms, i18n, testing, and related tooling. Explains where code belongs, which packages to use, and which Effector/FSD anti-patterns to avoid.
openclaw skills install @demark-pro/effector-ecosystemUse this skill for frontend applications that use or plan to use:
effector-react for binding units to components@withease/contracts or compatible contracts for runtime validationpatronum, atomic-router, effector-storage, effector-action, effector-forms, @withease/factories, @withease/i18next, @withease/web-api, @effector/next, @effector/reflect, @withease/redux, eslint-plugin-effector, Steiger, Effector Babel/SWC pluginsThis skill is not specific to admin panels. Admin tables and CRUD are examples, not the default assumption.
The target architecture:
UI is dumb. Business logic is declarative. Remote data is validated. Pages orchestrate. Features represent user actions. Entities represent domain objects. Shared code has no business knowledge.
Use this skill when the user asks about:
app, pages, widgets, features, entities, sharedWhen answering, do not immediately generate a huge structure unless the user asks for it. First identify the goal:
If the user gives code, review the code against this skill and return:
React components must:
useUnitReact components must not:
sample, createEvent, createStore, createEffect, or factories during render$store.getState()watch for application behavioruseUnit shape per connected componentFor every component that reads/calls several Effector units from the same model, prefer a single useUnit call with an object or array shape:
const { value, submitDisabled, onValueChange, onSubmit } = useUnit($$form);
or:
const [value, submitDisabled, onValueChange, onSubmit] = useUnit([
$value,
$submitDisabled,
valueChanged,
submitted,
]);
Then destructure every returned value and pass the bound callbacks to JSX. Name handler-like values returned from useUnit with React-style on* aliases: expose onSubmit: submitted, onValueChange: valueChanged, onRetryClick: retryClicked. Keep Effector events named as facts in models; alias them only for React binding.
Avoid repeated bindings in the same component:
// bad by default: noisy and easier to desync during refactoring
const value = useUnit($value);
const submitDisabled = useUnit($submitDisabled);
const onValueChange = useUnit(valueChangedEvent);
Split the component when subscription granularity matters instead of scattering many useUnit calls in one component.
Create units at module level only.
Use:
createEvent for facts that happenedcreateStore for statecreateEffect only for side effects not already handled by Farfetchedattach to inject stores/params into an effect declarativelysample as the main connection operatorcombine for view modelssplit or effector-action for complex branching when it improves readabilitypatronum for common operators like debounce, throttle, reset, status, pending helpersscopeBind for callbacks that leave Effector's call stack and must still work inside a ScopeAvoid:
watch for logic$store.getState() for production logicundefined from store reducers unless skipVoid: false is intentionalUse Farfetched for backend communication:
createJsonQuery for data readscreateJsonMutation for data writesdeclareParams<T>() for typed paramsresponse.contract for runtime validationmapData to map DTOs after validationmapError to normalize transport/validation/domain errorsconcurrency operator for search, filters, and fast-changing requestscreateBarrier + applyBarrier for auth refresh or unavailable-resource flowskeepFresh, cache, .refresh, and update for refresh/cache semantics when appropriateNever trust backend data without a contract.
Use layers:
app -> pages -> widgets -> features -> entities -> shared
Imports must point only downward by layer.
Each slice must expose public API through index.ts.
External code must import from slice public API, not internal files.
Inside a slice, use relative imports. Between slices, use absolute imports.
Do not add packages because they are popular. Choose them when they solve a specific architectural problem.
Use the package map in references/01-package-map.md and the detailed notes in references/10-ecosystem-library-notes.md.
src/
app/
entrypoint/
providers/
routes/
store/
styles/
pages/
<page-name>/
index.ts
route.ts
ui/
model/
api/ # only page-specific remote operations
lib/
widgets/
<widget-name>/
index.ts
ui/
model/
lib/
features/
<user-action>/
index.ts
ui/
model/
api/
lib/
entities/
<domain-entity>/
index.ts
@x/ # only for explicit entity cross-imports
ui/
model/
api/
lib/
shared/
api/
config/
routes/
ui/
lib/
i18n/
assets/
Do not create all segments automatically. Add a segment only when it has real content.
Use this decision tree:
app.pages/<page>.widgets/<widget>.features/<action>.entities/<entity>.shared.Stores:
export const $user = createStore<User | null>(null);
export const $isAuthorized = createStore(false);
Events:
export const formSubmitted = createEvent<FormValues>();
export const searchChanged = createEvent<string>();
export const pageOpened = createEvent();
useUnit UI binding shapes should expose these events as handler aliases:
export const $$form = {
value: $value,
onValueChange: valueChanged,
onSubmit: formSubmitted,
};
Effects:
export const analyticsTrackedFx = createEffect<AnalyticsPayload, void>();
Queries/mutations:
export const userQuery = createJsonQuery(...);
export const updateProfileMutation = createJsonMutation(...);
Avoid vague names:
// bad
export const setData = createEvent<any>();
export const update = createEvent();
export const fx = createEffect();
Before giving a detailed answer, consult the relevant files:
references/01-package-map.mdreferences/02-fsd-placement.mdreferences/03-effector-modeling.mdreferences/04-farfetched-contracts.mdreferences/05-react-ui-binding.mdreferences/06-routing-forms-persistence-i18n.mdreferences/07-testing-tooling.mdreferences/08-anti-patterns.mdreferences/09-review-checklist.mdreferences/10-ecosystem-library-notes.mdBe specific. Prefer concrete placement and code examples.
When correcting code, show the minimal correct version first, then explain.
When a choice is trade-off based, say what the default should be and when to deviate.