Angular's modular design and NgRx state management allow for the maintainable, performant, and collaborative development of even intricate applications with varied user roles and features. (Part 1, ⏱️ Estimated reading time: 5 minutes)
Introduction to the AdminPortal
Meet AdminPortal, a web application that helps organizations manage users and resources. Like many real-world apps, AdminPortal supports different areas for different people:
- Administrators need tools to manage users.
- Managers need dashboards to see team activity.
- Regular users need access to their profiles and basic functions.
Let's not cram all of this into one big chunk of code. That'd be chaos. Instead, we broke the application into smaller, focused pieces called modules. This improves maintainability, performance, and clarity.
In this article, you'll get the high-level tour; a look at how AdminPortal is structured, how its pieces work together, and how NgRx ties it all up without going too deep into technical weeds.
Application Architecture and Module Structure
Core Modules
AdminPortal is built with five main modules:
App Module: The main shell that wires everything together, routing, bootstrap logic, and core services.
-
Core Module: Hosts essential singleton services used app-wide:
- Authentication service
- HTTP interceptors (for auth tokens, error handling)
- Global error and session management
-
Shared Module: Reusable, stateless building blocks:
- UI components (buttons, cards, inputs)
- Pipes, directives
- TypeScript interfaces and helper models
Layout Module: Defines the global layout (header, footer, sidebar).
-
Feature Modules:
- Auth Module: Login, registration, password reset
- Dashboard Module: Role-based dashboards and user profiles
- Admin Module: Admin-only tools and user management
Module Interaction and Lazy Loading
The power of this structure lies in how the pieces fit:
By implementing lazy loading, feature modules are not loaded upfront but rather when they are navigated. This means that if a user never accesses the admin area, its code will not be loaded into the application.
A key aspect is the limited sharing; only Core and Shared modules are accessible throughout the application, ensuring that Feature modules remain isolated and do not directly depend on each other.
NgRx for Centralized and Shared State. NgRx centralizes application-wide data (e.g., user authentication, roles) in a single store, leading to a shared state with well-defined boundaries.
Simplified Module Map:
App Module
├── Core Module (services, guards)
├── Layout Module (header, footer, sidebar)
├── Shared Module (components, pipes, models)
└── Feature Modules
├── Auth Module (login, registration)
├── Dashboard Module (user dashboard)
└── Admin Module (user management)
Key Features and Role-Based Flow
Authentication System
Auth is handled through NgRx effects and a shared authentication service:
- Users log in via the Auth Module
- Tokens are stored securely and used with API requests
- Session expiration is monitored; expired tokens trigger logout
The authentication state is global:
- The Layout Module updates the header with the user profile
- Role-based routing and guards unlock or hide features
Role-Based Access Control (RBAC)
AdminPortal defines three main roles:
- Administrators – Full system access
- Managers – Read-only access to team metrics
- Users – Personal profile and usage only
RBAC affects:
- Navigation: Sidebar and header options change per role
- Routing: Unauthorized attempts trigger redirection
- UI Features: Certain buttons or views are hidden based on the role
Dashboards Tailored by Role
Each user gets a personalized dashboard:
- Admin Dashboard – System-wide metrics, shortcuts to admin tools
- Manager Dashboard – Team statistics and limited admin features
- User Dashboard – Personal usage, profile, recent activity
These dashboards reuse many components but differ in data and access logic.
User Journeys
Emily (Administrator)
When Emily logs in:
- She submits her credentials via the login form.
- The Auth Module verifies and stores her profile (including the admin role) in NgRx.
- She's redirected to the Admin Dashboard.
- The Layout Module updates to show admin-specific navigation.
- She clicks "User Management" to:
- Edit user profiles
- Change permissions
- Disable accounts
- Her changes are synced across the app via NgRx and backend API calls.
Siddarth (Regular User)
When Siddarth logs in:
- He logs in through the same Auth Module.
- His user role is stored in the NgRx store.
- He’s routed to the User Dashboard.
- The Layout Module hides admin links.
- He updates his profile and uses basic features.
- If he attempts to access
/admin
, he’s redirected to/dashboard
.
Development Best Practices
Clear Module Boundaries
Each module focuses on one area:
- Auth handles login and tokens
- Admin handles system-level features
- Dashboard manages user-specific views
This makes testing, maintenance, and team handoffs smoother.
Shared State with NgRx
NgRx handles cross-cutting concerns:
- Auth state
- Current user profile
- Global settings (e.g., dark mode preference)
This avoids tightly coupling feature modules.
Route Guards & Smart Routing
- Each module has a route config
- Route guards enforce login and role-based access
- Lazy loading keeps the app lean
Example: Visiting /admin/users
- App checks login status
- Verifies admin role
- Grants or redirects accordingly
Shared Components & Design System
The Shared Module powers UI consistency:
- Buttons, inputs, cards, alerts
- Theming and accessibility
- Form controls behave the same across features
Angular Modularity Principles in Action
AdminPortal follows key design principles:
- Single Responsibility: One purpose per module/component/service
- Encapsulation: Modules expose only what’s needed
- Reusability: Components and services are flexible, not hardwired
- Progressive Loading: Users load only what they need
Final Thoughts
AdminPortal shows how modular Angular apps with NgRx can scale smoothly:
- Teams can work in parallel without stepping on each other
- Apps perform better with lazy loading
- Features are isolated, testable, and easier to maintain
- Role-based logic is secure and user-friendly
The takeaway? Use Angular’s modular architecture intentionally. Pair it with NgRx to manage a shared state without tight coupling. The result is a maintainable, real-world-ready application that evolves with your users and developer team.
Top comments (0)