Skip to content

Commit 5202a66

Browse files
committed
docs(en): add slice-groups documentation
1 parent 9f3ef4d commit 5202a66

2 files changed

Lines changed: 308 additions & 1 deletion

File tree

src/content/docs/docs/reference/public-api.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Public API
33
sidebar:
4-
order: 3
4+
order: 4
55
---
66

77
import { FileTree, Aside } from '@astrojs/starlight/components';
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
---
2+
title: Slice groups
3+
sidebar:
4+
order: 3
5+
---
6+
7+
import { FileTree } from '@astrojs/starlight/components';
8+
9+
A slice group is a folder that visually groups related slices together.
10+
It is not a required part of FSD and can be optionally introduced when the number of slices grows large enough to make navigation difficult.
11+
12+
This document explains what a slice group is, what problem it solves, when to introduce it, and what rules to follow when applying it.
13+
14+
> Slice groups are also referred to as structural grouping or slice grouping. In this document, we call them **slice groups**.
15+
16+
## What is a slice group
17+
18+
A slice group is a folder that groups related slices within the same layer.
19+
A slice group itself is not a slice — it does not have its own segments or public API.
20+
21+
In other words, a slice group is a way to make the folder structure easier to find and read without changing FSD's dependency rules.
22+
23+
### Core rules
24+
25+
> **Rule 1: A group folder is just a structural folder**
26+
>
27+
> A group folder does not have its own segments like `model`, `ui`, or `api`. It also does not have a public API like `index.ts`.
28+
29+
> **Rule 2: Slices inside a group are still independent**
30+
>
31+
> Even when slices are under the same group, the isolation rules between slices apply exactly the same as outside the group.
32+
33+
> **Rule 3: A group is only for navigation, not as a separate functional unit**
34+
>
35+
> Do not use a slice group as a new layer, sub-layer, or shared module.
36+
37+
If these rules are not followed, the group folder may end up being used as a separate structural unit rather than a simple organizational folder.
38+
This makes it harder to distinguish which folders are actual slices and can make dependency relationships more complex.
39+
40+
## Why it is needed
41+
42+
When there are few slices, a flat structure is sufficient for navigation.
43+
However, as slices of the same nature grow in number, you have to scan through the entire layer multiple times to find related code.
44+
45+
For example, suppose the `entities` layer has accumulated many payment-related slices.
46+
47+
**Before grouping:**
48+
49+
<FileTree>
50+
- entities/
51+
- invoice/
52+
- model/
53+
- ui/
54+
- receipt/
55+
- model/
56+
- ui/
57+
- transaction/
58+
- model/
59+
- ui/
60+
- user/
61+
- model/
62+
- ui/
63+
- product/
64+
- model/
65+
- ui/
66+
- ...
67+
</FileTree>
68+
69+
To find the payment-related slices (`invoice`, `receipt`, `transaction`), you have to scan through the entire layer to locate them.
70+
71+
**After grouping:**
72+
73+
<FileTree>
74+
- entities/
75+
- payment/ slice group
76+
- invoice/ slice
77+
- model/
78+
- ui/
79+
- receipt/ slice
80+
- model/
81+
- ui/
82+
- transaction/ slice
83+
- model/
84+
- ui/
85+
- user/ slice (not a group)
86+
- model/
87+
- ui/
88+
- product/ slice (not a group)
89+
- model/
90+
- ui/
91+
- ...
92+
</FileTree>
93+
94+
Now, payment-domain-related slices can be found directly under `payment/`.
95+
96+
Slice groups work this way — by placing related slices close together, they **help you find related slices faster**.
97+
This is especially helpful for new team members or developers seeing the area for the first time to understand the structure.
98+
99+
### The same problem can occur in pages
100+
101+
A similar problem can appear in the pages layer.
102+
When list, detail, create, and edit pages for a specific domain are scattered across the entire layer, discoverability suffers.
103+
104+
<FileTree>
105+
- pages/
106+
- orderCreate/
107+
- ui/
108+
- orderDetail/
109+
- ui/
110+
- orderList/
111+
- ui/
112+
- customerDetail/
113+
- ui/
114+
- customerList/
115+
- ui/
116+
- settings/
117+
- ui/
118+
- ...
119+
</FileTree>
120+
121+
With `order`-related and `customer`-related pages listed flat, you have to scan the entire layer to find pages for a specific domain.
122+
123+
Introducing slice groups allows you to see all pages of the same domain in one place.
124+
125+
<FileTree>
126+
- pages/
127+
- order/ slice group
128+
- orderCreate/ slice
129+
- ui/
130+
- orderDetail/ slice
131+
- ui/
132+
- orderList/ slice
133+
- ui/
134+
- customer/ slice group
135+
- customerDetail/ slice
136+
- ui/
137+
- customerList/ slice
138+
- ui/
139+
- settings/ slice (not a group)
140+
- ui/
141+
- ...
142+
</FileTree>
143+
144+
In this way, slice groups can be applied not only to entities but also to the pages layer when related pages grow numerous enough to make navigation difficult.
145+
146+
## When to consider introducing them
147+
148+
Slice groups are not a default structure — they are introduced optionally when you need to solve a navigation problem.
149+
150+
### Signals to consider introduction
151+
152+
- **Multiple slices sharing the same business context are scattered within a layer.**
153+
For example, `invoice`, `receipt`, and `transaction` all deal with the payment context but are listed flat.
154+
155+
- **A common parent context is naturally apparent just from the slice names.**
156+
For example, `orderCreate`, `orderDetail`, and `orderList` are all understood under the common context of `order`.
157+
Similarly, `invoice`, `receipt`, and `transaction` can be recognized together under the `payment` context.
158+
159+
- **You find yourself repeatedly scanning the entire layer to find related slices.**
160+
161+
- **New team members find themselves repeatedly scanning the entire layer to understand the structure.**
162+
163+
### Signals it is not needed yet
164+
165+
- Even with many slices, names alone are sufficient for quick navigation.
166+
167+
- The grouping criteria feel unnatural, and different team members keep grouping things differently.
168+
169+
- Even after creating a group, it only contains 1–2 slices, so the organizational benefit is minimal.
170+
171+
- Creating a group actually requires additional explanation like "is this a slice or a group?"
172+
173+
The key point is not about increasing folder depth, but about whether the structure actually becomes easier to find and understand.
174+
175+
## How to apply
176+
177+
### entities — domain-based grouping
178+
179+
Group slices that are close from a domain model perspective.
180+
181+
<FileTree>
182+
- entities/
183+
- payment/ slice group
184+
- invoice/ slice
185+
- model/
186+
- ui/
187+
- receipt/ slice
188+
- model/
189+
- ui/
190+
- transaction/ slice
191+
- model/
192+
- ui/
193+
- user/ slice (not a group)
194+
- model/
195+
- ui/
196+
- ...
197+
</FileTree>
198+
199+
Since `payment/` is not a slice, it does not have its own `model.ts`, `index.ts`, or `api/`.
200+
201+
Not all slices need to be placed in a group.
202+
Slices like `user/`, whose meaning is clear on its own, can remain without a group.
203+
204+
### pages — domain-based page grouping
205+
206+
This can be used when multiple pages of the same domain need to be handled together.
207+
208+
<FileTree>
209+
- pages/
210+
- order/ slice group
211+
- orderCreate/ slice
212+
- ui/
213+
- orderDetail/ slice
214+
- ui/
215+
- orderList/ slice
216+
- ui/
217+
- customer/ slice group
218+
- customerDetail/ slice
219+
- ui/
220+
- customerList/ slice
221+
- ui/
222+
- settings/ slice (not a group)
223+
- ui/
224+
- ...
225+
</FileTree>
226+
227+
This structure is helpful when there are many pages on the same topic, such as list, detail, create, and edit.
228+
Opening just one parent folder lets you see all related pages together.
229+
230+
### Can it be used in features too?
231+
232+
Yes, it can.
233+
However, since features often span multiple entities and multiple user flows, the grouping criteria may be less clear than in entities or pages.
234+
235+
Therefore, it is better to view slice groups in features as an option to be used exceptionally.
236+
If there is no natural grouping criterion, it is better not to force their introduction.
237+
238+
## Patterns to avoid
239+
240+
A slice group should be a structural folder only.
241+
If you start placing shared code or files that re-export multiple slices in the group folder, the group effectively starts behaving as a module.
242+
243+
**Pattern to avoid:**
244+
245+
<FileTree>
246+
- entities/
247+
- payment/
248+
- model.ts group-level shared model
249+
- index.ts group-level re-export
250+
- invoice/
251+
- model/
252+
- ui/
253+
- receipt/
254+
- model/
255+
- ui/
256+
</FileTree>
257+
258+
In this structure, through `payment/model.ts` or `payment/index.ts`,
259+
even though the child slices appear independent, they easily become coupled at the group level in practice.
260+
261+
As a result, slice boundaries become blurred, dependency directions become harder to trace, and it becomes confusing what the actual independent units are.
262+
263+
**Correct pattern:**
264+
265+
<FileTree>
266+
- entities/
267+
- payment/
268+
- invoice/
269+
- model/
270+
- ui/
271+
- receipt/
272+
- model/
273+
- ui/
274+
</FileTree>
275+
276+
If shared logic is genuinely needed, you should first consider whether it can be separated into a more appropriate layer or a separate slice, rather than forcing it into the group folder.
277+
278+
## FAQ
279+
280+
### Do all slices need to be placed in a group?
281+
282+
No.
283+
Only group slices that naturally belong together, and leave the rest as they are.
284+
285+
For example, group only cases where viewing them together is natural, like `payment/invoice` and `payment/receipt`,
286+
while slices that are independently understood like `user` and `settings` can remain without a group.
287+
288+
### Is it okay if the group name is included in the import path?
289+
290+
Yes, it is fine.
291+
For example, if the group name is included in the path like `@/entities/payment/invoice`, the path itself reveals which topic the slice belongs to.
292+
293+
However, how to expose the path is a matter of the team's import convention.
294+
295+
### Does having a slice group make imports between slices more flexible?
296+
297+
No.
298+
Import rules between slices are not relaxed just because they are in the same group.
299+
300+
A group is only a structure for navigation, and slice boundaries and dependency rules remain the same as before.
301+
302+
## References
303+
304+
- [KakaoPay — A case of applying slice grouping in the pages layer](https://tech.kakaopay.com/post/fsd/#2-slice-grouping-%ED%97%88%EC%9A%A9-%EB%B0%8F-pages-%EB%A0%88%EC%9D%B4%EC%96%B4-%EA%B5%AC%EC%84%B1)
305+
- [Russian Telegram FSD community — Discussion on structural grouping, slice groups, and layer extension](https://t.me/c/1216849846/1/2785)
306+
- [Russian Telegram FSD community — Nested vs. flat structures, forms and allowed scope of slice groups](https://t.me/c/1216849846/1/5051)
307+
- [Russian Telegram FSD community — Why there are fewer grouping examples in features, and whether slice groups are possible in features](https://t.me/c/1216849846/1/80620)

0 commit comments

Comments
 (0)