Trader-FE
Trader-FE is both the browser application and its small backend-for-frontend, or BFF. The browser side is a React Router application written in TypeScript. The BFF is a Rust Axum service. A lightweight production web server serves the compiled application and forwards same-origin API traffic to the BFF.
This separation gives the browser one stable API origin. It also keeps upstream host names, CORS concerns, and proxy details out of page components. The BFF is intentionally thin: business rules remain in Trader-BE and analysis rules remain in News-Analyzer.
Browser routes and user journeys
| Route | Who uses it | What it does |
|---|---|---|
/ | Everyone | Product landing page and entry to search or authentication |
/login, /register, /logout | Everyone | Email/password and Google authentication, session creation, and session cleanup |
/home | Signed-in users | Search dashboard, popular assets, recent activity, platform information, and preview content |
/details | Everyone for public data; sign-in needed to analyze | Asset identity, market profile, chart, news, related assets, and analysis controls |
/result | Signed-in users | Analysis result presentation when reached through the result flow |
/history | Signed-in users | Paginated saved analyses, filtering, reopening, and deletion |
/credits | Signed-in users | Balance, active packs, PayOS checkout, payment status, and purchase history |
/settings | Signed-in users | Disclaimer acceptance and stored user preferences |
/admin | Administrators | Dashboard metrics, accounts, cache settings, credit packs, and all purchase history |
/about, /disclaimer, /terms, /privacy, /refund | Everyone | Product and legal information |
| Any unknown path | Everyone | Coming-soon or fallback page |
The route table itself does not wrap every signed-in page in a single route-level protected layout. Individual screens and shared layout components therefore participate in access control. The administrator route is explicitly nested under the administrator guard, which checks the stored role.
Asset discovery and detail page
Search requests go through the BFF to Trader-BE. Results can combine conventional securities and cryptocurrency symbols. Choosing a result opens the details route with the selected symbol in the query string and can add it to the signed-in user’s recent-search list.
The details screen coordinates several independent requests so basic market information does not wait for AI analysis. It loads asset metadata and an enriched market profile, live price, historical chart points, related assets, and the free news preview. The TradingView-style chart component presents different ranges and intervals using Trader-BE’s history endpoint.
The news section shows article metadata, per-item sentiment, topic categories, impact markers, source links, images when available, overall counts, and trending topics. This is a free deterministic preview, not the paid investment analysis.
Starting and viewing an analysis
The user must confirm the cost before a new analysis begins. The frontend then initiates the analysis flow.
First it initializes a News-Analyzer context through Trader-BE. This returns a context identifier and normalized symbol. Second it submits the paid overview request (POST /api/v1/analyze), which strictly requires authentication and returns an HTTP 202 ACCEPTED response containing the pending analysis identifier.
The frontend subscribes to real-time updates and runs a concurrent polling loop (GET /api/v1/analysis/history/:id every 2.5s with a 1.5s WebSocket fallback timeout). As each research stage completes, Redux (news.slice.ts) updates completedStages and runningStages, unlocking sub-tabs and animating stage progress in real time. When analysis finishes, the final payload is loaded into the Redux state.
The result is organized into overview, fundamentals, valuation, risks, scenarios, historical context, and evidence-oriented content. Supporting tabs can also be fetched lazily using the context identifier. Responses are retained in a page-local map, so they survive tab switching. Starting a new analysis clears the old tab cache and resets active stages.
If Trader-BE reports a low-confidence refund, the analysis screen displays that fact. A 402 response leads the user toward credit management. An expired or unavailable context requires the analysis initialization to run again.
State ownership
Redux holds cross-page application state: authentication, user information, credits, analysis overview, history, and settings. Component state holds transient presentation details such as an open modal, the selected tab, pagination inside a card, and tab responses that belong only to the current asset view.
Authentication data is safely persisted in browser local storage via auth.slice.ts using centralized token getters (getStoredAccessToken and getStoredRefreshToken). This prevents user profile updates from overwriting valid local tokens. Logging out explicitly clears this data (clearPersistedAuthData) and resets Redux. Because local storage is readable by browser JavaScript, cross-site scripting prevention is a security requirement; the frontend must not render unsanitized third-party HTML.
Request and session behavior
The shared network service (network.services.ts) dynamically retrieves valid access_tokens from local storage and ensures Authorization: Bearer <token> is attached to all API requests. On a 401 response, it initiates token refresh when a refresh token is available. Only one refresh runs at a time; other failed requests join a queue and retry after the new token arrives. If refresh fails, navigation moves to login.
Most service methods use the shared network layer directly. Analysis and authentication methods add abort-based timeouts. Analysis defaults to 300 seconds and can read a runtime frontend value named TRADER_BE_TIMEOUT_MS. Authentication defaults to 30 seconds.
The current analysis timeout helper accepts an external abort signal but does not connect that signal to the internal fetch controller. It notices external cancellation only after an error is raised. Callers should not assume an external abort immediately cancels the network request.
Credits and checkout experience
The header and credit page obtain the current balance for the authenticated account. Administrators are represented as unlimited rather than as a numeric balance. The credit page lists active packs, derives display values such as price per credit, and creates a PayOS payment through the protected API. It can query or cancel a pending order and lists completed and pending purchase records.
The frontend does not grant credits and does not trust a browser-side payment result. PayOS completion must reach Trader-BE’s webhook, which updates the durable transaction and balance.
History and settings
History is server-owned. The frontend requests a page, optionally filters by asset, opens a user-owned detail, and can delete that record. Analysis history may be unavailable in database-free development mode even if the live analysis itself succeeds.
Settings currently store disclaimer acceptance and a flexible preferences object. The server returns safe defaults when no row exists. The browser uses the disclaimer state to decide whether acknowledgement is required.
Administration
The administrator screen has four main areas. Dashboard shows aggregate account and purchase information and exposes cache controls. Accounts supports list, detail, and status changes. Credit packs supports creation, editing, ordering, activation, popularity badges, and deletion. Purchase history lists transactions across users.
The browser’s administrator guard improves navigation and presentation, but it is not the security boundary. Trader-BE must and does enforce the role for administrator endpoints.
BFF behavior
The BFF defines an explicit route for each browser API operation. It forwards method, request body, query string, authorization header, and relevant response headers to Trader-BE. It also has a health endpoint. Its upstream base address is deployment configuration, while the browser always calls the same origin under /api/v1.
The BFF contains no credit calculation, asset ranking, analysis, payment settlement, or authorization policy. Its role is contract adaptation and transport. If the BFF is healthy while Trader-BE is unavailable, user requests still fail with an upstream error.
Internationalization and presentation
The application has English and Vietnamese translation catalogs. Shared formatting helpers handle dates, numbers, money, percentages, and analysis terminology. Legal copy and financial labels should be added to both catalogs so language switching does not expose raw translation keys.
Frontend operational checks
After a frontend or API-contract change, verify anonymous asset search and news preview, login and refresh, analysis confirmation and 402 handling, all lazy tabs, history ownership, credit checkout status, logout cleanup, Vietnamese and English rendering, administrator denial for a normal user, and administrator functions for an admin user. Also verify a direct browser refresh on every route because production routing must return the application shell for client-side paths.