Enterprise-grade Angular 17+ Admin Dashboard β Production-ready authentication, CRUD operations, and modern UI/UX patterns.
Secure Admin Portal is a professional, production-ready Angular application demonstrating enterprise architecture patterns, security best practices, and modern UX/UI design principles.
β
Enterprise Authentication β JWT-based login with secure token management
β
Protected Routes β AuthGuard prevents unauthorized access
β
Token Interceptor β Automatically attaches JWT to all API requests
β
CRUD Operations β Create, read, update, delete user records
β
Server-side Pagination β Efficient data handling for large datasets
β
Search & Filter β RxJS debounce, role/status filters
β
State Management β BehaviorSubject + Angular Signals
β
Reusable Components β Table, modal, toast, loader, search bar
β
Modern Design System β Custom CSS variables, responsive layout
β
OnPush Change Detection β Performance-optimized rendering
- Node.js 18+ and npm 9+
- Angular CLI 17+
-
Clone or extract the project
cd secure-admin-portal -
Install dependencies
npm install
-
Start the development server
npm start # or ng serve -
Open in browser
http://localhost:4200
Use these credentials to test the application:
Email: eve.holt@reqres.in
Password: cityslicka
Note: The app uses reqres.in as a mock REST API for demonstration.
secure-admin-portal/
βββ src/
β βββ app/
β β βββ core/ # Singleton services, guards, interceptors
β β β βββ guards/
β β β β βββ auth.guard.ts # Route protection
β β β β βββ no-auth.guard.ts # Prevent authenticated users from login
β β β βββ interceptors/
β β β β βββ auth.interceptor.ts # JWT token attachment
β β β βββ services/
β β β β βββ auth.service.ts # Authentication API calls
β β β β βββ auth-state.service.ts # Global auth state
β β β β βββ toast.service.ts # Notifications
β β β β βββ loader.service.ts # Loading indicators
β β β βββ models/
β β β βββ index.ts # Shared interfaces & types
β β β
β β βββ shared/ # Reusable components, pipes, directives
β β β βββ components/
β β β βββ table/ # Dynamic data table
β β β βββ toast/ # Toast notifications
β β β βββ loader/ # Global & inline spinners
β β β βββ search-bar/ # Debounced search input
β β β βββ form-modal/ # Reusable form modal
β β β βββ confirm-dialog/ # Delete confirmation
β β β
β β βββ features/ # Feature modules (lazy-loaded)
β β β βββ auth/ # Authentication module
β β β β βββ components/
β β β β β βββ login-page/ # Login page
β β β β βββ services/
β β β β βββ auth.routes.ts
β β β β
β β β βββ dashboard/ # Dashboard module
β β β βββ components/
β β β β βββ dashboard-home/ # Shell layout with sidebar
β β β β βββ dashboard-overview/ # Stats & welcome
β β β β βββ user-list/ # CRUD interface
β β β βββ services/
β β β β βββ dashboard.service.ts # API calls
β β β βββ dashboard.routes.ts
β β β
β β βββ app.component.ts # Root component
β β βββ app.config.ts # App configuration
β β βββ app.routes.ts # Main routing config
β β
β βββ environments/
β β βββ environment.ts # Development
β β βββ environment.prod.ts # Production
β β
β βββ styles.scss # Global styles & design system
β βββ index.html # HTML template
β βββ main.ts # Bootstrap
β βββ favicon.ico
β
βββ angular.json # Angular CLI config
βββ tsconfig.json # TypeScript config
βββ package.json # Dependencies
βββ README.md # This file
βββ .gitignore
1. User enters email & password
β
2. LoginComponent sends POST /api/login
β
3. Backend returns JWT token
β
4. AuthService fetches user profile (GET /api/users/2)
β
5. AuthStateService stores token + user data in localStorage
β
6. User redirected to dashboard
All dashboard routes are protected by AuthGuard:
// If not authenticated β redirected to /auth/login
// returnUrl query param preserves intended destination- Stored in:
localStorage(key:sap_auth_token) - Synced on: App initialization (AuthStateService)
- Cleared on: Logout or 401 response
The authInterceptor automatically:
β Attaches JWT token to every request
β Handles 401 (session expired)
β Handles 403 (forbidden)
β Handles network errors
β Shows appropriate toast messages
// No manual header setup needed:
this.http.get('/api/users').subscribe(...);
// Becomes: GET /api/users Authorization: Bearer <token>dashboardService.createUser({
first_name: 'John',
last_name: 'Doe',
email: 'john@company.com',
job: 'Software Engineer',
role: 'editor',
department: 'Engineering'
})dashboardService.getUsers({
page: 1,
per_page: 6,
search: 'john'
})dashboardService.updateUser(userId, {
first_name: 'Jane',
job: 'Senior Engineer'
})dashboardService.deleteUser(userId)// AuthStateService uses BehaviorSubject for backward compatibility
authState.currentUser$.subscribe(user => {
console.log('Current user:', user);
});
authState.isAuthenticated$.subscribe(isAuth => {
console.log('Is authenticated:', isAuth);
});// Signals for reactive updates without subscriptions
const user = authState.user(); // null | AuthUser
const isAuth = authState.isAuthenticated(); // booleantoastService.success('Success', 'Operation completed');
toastService.error('Error', 'Something went wrong');
toastService.warning('Warning', 'Please review');
toastService.info('Info', 'Additional information');loaderService.show('Processing...');
// ... async operation
loaderService.hide();
// Force hide (in case of multiple requests)
loaderService.forceHide();<app-common-table
[columns]="tableColumns"
[data]="userData"
[isLoading]="isLoading()"
[pagination]="paginationConfig"
[sort]="sortConfig"
(sortChange)="onSort($event)"
(pageChange)="onPageChange($event)"
>
<!-- Custom cell templates optional -->
</app-common-table><app-search-input
placeholder="Search users..."
[debounce]="350"
(search)="onSearch($event)"
/>
// Emits after 350ms of inactivityAll components use ChangeDetectionStrategy.OnPush:
@Component({
selector: 'app-example',
changeDetection: ChangeDetectionStrategy.OnPush,
})This disables automatic change detection and requires manual triggers, significantly improving rendering performance.
<app-table
[data]="users"
trackByKey="id" // Uses ID for DOM reconciliation
/>Feature modules are lazy-loaded:
// app.routes.ts
{
path: 'auth',
loadChildren: () => import('./features/auth/auth.routes')
}Search input is debounced to reduce API calls:
// SearchBarComponent
searchControl.valueChanges
.pipe(
debounceTime(350),
distinctUntilChanged()
)
.subscribe(value => this.search.emit(value));| Feature | Implementation |
|---|---|
| JWT Authentication | Bearer token in Authorization header |
| Secure Token Storage | localStorage with key namespacing |
| Route Guards | AuthGuard prevents unauthorized access |
| Session Management | 401 triggers automatic logout |
| XSRF Protection | Built-in Angular XSRF configuration |
| Input Validation | Reactive Forms with Validators |
| Error Handling | Centralized error responses |
npm start
# Starts dev server on http://localhost:4200npm run build:prod
# Creates optimized build in dist/secure-admin-portal/dist/secure-admin-portal/
βββ index.html
βββ styles.css (bundled & minified)
βββ main.js (bundled & optimized)
βββ polyfills.js
βββ ...
Deploy the dist/ folder to:
- Static Hosting: Firebase, Vercel, Netlify, GitHub Pages
- Server: Express, Node.js, AWS S3, Azure Static Web Apps
- Docker: Build Docker image with Angular dist as static assets
export const environment = {
production: false,
apiUrl: 'https://reqres.in/api',
tokenKey: 'sap_auth_token',
};export const environment = {
production: true,
apiUrl: 'https://api.production-server.com/api',
tokenKey: 'sap_auth_token',
};import { environment } from '@environments/environment';
constructor(private http: HttpClient) {
const apiUrl = environment.apiUrl;
const isProduction = environment.production;
}The application is fully responsive:
- Desktop (1024px+) β Full sidebar, multi-column layouts
- Tablet (768px-1023px) β Collapsible sidebar, adjusted grids
- Mobile (< 768px) β Drawer sidebar, single-column layouts
CSS utilities: .hide-mobile, .hide-desktop, .hide-tablet
npm testnpm run e2eTesting setup can be added using Jasmine/Karma or Cypress
| Package | Purpose |
|---|---|
| @angular/common | Common directives, pipes |
| @angular/forms | Reactive Forms |
| @angular/router | Routing & navigation |
| @angular/platform-browser | DOM API |
| rxjs | Reactive programming |
| typescript | Language support |
- Angular Official Docs
- RxJS Guide
- TypeScript Handbook
- Reactive Forms
- HTTP Client
- Routing & Navigation
This is a portfolio/demo project. Contributions are welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License β see LICENSE file for details.
For issues, questions, or suggestions:
- GitHub Issues β Report bugs or feature requests
- Discussions β Ask questions and share ideas
- Email β Contact via project documentation
- Role-based access control (RBAC)
- Advanced analytics dashboard
- Real-time notifications via WebSocket
- Audit logging & activity tracking
- Bulk operations (import/export users)
- Two-factor authentication (2FA)
- Dark/light theme toggle
- Internationalization (i18n)
- End-to-end testing suite
- Storybook component library
Built with Angular 17+, TypeScript, and modern web standards.
An enterprise-ready template for admin dashboards, CRM systems, and management applications.
Last Updated: May 2026
Version: 1.0.0
Status: Production-Ready β