Design of a software distribution platform

Work in Progress . . .

Project context

This project is a software distribution platform inspired by Steam, currently under development. Even though the first visible version will intentionally remain simple, the architecture has been designed with a long-term vision to avoid building a V1 that would be difficult to evolve.

Role & organization

My role in this project goes beyond development. I am involved in both technical and organizational aspects, including requirement analysis, version planning, task prioritization, documentation, data modeling and V1 prototyping.

I am responsible for the overall structuring of the project, without being the origin of the product.

Functional directions are defined upstream, and my role is to structure them, translate them into coherent technical solutions, and ensure a solid foundation for future evolutions.

As the project is designed to evolve in stages, I set up a Trello-based organization to maintain a clear overview of progress, decisions, and upcoming priorities, structured by versions and development phases.

Project organization using a Trello board structured by phases (backlog, in progress, validation, completed) and by versions (V1, V2 and beyond)

Analysis & project breakdown

A significant part of the initial work focused on understanding the product model. The goal was to design a data model more advanced than the first version that will actually be deployed.

The public V1 will focus solely on product browsing, but the backend already anticipates future needs such as product management, relationships between products, files, formats, supported systems, media, updates, related content, and internal access control.

Two levels of evolution are defined: the user-facing version, intentionally limited at first, and the technical data model, more comprehensive and designed to support future evolutions without impacting the overall architecture.

Data modeling

An initial phase consisted of defining a data dictionary (field identification, typing, and documentation) as well as a relational diagram.

The PostgreSQL database serves as the source of truth, and TypeORM entities explicitly reflect it. Each relationship, constraint, enum, composite key, or exception is documented to remain understandable over time.

Database diagram showing relationships between different entities

DTO strategy

A distinct DTO strategy has been implemented depending on usage.

Read DTOs are intentionally broad at first to quickly cover the data model. On the other hand, CREATE and UPDATE DTOs are much stricter and are only created when a real application flow exists. They do not mirror entities, but instead represent what the client is actually allowed to send.

Some fields are intentionally excluded when they are generated by the backend, are sensitive, technical, or already inferred from the parent context.

Structuring & inventories

To maintain a clear overview of the project scope, I created dedicated inventories of existing DTOs, specialized DTOs, available services, exposed methods, and responsibilities of each layer. This avoids having to browse the entire project structure for every decision and helps maintain documentation that will be useful for future collaborators.

Documentation of DTO conventions and API structure

Services & patterns

On the service layer, I chose to progress from the simplest cases to the most complex ones.

The first implementations focus on read-only reference tables. These services follow an _R__ pattern, meaning read-only, with no create, update, or delete operations.

More complex entities, such as those related to products, are intentionally handled later. They involve more advanced logic (multiple relationships, specific business cases, transactions, orchestration), which require a solid foundation first.

To standardize behaviors, I defined operation patterns such as _R__, CRU_, CR_D, or CRUD. These patterns serve as guidelines to adapt each entity to its actual needs.

Overall approach

The project is structured with a clear separation of responsibilities, where each layer has its own role. This avoids mixing concerns and helps maintain a clean and maintainable architecture.

This level of structuring and documentation requires more effort upfront, but it helps maintain a clear long-term vision, makes it easier to get back up to speed quickly, and facilitates onboarding new collaborators.