A Scalable Architecture for Large Vue 3 Projects
last week - 22 min read • #vue, #frontendWhen I started working on large Vue 3 projects, I often found myself struggling with how to structure the code so it remained clean, scalable, and easy for others to navigate. Over time, I discovered that combining three architectural approaches – feature-based modular structure, Atomic Design for UI components, and the Container-Presentational Pattern – provides a powerful foundation for any medium to large-scale application.
In my experience, structuring projects by features makes it easier to encapsulate logic, state, and components related to a single domain. At the same time, following Atomic Design principles for shared UI components ensures consistency across the entire app and speeds up development by reusing well-defined building blocks. Adding the presentational-container component split on top of this further improves maintainability by clearly separating data-fetching and state management from pure UI rendering, resulting in cleaner, more focused components.
In this article, I’ll share how to combine these three patterns effectively, why they work so well in practice, and how they help build applications that are both maintainable and enjoyable to work with.
Atomic Design for UI components
If your project has complex and reusable UI, consider Atomic Design principles:
- Atoms – basic HTML elements and small components (buttons, inputs)
- Molecules – groups of atoms (input + label)
- Organisms – complex UI sections (forms, tables)
- Templates/Pages – layout + data binding
This is useful in design-heavy applications with a design system.
Modular feature-based structure
Instead of grouping by type (components, views, store, etc.), group by feature or domain (example):
/src
/features
/users
components/
store.js
api.js
UserListView.vue
/projects
components/
store.js
api.js
ProjectListView.vue
/shared
components/
utils/
Container-Presentational Pattern
It is an architectural approach where you divide components into two distinct categories:
Container Components (Smart)
- Responsible for data fetching, state management and business logic.
- They do not render much UI themselves but pass data to props and handle events of presentational components.
Presentational Components (Dumb)
- Focus purely on how things look.
- Receive data via props and event handlers.
- Are typically stateless or only manage local UI state (e.g. input focus).
Real Example
/src
/features
/users
components/
UserListContainer.vue # Container (data fetching, logic)
UserList.vue # Presentational (UI only)
UserCard.vue # Presentational
api.js
store.js
UserRoutes.js
/projects
components/
ProjectTableContainer.vue
ProjectTable.vue
ProjectRow.vue
api.js
store.js
ProjectRoutes.js
/shared
/ui
/atoms
Button.vue
Input.vue
Checkbox.vue
/molecules
FormField.vue
Card.vue
Modal.vue
/organisms
Header.vue
Sidebar.vue
/layout
AppLayout.vue
index.js
/icons
IconEdit.vue
IconDelete.vue
/composables
useFetch.js
useAuth.js
/services
apiClient.js
authService.js
/router
index.js
App.vue
main.js
1. Feature-based modular structure
- Under
/features
, each domain (e.g.users
,projects
) has its own folder. - Contains feature-specific components, API calls, stores, and routes.
- Encourages encapsulation and independent development of features.
2. Atomic Design for UI components
- Under
/shared/ui
, components are organised by Atomic Design principles:- Atoms: Smallest building blocks (Button, Input).
- Molecules: Groups of atoms forming a unit (FormField, Card).
- Organisms: Complex UI structures (Header, Sidebar).
- Layout: Page-level layouts and wrappers.
Promotes consistency and reusability across all features.
3. Container-Presentational Pattern
Inside each feature’s components/
folder:
- Container components (e.g.
UserListContainer.vue
) handle data fetching, store interactions, and business logic. - Presentational components (e.g.
UserList.vue
,UserCard.vue
) focus purely on rendering UI based on props.
Example flow:
UserListContainer.vue
fetches user data → passes it to UserList.vue
→ which uses UserCard.vue
for each user item.
Advantages of this structure
- Scalable and clear ownership
Features are independent, and their logic is self-contained. - Consistent, reusable UI components
Atomic Design structure ensures a shared design system for the whole app. - Clean separation of concerns within features
Container components manage logic, while presentational components focus on UI. - Ideal for large teams
Developers can work on separate features or the shared UI library without conflicts.
Wrapping Up
By combining a feature-based modular structure, Atomic Design principles, and the Container-Presentational Pattern, this architecture remains clean, scalable, and easy for any team to navigate. This approach keeps the codebase organised, components reusable, and the development process efficient – setting up any large Vue 3 project for success.