Project Structure as a Way of Thinking: Technical Considerations
As front-end projects grow in complexity, code organization is no longer just a matter of aesthetics. It is becoming a key aspect that determines the scalability, performance and maintainability of an application. In this article, we will examine how project structure can become a mindset and the benefits of a composables and modules approach.
Challenges in Scalable Frontend Projects
As we develop frontend projects, we often encounter problems of code chaos, difficulty in code maintenance and performance degradation. In the initial phase of application development, file structure is often imposed by the framework or conventions adopted by the team. However, over time, as the application grows, this approach can lead to various problems:
Code duplication - The same code snippets appear in different parts of the application, leading to difficulties in maintaining them.
Complexity of refactoring - Over time, refactoring becomes more difficult, as modifications to one component can affect many others.
Lack of modularity - The application becomes a monolith in which each component is tightly coupled to others, limiting the ability to grow and scale.
Evolution of Structure: From Classical to Modular
Classic Structure
The traditional project structure is usually divided into directories such as components, pages, services and assets. This is a relatively straightforward approach that allows you to start working on a project quickly. However, in the long run, such a structure has its limitations, especially when the team grows and the project begins to include more and more functionality.
An example of a classic structure:
src/
├── components/
│ ├── Button.vue
│ ├── Header.vue
├── pages/
│ ├── Home.vue
│ ├── About.vue
├── services/
│ ├── ApiService.js
├── assets/
│ ├── logo.png
└── main.js
With this approach, the code is easy to understand at the initial stage, but over time it can lead to management difficulties as the various components begin to intermingle and the application logic becomes fragmented.
Modularity as a Solution
In response to the increasing complexity of applications, our team has adopted a structure that integrates composables and modules. This approach allows for better code management, avoids duplicate logic, and facilitates testing and refactoring.
Composables and Modules: A New Paradigm for Thinking about Code
Composables - Multiple Uses of Logic
Composables are functions that can be reused in different components. They allow you to pull common logic into one place, which greatly simplifies code management and testing.
An example of using composables:
Suppose we need to manage a user's authentication status in multiple places in the application. Instead of duplicating the code, we can extract it to the useAuth function.
// composables/useAuth.js
import { ref } from 'vue';
export function useAuth() {
const user = ref(null);
function login(credentials) {
// logika logowania
}
function logout() {
// logika wylogowania
}
return {
user,
login,
logout,
};
}
This allows useAuth to be used in different components without duplicating logic:
// components/LoginForm.vue
import { useAuth } from '@/composables/useAuth';
export default {
setup() {
const { login } = useAuth();
function submitForm() {
login(credentials);
}
return {
submitForm,
};
},
};
Modules - Independence and Scalability
Modules introduce a clear division of responsibilities in the application. Each module represents a separate functionality, which facilitates its development and scaling. In this way, modules can be developed independently, without the risk of affecting other parts of the application.
An example of a catalog module:
src/
├── modules/
│ ├── catalog/
│ │ ├── pages/
│ │ │ ├── ProductPage.vue
│ │ ├── components/
│ │ │ ├── ProductList.vue
│ │ ├── services/
│ │ │ ├── CatalogService.js
│ │ ├── index.js
│ │ └── types.d.ts
└── main.js
The catalog module can manage all functions related to the product catalog - from displaying the product list to managing status and communication with the backend.
Benefits of the Modular Approach
1. Better Organization of Codes
With the modular approach, each part of the application has a clearly defined place. This makes it simpler to navigate the project and less risky to make changes.
2. Multiple Uses of Logic
Composables allow you to extract repetitive logic into individual functions, reducing the risk of code duplication and making it easier to maintain.
3. Scalability
Modules can be developed and scaled independently of each other. This is especially important in large projects, where different teams can work on different functions at the same time, without the risk of affecting each other's work.
4. Testability
Isolated modules and composables can be tested individually, making it easy to make changes and ensure high code quality.
Implementation Example: Catalog Module
The catalog module can include components such as ProductList, which renders a list of products on the page, and ProductPage, which displays the details of the selected product. All catalog-related functions, such as retrieving data from the API, managing product status, are handled within this module.
// modules/catalog/components/ProductList.vue
<template>
<div>
<Product v-for="product in products" :key="product.id" :data="product" />
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
import { fetchProducts } from '@/modules/catalog/services/CatalogService';
import Product from './Product.vue';
export default {
components: {
Product,
},
setup() {
const products = ref([]);
onMounted(() => {
fetchProducts().then(data => {
products.value = data;
});
});
return {
products,
};
},
};
</script>
// modules/catalog/services/CatalogService.js
export function fetchProducts() { return fetch('/api/products') .then(response => response.json()) .catch(error => console.error('Error fetching products:', error)); }
Application to the Project
In our project, adopting a modular approach using composables and modules allowed us to significantly improve code organization. The module structure provides clear divisions of responsibility, which translates into ease of introducing new features. Implementing a modular structure in our project using composables and modules has brought a number of benefits, from increased scalability to better code organization to improved performance. The structure allows for clear divisions of responsibility, where each module can develop independently, and common logic is separated into composables, making it easier to reuse and test.
Example of Modular Structure
src/
├── app/
├── composables/
│ ├── useAuth.js
│ └── useFetch.js
├── modules/
│ ├── catalog/
│ │ ├── pages/
│ │ │ ├── ProductPage.vue
│ │ ├── components/
│ │ │ ├── ProductList.vue
│ │ ├── services/
│ │ │ ├── CatalogService.js
│ │ ├── index.js
│ │ └── types.d.ts
└── main.js
In the above example, the catalog module contains all the components necessary to manage the product catalog. The authentication logic has been extracted into composable useAuth, which allows it to be reused in different components, such as the login form.
Technical Advantages and Examples
1. Isolation of Logic: composables allow you to isolate repetitive logic. The useAuth example shows how logic related to authentication can be isolated and reused in different parts of the application.
2. Modularity: modules, such as catalog, organize related components, pages and services into a single structure, which simplifies management and development of functionality.
3. Scalability: As the project grows, new modules can be added without affecting existing logic, making the structure scalable.
4. Efficiency: By separating logic into composables, the number of duplicate code snippets is reduced, increasing efficiency and making maintenance easier.
Summary
We believe that a well-designed project structure is the foundation for the success of any application. With our approach, based on composables and modules, we create scalable, efficient and maintainable applications that grow with your business. Our experience in implementing modern architectural solutions allows us to deliver projects that meet the needs of even the most demanding clients. If you are looking for a partner to help you build a robust and future-proof application - contact us.
Let's talk about potential areas of collaboration!
Hi!
during the first consultation we'll analyze your goals through the lens of ROI and operational risk. Whether we're building an Enterprise system, an application, or an AI automation — together we'll plan an architecture that eliminates your technical debt and unlocks scalability.
You can find more articles on this topic on our blog
Tailwind CSS: Ending "CSS Hell" – How Utility-First Architecture Lowers TCO and Stabilizes Scalable Projects
Discover Tailwind CSS – the "utility-first" framework revolutionizing the frontend. See how it cuts development time and guarantees design consistency in web design.
6 min
Read more
Budget in IT projects
How to ask the client about the project budget. How to fit in the budget and how to monitor it.
7 min
Read more
Designing Mobile Stores: Elements That Determine Conversion
Online Store for Mobile Devices - How to Design it Well to be Effective and User-Friendly.
3 min
Read more







