Mogtrade is a trading platform web application that connects to various stock exchanges, permitting users to perform trades on the stock market (stocks, options, futures, etc.). This codebase is the Angular frontend UI, built with Angular 22 and integrating with a RESTful API backend as the source of truth.
- Framework: Angular 22 (standalone components, default in Angular v20+)
- Rendering: SSR/SSG enabled via
@angular/platform-serverandexpress - Styling: Tailwind CSS v4
- State Management: Angular Signals with NgRx SignalStore
- Forms: Signal Forms (
@angular/forms/signals) for new forms; Reactive Forms as alternative - HTTP: RxJS for reactive programming, with orval-generated typesafe SDK
- Authentication: JWT bearer tokens with refresh token rotation, FingerprintJS for device fingerprinting (
@fingerprintjs/fingerprintjs) - Build Tool: pnpm v11
- UI Library: spartan-ng components (similar to shadcn-ui for Angular)
mogtrade/
├── src/
│ ├── app/ # Angular application code
│ │ ├── app.ts # Main application entry point
│ │ ├── app.html # Root template
│ │ ├── app.config.ts # Client-side configuration
│ │ ├── app.config.server.ts # Server-side configuration
│ │ ├── app.routes.ts # Client-side routes
│ │ ├── app.routes.server.ts # Server-side routes
│ │ ├── app.spec.ts # Test configuration
│ │ ├── models/ # Application models (e.g., Principal)
│ │ ├── store/ # NgRx SignalStore state management
│ │ ├── adapters/ # Adapters for external services
│ │ ├── components/ # Reusable standalone components
│ │ ├── interceptors/ # HTTP interceptors
│ │ ├── guards/ # Route guards
│ │ ├── layouts/ # Page layout components
│ │ ├── pages/ # Page-level components
│ │ └── utils/ # Utility functions
│ ├── main.ts # Client-side entry point
│ ├── main.server.ts # Server-side rendering entry point
│ ├── server.ts # Express server setup
│ ├── index.html # HTML template
│ └── styles.scss # Global styles
├── angular.json # Angular CLI configuration
├── tsconfig*.json # TypeScript configurations
├── package.json # Dependencies and scripts
├── pnpm-lock.yaml # Lock file
└── tailwind.config.* # Tailwind CSS configuration
├── orval.config.ts # API client generation configuration
└── components.json # spartan-ng component configuration
src/app/: Contains all Angular components, services, and modulessrc/app/app.html: Root component templatesrc/app/app.config.ts: Client-side application configurationsrc/app/app.config.server.ts: Server-side rendering configurationsrc/app/app.routes.ts: Client-side routing configurationsrc/app/app.routes.server.ts: Server-side routing configurationsrc/main.ts: Bootstrap the application in the browsersrc/main.server.ts: Bootstrap the application for server-side renderingsrc/server.ts: Express server for serving the SSR applicationsrc/store/: NgRx SignalStore state management (auth, device, upcoming: wallets)libs/sdk/: Orval-generated typesafe Angular SDKlibs/ui/: Spartan-ng UI components (added incrementally)
- Standalone Components: All components are standalone (default in Angular v20+). No NgModules.
- Signal-Based State: Use signals for local component state and
computed()for derived state. NgRx SignalStore for global state management. - State Stores Currently Implemented:
AuthStore: Manages authentication state (principal, access token, refresh token, signedIn status). UseswithState,withMethods,withEventHandlers,withHooks. Principal model extracted from JWT claims (id, displayName, email, emailVerified, photo).DeviceStore: Manages device fingerprint state. UseswithStateandwithMethods.wallets: Next store to be implemented.
- Lazy Loading: Feature routes should use lazy loading.
- Reactive Forms: Signal Forms (
@angular/forms/signals) for new forms. Pattern demonstrated inLoginPageusingform(),validateStandardSchema, and signal-based submission. All new forms should follow this pattern. - SSR/SSG: Server-Side Rendering and Static Site Generation enabled. Auth-required pages render on the client to avoid SSR hydration issues.
- API Integration: RESTful API backend is the source of truth. Orval generates a typesafe Angular SDK from the OpenAPI spec. All data fetching goes through the generated SDK.
- API Interceptors:
apiBearerTokenInterceptor: Modifies API URLs based on executing environment, provides bearer token handling.apiDeviceIdInterceptor: Addsx-d-idheader with device fingerprint from FingerprintJS.
- Authentication Flow:
- Login via
POST /api/v1/auth/login/credentialendpoint. - Successful response contains access token and refresh token.
- Tokens stored in
localStorageAND NgRx SignalStore state. - Refresh token rotation handled in
signed-in-guard.ts(note: recommended to move to interceptor for broader applicability). - FingerprintJS used for device fingerprinting (
@fingerprintjs/fingerprintjs).
- Login via
- Accessibility: Must pass AXE checks and follow WCAG AA minimums.
- Component Guidelines:
- Small, focused components with single responsibility.
input()andoutput()functions instead of decorators.- Native control flow (
@if,@for,@switch) instead of*ngIf,*ngFor,*ngSwitch. NgOptimizedImagefor all static images.- No
ngClass/ngStyle— use class/style bindings instead. - No
@HostBinding/@HostListener— usehostobject instead. - Use
NgIconfrom@ng-icons/corefor icons. Hlm*components from@spartan-ng/helmfor styled primitives.
- Available Scripts
| Script | Description |
|---|---|
dev |
Start development server (ng serve) |
build |
Build the application (ng build) |
watch |
Watch for changes and rebuild (ng build --watch --configuration development) |
test |
Run tests (ng test) |
serve:ssr |
Serve the SSR application (node dist/mogtrade/server/main.js) |
sdk:update |
Update the orval-generated SDK |
- TypeScript strict mode enabled
- Prettier for code formatting
- Vitest for testing
- JSdom for test environment
- Tailwind CSS v4 used for styling — no custom CSS framework beyond that
- UI components added incrementally via
ng generate @spartan-ng/cli:ui <name-of-component> - Orval SDK generated from:
https://github.com/brinestone/mogtrade-engine/raw/refs/heads/master/build/smithy/source/openapi/Auth.openapi.json
Private project — all rights reserved.