# Asset Handling How to place static assets (images, icons, fonts, PDFs, stylesheets) inside an FSD project. Assets follow the same placement rules as code: group by use case, not by type, and keep them next to the code that uses them. > **Caution:** A custom top-level `assets` segment that aggregates all static > files is **not recommended**. It violates the FSD principles of high > cohesion and locality of changes. Place assets where they are used. --- ## Decision Tree 1. **Used by exactly one slice?** Keep the asset inside that slice, usually in the `ui/` segment, or in `model/` if it is part of business logic. 2. **Reused across the app (icons, placeholder images)?** Move to `shared/ui/`. 3. **Global stylesheet, font, or app-level resource?** Place in the `app/` layer (`app/styles/`, `app/fonts/`). 4. **Served as-is by the bundler (favicon, robots.txt)?** Use the framework's `public/` folder. The `public/` folder is not part of FSD and does not conflict with FSD layers. --- ## Slice-specific Assets When an asset belongs to one page, widget, or feature, keep it inside that slice. The asset lives next to the component that renders it: ```text pages/ home/ ui/ hero-image.jpg ← Used only by HomePage HomePage.tsx index.ts ``` If a slice uses many static images, group them in a subfolder of `ui/`: ```text pages/ home/ ui/ previews/ cake.jpg pizza.jpg sushi.jpg HomePage.tsx index.ts ``` ### Non-UI Assets Some assets are not part of the UI but are coupled to business logic. For example, a PDF template used to generate invoices. Place these in the `model/` segment alongside the logic that consumes them, not in `ui/`: ```text features/ billing/ model/ invoice-template.pdf ← Coupled to create-invoice.ts create-invoice.ts index.ts ``` The principle is locality of changes: if you delete the slice, every file it owns goes with it. An asset that lives in business logic should sit next to that logic. --- ## Shared Assets When the same asset appears across multiple slices, move it to `shared/ui/`. Place reusable images in a topical subfolder, or place a single asset next to the shared component that uses it: ```text shared/ ui/ placeholders/ ← Reused placeholder images cake.jpg pizza.jpg Dropdown.tsx chevron.svg ← Used only by Dropdown, kept next to it ``` A single icon used by exactly one component in the UI kit stays next to that component. A library of icons or images reused across many components goes in a topical subfolder. --- ## Global Assets Global stylesheets and fonts belong in the `app/` layer because they are imported by the application entrypoint, not by individual slices: ```text app/ styles/ reset.css global.css fonts/ inter.woff2 main.ts ``` Theme variables, CSS resets, and font registrations are app-wide concerns. They bootstrap the application's visual layer the same way providers bootstrap the runtime layer. --- ## Public Folder Most bundlers expose a `public/` folder at the project root. Files here are served as-is, without bundling or hashing. - Vite, Next.js, Nuxt: `public/` at the project root. - Astro: `public/` at the project root (path is fixed and cannot be changed). `public/` is not part of FSD. It does not collide with FSD layers and does not need to live under `src/`. Use it for files that must be served at fixed URLs: favicon, `robots.txt`, `sitemap.xml`, OG images, and similar. ```text public/ favicon.ico robots.txt og-image.png src/ app/ pages/ shared/ ``` Some projects keep a project-local `app/public/` folder when the bundler allows assets to live alongside the entrypoint. Both layouts are valid. --- ## Summary Table | Asset | Location | | -------------------------------------- | ----------------------------------------- | | Image used by one page/widget/feature | Inside the slice's `ui/` segment | | PDF or template tied to business logic | Inside the slice's `model/` segment | | Icon reused across the app | `shared/ui/` (topical subfolder if many) | | Icon used by exactly one shared kit UI | Next to that component in `shared/ui/` | | Global CSS reset, theme variables | `app/styles/` | | Web fonts | `app/fonts/`, `public/`, or `app/public/` | | Favicon, robots.txt, sitemap | `public/` (or `app/public/`) | --- ## Anti-patterns - **Do not create a top-level `assets/` segment** that holds all images, fonts, and icons. It breaks cohesion and forces consumers to import from a folder unrelated to the code they are working on. - **Do not extract a slice-local asset to `shared/` "in case" it gets reused.** Move it only when actual reuse appears. - **Do not place CSS modules in an `assets/` folder.** A component's stylesheet belongs next to that component in `ui/`. - **Do not name an FSD segment `public`.** The framework's `public/` folder is reserved and lives outside `src/`. - **Do not split assets and the components that use them.** A page that ships a hero image should keep that image in the page so removing the page removes the image. --- ## See Also - `references/layer-structure.md`: segment rules and layer organization - [Desegmentation](https://fsd.how/docs/guides/issues/desegmented/): why technical-role grouping (including a generic `assets/` segment) hurts cohesion