Refactoring Saffira: Moving from type-based to feature-first architecture

Published 2026-07-07
Updated 2026-07-07
[insights][architecture]

The Legacy Structure: Type/Function-based

In Saffira's early stages, we partitioned our directories strictly by type: components, services, utils, and models. While this folder-by-type design was simple to bootstrap, it introduced high friction as the application grew. I found that a single logical feature modification required changes across several directories, creating low cohesion and high coupling. I was forced to jump across separated sub-trees for a single task, leading to massive, spaghetti imports.

Type/Function-based folder organization diagram

Feature-based + App Shell Design

To solve this layout coupling, I refactored Saffira to a feature-first directory layout. I grouped related files into cohesive module sub-folders under a global features/ directory (like map, alerts, occurrences), treating each as a self-contained domain module encapsulating its private components, page views, services, types, and utility functions. I strictly isolated features so they are not allowed to import other features. For shared logic, I utilized the shared/ directory, maintaining a functional structure for generic components, core configurations, and helpers.

Core, Features, and Shared folder architecture diagram

The Layout Shell Pattern

A critical aspect of the new layout was separating permanent visual components from dynamic page views. I created the core/ layer to house persistent layouts, such as MainShellLayoutComponent and DashboardShellLayoutComponent. The App Shell wraps persistent chrome elements (headers, collapsible panels) around a dynamic router outlet. This guaranteed zero-layout shifts during route transitions and kept active operators' sessions decoupled from sub-page render cycles.

App Shell layout and chrome wireframe

Cohesion and trade-offs

Shifting to feature-first folder organization dramatically increased cohesion and enforced clear, logical boundaries between systems. I found that this layout makes parallel development and onboarding new team members much easier. However, I learned that this model introduces minor code duplication risks if teams build local helpers instead of migrating them. Enforcing rigid import reviews and design audits is necessary to keep the shared folder lean.

Comparison table of folder architectures