Let’s continue developing step-by-step JavaScript full stack real world business system for transportation logistics (full table of contents here). Now we can move from backend development to frontend development . This article describes the implementation of two tasks from the first stage of the project plan for developing the ‘Awesome Trucks Company System’:
- Creating basic app сomponents
- Setting up a global styles structure
to create main app toolbar and navigation, prepare for frontend authentication development and achieve the result shown in the mockup below:
The implementation of this mockup started from installation of Angular Material library
npm i --save @angular/material
and then install angular material fonts
npm i @material-design-icons/font
Generate scss library for styles configuration
npx nx g @nx/angular:library scss \ --prefix nav \ --importPath=@nav/frontend/ui-style \ --tags type:ui,scope:frontend \ --directory=libs/frontend/ui/ui-style \ --unitTestRunner=none \ --projectNameAndRootFormat=as-provided
And create a basic structure for styles folders and files:
And set up libs/frontend/ui-style/src/lib/scss/style.scss
@charset 'utf-8'; @import 'vendors'; @import 'abstract'; @import 'base'; @import 'components'; @import 'layout';
add style libraries to apps/frontend/project.json
"styles": [
"apps/frontend/src/styles.scss",
"node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"node_modules/@material-design-icons/font/index.css"
],
"stylePreprocessorOptions": {
"includePaths": ["libs/frontend/ui/ui-style/src/lib/scss"]
},
and update apps/frontend/src/styles.scss
@import "style";
finally update libs/frontend/ui/ui-style/src/lib/scss/base/_global.scss
html, body {
height: 100%;
margin: 0px;
}
body {
font-family: Roboto, "Helvetica Neue", sans-serif;
*{
margin: 0px;
padding: 0;
outline: none;
border: none;
box-sizing: border-box;
}
}
Now we are ready to generate basic ui components
Generate Home component:
npx nx g @nx/angular:component home \ --prefix mtfs \ --directory=libs/frontend/ui/ui-components/src/lib/home \ --style=scss \ --nameAndDirectoryFormat=as-provided
update apps/frontend/src/app/app.routes.ts to add home-component route
import { Route } from '@angular/router';
export const appRoutes: Route[] = [
{
path: '',
async loadComponent() {
const c = await import('@nav/frontend/ui-components');
return c.HomeComponent
}
}
];
Generate Header component:
npx nx g @nx/angular:component header \ --prefix mtfs \ --directory=libs/frontend/ui/ui-components/src/lib/header \ --style=scss \ --nameAndDirectoryFormat=as-provided
Update HeaderComponent to add Angular Material modules and methods for control buttons:
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import {MatToolbarModule} from '@angular/material/toolbar';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import {MatTooltipModule} from '@angular/material/tooltip';
import { MatMenuModule } from '@angular/material/menu';
import { SideNavService } from '@mtfs/frontend/utils';
@Component({
selector: 'mtfs-header',
standalone: true,
imports: [
CommonModule,
MatToolbarModule,
MatButtonModule,
MatIconModule,
MatMenuModule,
MatTooltipModule
],
templateUrl: './header.component.html',
styleUrl: './header.component.scss',
})
export class HeaderComponent {
constructor(
private sidenav: SideNavService,
){}
logout(){
console.log('logout');
}
toggleMenu(){
console.log("toggle")
this.sidenav.toggle();
}
displayProfile(){
console.log('displayProfile');
}
}
Update HeaderComponent template :
<mat-toolbar class="mat-elevation header" color="primary">
<!--side navigation toggle button-->
<button mat-icon-button matTooltip="Menu" color="white" aria-label="Main menu"
(click)="clickMenu()" >
<mat-icon aria-hidden="false" fontIcon="menu">menu</mat-icon>
</button>
<!--app name or logo-->
<span class="logo">Awesome Trucks Company</span>
<span class="example-spacer"></span>
<!--user's profile button-->
<button mat-icon-button matTooltip="User's profile" color="white" aria-label="User's profile"
class="material-symbol-outlined" (click)="displayProfile()">
<mat-icon aria-hidden="false" fontIcon="person">person</mat-icon>
</button>
<!--logout button-->
<button mat-icon-button matTooltip="Logout" color="white" aria-label="Main menu" (click)="logout()">
<mat-icon aria-hidden="false" fontIcon="logout">logout</mat-icon>
</button>
</mat-toolbar>
Create SideNavService to open and close side navigation menu by clicking menu button from header toolbar
generate libs/frontend/utils/ui library
npx nx g @nx/angular:library services \ --prefix mtfs \ --importPath=@mtfs/frontend/utils \ --tags type:utils,scope:frontend \ --directory=libs/frontend/utils \ --projectNameAndRootFormat=as-provided
generate SideNavService in libs/frontend/utils/ui library
npx nx generate @schematics/angular:service \ --name=side-nav --project=frontend \ --path=libs/frontend/utils/src/lib/services \ --no-interactive --dry-run
update SideNavService
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SideNavService {
public sideNaveToggleSubject: BehaviorSubject<any> = new BehaviorSubject(null);
public toggle(){
return this.sideNaveToggleSubject.next(null);
}
}
update HeaderComponent libs/frontend/ui-components/src/lib/header/header.component.ts to add toggleMenu()
toggleMenu(){
this.sidenav.toggle();
}
update update HomeComponent
import { Component, OnInit, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import {MatSidenavModule} from '@angular/material/sidenav';
import { MatSidenav } from '@angular/material/sidenav';
import { SideNavService } from '@mtfs/frontend/utils';
@Component({
selector: 'mtfs-home',
standalone: true,
imports: [
CommonModule,
MatSidenavModule],
templateUrl: './home.component.html',
styleUrl: './home.component.scss',
})
export class HomeComponent implements OnInit {
@ViewChild('sidenav', {static:true}) public sidenav!: MatSidenav;
constructor(
private sideNavService: SideNavService
){}
ngOnInit(){
this.sideNavService.sideNaveToggleSubject.subscribe(()=>{
this.sidenav.toggle();
})
}
}
update HomeComponent template
<mat-sidenav-container class="container">
<mat-sidenav #sidenav mode="side">
<mat-nav-list>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<div>
<router-outlet> </router-outlet>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
In accordance with project decisions, our system will use role-based access to information within the framework of a single monolithic frontend application. Therefore, a side navigation menu will be created for each role. As part of the full stack template, navigation panels for User and Admin roles will be sufficient
generate NavigationUser component:
npx nx g @nx/angular:component navigation-user \ --prefix mtfs \ --directory=libs/frontend/ui/ui-components/src/lib/navigation-user \ --style=scss \ --nameAndDirectoryFormat=as-provided
generate NavigationAdmin component
npx nx g @nx/angular:component navigation-admin \ --prefix mtfs \ --directory=libs/frontend/ui/ui-components/src/lib/navigation-admin \ --style=scss \ --nameAndDirectoryFormat=as-provided
This components will be used further to implement Role Based Access Control
Error Message Components
generate ErrorPages library
npx nx g @nx/angular:library error-pages \ --prefix mtfs \ --importPath=@mtfs/frontend/error-pages \ --tags type:ui,scope:frontend \ --directory=libs/frontend/ui/error-pages \ --projectNameAndRootFormat=as-provided
generate NotFoundComponent
npx nx g @nx/angular:component not-found \ --prefix mtfs \ --directory=libs/frontend/ui/error-pages/src/lib/not-found \ --style=scss \ --nameAndDirectoryFormat=as-provided
generate ForbiddenComponent
npx nx g @nx/angular:component forbidden \ --prefix mtfs \ --directory=libs/frontend/ui/error-pages/src/lib/forbidden \ --style=scss \ --nameAndDirectoryFormat=as-provided
generate ServerErrorComponent
npx nx g @nx/angular:component server-error \ --prefix mtfs \ --directory=libs/frontend/ui/error-pages/src/lib/server-error \ --style=scss \ --nameAndDirectoryFormat=as-provided
delete error-page folder and update libs/frontend/ui/error-pages/src/index.ts
export * from './lib/forbidden/forbidden.component'; export * from './lib/not-found/not-found.component'; export * from './lib/server-error/server-error.component';
run frontend application to show results
nx serve frontend
Summary and conclusions
This article describes the initial steps in creating a front-end application for building a JavaScript full stack boilerplate and for further development of the Awesome Trucks Company system. We created a set of basic user interface components, such as:
- HomeComponent
- HeaderComponent with toolbar
- Navigation User component
- Navigation Admin component
We also installed Angular Material and Material Fonts, set up SCSS files and folder structure, and created a SidNave Service to show and hide the side navigation menu panel. Additionally, we generated components for error messages such as:
- NotFoundComponent for routes that not found
- ForbiddenСomponent for cases when the route is not available for the current user’s role
- ServerErrorComponent for other server errors
So, now we are ready to mark tasks “Сreate basic app-components” and “Setup global styles structure” as completed and proceed to create frontend cookie-based authentication.
Discover more from More Than Fullstack
Subscribe to get the latest posts sent to your email.

