Article
Angular Naming Style Guide: Best Practices for Scalable Apps
The updated official Angular style guide introduces a new naming rule, encouraging not to use suffixes anymore for Components, Directives, and Services.
It means previously generated HomeComponent, HighlightDirective, and UserService, will result in Home, Highlight, and User instead.
This change affect both their file names and their class names.
There are two motivations behind this rule:
- To avoid relying too much on sufffixes too be lazy about proper naming.
- To prepare for selectorless components, an official Angular feature that would let you use the component class name directly in a template (e.g.
<app-home />→<Home />).
That feature was prototyped in 2025 but is now on hold and removed from the roadmap. Read The Truth About Angular Selectorless Components for details. Suffixless naming still makes sense on its own, but don't rename your codebase today expecting that template syntax to arrive soon.
Introduced with Angular v20 release, the new style guide not just encourage but enforce this new naming convention by updating the documentation and removing the suffixes for new v20 projects.
However, We still miss guidelines to help us migrate to this new naming convention. Here is an attempt to help you! It comes with some opinions but aims to understand you might have your own conventions, so feel free to adapt it to your needs.
The conflict dilemma
Given you have to deal with users in your application, it was quite common to have:
- a interface/type named
User - a service named
UserService - a component named
UserComponent
The question is: what happens by removing the suffixes?
UserService->UserUserComponent->UserUser->User
Everything is called User now.
Be Semantic
Removing suffixes does not mean removing context from your names. It means replacing generic suffixes (Component, Service) with names that describe what each piece actually does.
Types and components/services play different roles. A type models your domain — keep it plain: User, Product, Order. No Page, no Api, no Store on a type. It is already exactly what it represents.
Components and services carry behavior. They fetch data, render a view, hold state, or coordinate a feature. That is where context belongs:
User(type) vsUserPage(routed view) vsUserApi(HTTP layer) vsUserStore(state)Product(type) vsProductList(display) vsProductForm(creation flow)
When you rename, ask what the file does — not what Angular artifact it is. The answer becomes the name. Suffixes were a shortcut; semantic context is the replacement.
Types
As above, types should stay unchanged: name them for exactly what they are — a User, a Flower, etc.
While I would not recommend it, some companies are used to prefixing their types with I (such as IUser). it's often due to some global convention already used in backend languages such as C# or Java, but it's not a common practice in the TypeScript ecosystem and it does not bring any value, so I would recommend to avoid it.
I would also discourage suffixing them with Model or Data (such as UserModel or UserData) as it does not bring any value and does not follow the common practices of the TypeScript ecosystem.
The Dto suffix can make sense if you have a specific type used for data transfer, such as the one used to send data to the backend or to receive data from the backend. In this case, you can suffix it with Dto to indicate that it's a data transfer object.
Components
We usually called them quite lazily, like UserComponent, HomeComponent, etc.
Removing the suffixes creates naming conflicts when the component name collapses to the same word as the model — UserComponent becomes User, just like the User type.
The fix is semantic naming: describe what the component does or represents in the UI, not that it is a component. The patterns below show how to apply that.
Pages
The suffixless naming confict for components is usually related to routed components.
ProductComponent, DashboardComponent, UserComponent are common names for routed components, but they are not really semantic as they do not describe what the component does, but rather where it is used.
A solution to this conflict is to suffix the feature name with Page, such as UserPage, ProductPage, DashboardPage.
Pageis a common term used to describe a routed component taking most of the document space (most of the time minus the header and footer).
It's also a term used by the Atomic Design methodology, as wrapping multiple related elements.
ng generate component user/user-page@Component({ selector: "app-user-page", templateUrl: "./user-page.html", styleUrls: ["./user-page.scss"],})export class UserPage {}Suffixing the feature name with Page is a good way to indicate that it's a page but it might be specific enough: for a given feature, your application might have multiple pages.
It can be a page about:
- a user profile:
UserProfilePage - a user form:
UserFormPage - a user list:
UserListPage - a user details:
UserDetailsPage
A page often refers to a content taking most of the screen, but sometimes routed components only takes a part of the screen, due to a nested router-outlet.
There is no official or community convention i'm aware of for such a situation. There are two solutions:
- they are carrying a really specific usecase you now there won't be any possible naming conflict, like ProductFormEditor.
- they share a common purpose with some other components, suffix them with
Panel.
Non routed components
Non routed components are components that are not tied to a specific route. They are usually used to display a list of items, a form, a details, etc. That's the most important part of the application.
This guide will focus on some common patterns you can use to name your components.
Display an array of items
It's quite common to display a array of items in a component. Another common way to explain it is to call about a list of items.
But let's divide this into two patterns:
- a simple list (like the Angular Material list)
- a table (like the Angular Material table)
ng generate component user/user-list
ng generate component user/user-tableIf you happen to have dedicated filters or pagination, you can isolate their logic in a dedicated component, using UserListor UserTable as a base to identify their specfic usage:
ng generate component user/user-list-filters
ng generate component user/user-list-pagination
ng generate component user/user-table-filters
ng generate component user/user-table-paginationIf filters and/or pagination are isolated in dedicated components this way rather than being part of List/Page, you can wrap the UserListand the UserListFilters components in a UserExplorer component.
Display a form
You could just suffix the form component with Form such as UserForm. But how they behave depends on the usage: some are meant to be used for creation, some for edition, some for both.
Use these patterns to name your form components:
UserCreateFormUserEditFormUserForm(when meant to be used for both creation and edition)
Services
The same semantic principle applies to services. A service is rarely just User — it has a specific job. Name it for that job.
Services have (or should have) a single responsibility and that's already the case in most projects. A service is mainly used for 2 motivations:
- to share data between different parts of the application (when not provided to an isolated element)
- to isolate some logic which require dependancy injection, such as HttpClient.
Service as an API layer
Even if we could use the HttpClient service directly in the component, isolating the logic in a service has always been a good practice.
Such a good practice is not limited to HttpClientthough, it could be used for any logic that requires dependancy injection to expose a third party API to the application, like a Firebase service or a graphql client.
There are multiple ways to name such a service:
UserApiUserClientUserGatewayUserDataClient
Under the suffixless convention, prefer UserApi over UserApiService — the role is already clear without the extra suffix. Select the pattern that best fits your mindset but stick to it for consistency.
ng generate service user/user-api@Service()export class UserApi { private readonly http = inject(HttpClient);
getUser(id: string): User { return this.http.get<User>(`/api/users/${id}`); }}Service as a state provider
We commonly called 'stores' the elements reponsible to provide a state to the application.
So you can suffix your service with Store to indicate that it's a state provider:
ng generate service user/user-store@Service()export class UserStore { private readonly _user = signal<User | null>(null); public readonly user = this._user.asReadonly();}Some stores are not reated ot the whole application, but to a specific part of the application, even something only provided to a component.
Besides the Store suffix, you should care about its exact context and name it accordingly. If tied to the UserPage, you can name it UserPageStore.
- The
UserStoreis a global store, so it's not tied to a specific component. - The
UserPageStoreis a store tied to theUserPagecomponent.
Conclusion
These recommendations are opinions, not laws. Some teams will prefer Client over Api, skip the Page suffix, or keep Dto types while others drop them. What matters is that you pick the conventions that fit your codebase and apply them consistently.
The best way to make that stick — especially when AI tools generate code for you — is to write your choices down. An AGENTS.md file at the root of your repository gives coding agents a single source of truth for your naming rules, file structure, and patterns. When a convention is documented there, generated components, services, and types are far more likely to match the style your team actually uses.
Pick what works for you, document it, and move on.