Install
openclaw skills install @demark-pro/effector-fsdUse when designing, reviewing, generating, or refactoring Feature-Sliced Design project structure for Effector ecosystem applications: layers, slices, segments, public APIs, imports, placement of Effector models, Farfetched operations, Atomic Router routes, Next.js adapters, and Steiger checks.
openclaw skills install @demark-pro/effector-fsdUse this skill for project structure in applications that combine Feature-Sliced Design with the Effector ecosystem.
This skill answers:
app, pages, widgets, features, entities, sharedapp/pages framework folders coexist with FSD layers@x cross-imports, and import boundaries workUse effector-ecosystem alongside this skill for exact Effector/Farfetched/React/Next.js API usage. This skill owns placement and structure; effector-ecosystem owns reactive code semantics.
Use this skill when the user asks about:
model, ui, api, lib, route.ts, contracts, mappers, forms, queries, mutations, barriers, widgets, providers, or adapterssrc/api, src/components, src/store, src/hooks, src/utils into FSD@xWhen the user asks a placement question, answer with:
When the question is mostly about exact Effector/Farfetched API syntax, defer to effector-ecosystem but keep placement guidance here.
When the user asks for a full FSD/Effector architecture audit, do not only check import direction and folder names. Also inspect ownership of cross-cutting Effector flows:
profileUpdated or a $$feature facade.$isOpened gate or move invalidation to an app/entity integration owner.pages. If the operation or contract describes a reusable business resource, move it to an entity; if it is a user action, move the mutation to a feature; keep only page-only filters/list queries in pages.app, not inside shared, and not scattered through unrelated pages.shared stays transport-only or document an adapter boundary.For each finding, give the target owner (app, page, widget, feature, entity, shared), the dependency reason, and a minimal folder/import example.
Default layer order:
app -> pages -> widgets -> features -> entities -> shared
A module inside a slice can import only from:
shared infrastructureIt must not import from higher layers or from sibling slices on the same layer, except explicit @x public APIs for justified entity relationships.
Every slice must expose a public API through index.ts.
External code imports from:
import { UserAvatar, userQuery } from '@/entities/user';
not from:
import { userQuery } from '@/entities/user/api/user.query';
import { $user } from '@/entities/user/model/user.model';
Inside a slice, use relative imports. Between slices, use absolute imports through public APIs.
app and shared are layers and slices at the same time. They contain segments directly, not business slices.
Good:
shared/api/
shared/ui/
shared/lib/date/
app/providers/
app/routes/
app/model/
Bad:
shared/user/
shared/features/
app/entities/
Use conventional segments:
ui # rendering and visual composition
model # stores, events, business rules, contracts if they describe the model
api # backend operations, DTO mappers, endpoint-specific remote logic
lib # local helpers for this slice/segment
config # feature flags/config for this owner
route # route declaration/re-export when route ownership is local
Avoid generic dumping grounds:
components/
hooks/
helpers/
utils/
types/
store/
A small types.ts or utils.ts is acceptable only when it is tightly scoped and not mixing multiple domains.
Do not scaffold every layer and segment by default. Add a layer/segment when it has real content and a clear owner.
Most apps need at least:
app/
pages/
shared/
Add entities, features, and widgets when the product complexity justifies them.
src/
app/
entrypoint/
providers/
routes/
model/
styles/
pages/
<page>/
index.ts
route.ts
ui/
model/
api/ # page-specific only
lib/
widgets/
<widget>/
index.ts
ui/
model/
lib/
features/
<user-action>/
index.ts
ui/
model/
api/
lib/
entities/
<domain-entity>/
index.ts
@x/ # only explicit entity cross-import APIs
ui/
model/
api/
lib/
shared/
api/
config/
routes/
ui/
lib/
i18n/
assets/
Do not create empty folders.
appPut here:
appStarted, appStopped, global lifecycleEffectorNext root/provider adaptersExample:
app/model/app.model.ts
app/routes/router.ts
app/routes/protected.ts
app/providers/effector-provider.tsx
pages/<page>Put here:
pageStarted, route params, page filters/sorting/paginationExample:
pages/users/route.ts
pages/users/model/page.model.ts
pages/users/api/users-page.query.ts
pages/users/ui/users-page.tsx
widgets/<widget>Put here only when the block is large, self-contained, and reused or independently meaningful.
Examples:
widgets/sidebar/
widgets/user-card-list/
widgets/checkout-summary/
Do not create a widget for every small card, form, or one-page block.
features/<user-action>Put here:
formSubmitted, profileUpdated, loginSubmittedGood feature names:
features/session-login
features/session-logout
features/profile-update
features/comment-create
features/order-cancel
Bad feature names:
features/open-modal
features/set-search
features/button-click
features/use-form
entities/<domain-entity>Put here:
Examples:
entities/user/model/user.contract.ts
entities/user/model/user.mapper.ts
entities/user/api/user.query.ts
entities/user/ui/user-avatar.tsx
entities/session/model/session.model.ts
Entities must not import features, widgets, pages, or app.
sharedPut here only domain-independent foundation:
shared/api/base-url.ts
shared/api/errors.ts
shared/api/http.ts
shared/config/env.ts
shared/ui/button.tsx
shared/lib/date/format-date.ts
shared/i18n/index.ts
shared/routes/index.ts
shared must not know user, session, order, profile, dashboard, or product-specific workflows.
entities/<entity>/api/*.query.tsfeatures/<action>/api/*.mutation.tspages/<page>/api/*.query.tsshared/api/*entities/session or app, not sharedshared/apiapp integration moduleStrict rule: shared/api may contain transport infrastructure, but must not import entities/session or open routes. If a barrier updates session state or uses session contracts, it is not shared.
shared/routesapp/routesapp/routes/protected.tspages/<page>/route.tspages/<page>/model/page.model.tsapp/routes or page route modelDo not hide routing decisions in React useEffect or shared API modules.
FSD app and pages conflict with Next.js framework folders. Prefer the official FSD recommendation: keep framework folders at project root and rename FSD layers to _app and _pages.
app/ # Next.js App Router
users/[userId]/page.tsx # thin adapter
src/
_app/ # FSD App layer
_pages/user/ # FSD Pages layer
widgets/
features/
entities/
shared/
Next App Router page adapter:
// app/users/[userId]/page.tsx
export { UserPage as default } from '@/_pages/user';
For Effector SSR/RSC, framework route files may create a Scope, call allSettled(pageStarted, { scope, params }), serialize it, and render the FSD page public API. Do not let framework route files become business models.
Use index.server.ts when a slice must expose server-only modules separately from client-safe public API.
When reviewing FSD + Effector code, look first for:
shared containing business domain code.shared importing session entities or routing.stores.ts/events.ts/effects.ts instead of responsibility.Before giving a detailed answer, consult the relevant files:
references/00-source-policy.mdreferences/01-core-rules.mdreferences/02-effector-placement.mdreferences/03-layer-recipes.mdreferences/04-routing-nextjs.mdreferences/05-farfetched-placement.mdreferences/06-public-api-imports.mdreferences/07-review-checklist.mdreferences/08-anti-patterns.mdreferences/09-migration-playbook.mdreferences/10-tooling.mdreferences/11-effector-audit-ownership.mdBe decisive on placement. Show a small tree and import examples.
When several placements are possible, choose the strict FSD default first, then list exceptions.
Do not over-scaffold. Prefer the smallest structure that preserves ownership and dependency direction.