6.9 KiB
AGENTS.md — Aeroflot.Flights.Web
Quick Start
# Install dependencies
pnpm install
# Development servers
pnpm dev # Modern.js on :8081
pnpm dev:full # Proxy on :8080 (API forwarding via curl to bypass WAF)
# Build targets
pnpm build:standalone # SSR server at dist/standalone/
pnpm build:remote # MF remote at dist/remote/ (with mf-manifest.json)
pnpm build:both # Both targets
# Quality checks (run in order)
pnpm typecheck
pnpm lint
pnpm test
pnpm test:coverage
pnpm bundle-size # CI gate: total gzip ≤ 2000 kB
pnpm check-coverage # CI gate: line coverage ≥ 65%
# E2E tests
pnpm test:e2e # React app (port 8080)
pnpm test:e2e:angular # Angular app (port 4203)
Current State
React 18 SSR application built with Modern.js 2.70.8 (Rspack bundler) and Module Federation 2.3.3. The app is a remote frontend component embeddable in the customer's channel apps (Web, PWA).
Stack: Modern.js 2.70.8, React 18.2, Rspack, Module Federation 2.3.3, i18next (9 languages), PrimeReact, Leaflet, SignalR, OpenTelemetry, Vitest, Playwright.
Source: src/ (file-based routing under src/routes/). Legacy Angular 12 SPA in ClientApp/ (read-only reference, not deployed).
Builds: pnpm build:standalone (SSR server at dist/standalone/), pnpm build:remote (MF remote at dist/remote/ with mf-manifest.json).
Dev: pnpm dev (Modern.js on :8081), pnpm dev:full (proxy on :8080 with API forwarding via curl to bypass WAF).
Known constraint: Modern.js 3.x upgrade is blocked by @module-federation/modern-js ESM incompatibilities (broken __filename/require in ESM bundles, missing api.modifyWebpackConfig in Rsbuild 2.0). React Router v7 future flags are enabled to suppress deprecation warnings.
Contractual Requirements
The following are contractual hard constraints for the remote frontend component.
1. Tech Stack
- ModernJS (SSR) for the frontend framework.
- Module Federation 2.0. Any bundler with MF 2.0 support is acceptable: Webpack 5, Rsbuild, Rspack, or Vite.
- Must emit
mf-manifest.jsonathttps://<domain>/mf-manifest.jsonexposing components and logic. Reference: https://module-federation.io/guide/basic/webpack.html. - React 18+, Concurrent Mode compatible.
<Suspense>support required when async loading is used.- Component bodies must be side-effect free — no
fetchoutsideuseEffect. - Dynamic imports must use
React.lazy().
2. Data & Integrations
- Consumes customer REST APIs, JSON payloads only.
- Rendered data must stay consistent with API responses (no stale state leaking into the UI).
3. Performance
- Must sustain 100 RPS.
4. Availability & Fault Tolerance
- VMs hosting the component must be geographically distributed.
- 24/7/365 availability; recovery time ≤ 6 hours after infra is restored.
5. Security
- Component must be isolated — no attack surface exposed to other components of the host site.
6. SEO & Accessibility
- SEO optimization required.
- Render microdata: JSON-LD and OpenGraph.
- Web analytics integrations: Yandex.Metrica, CTM, Variocube, Key-Astrom (Dynatrace).
7. Cross-Platform
- Embeddable in multiple channel apps (Web, PWA).
- Fully responsive ("fluid") layout across all screen sizes.
8. Logging & Monitoring
- Frontend log collection in a customer-specified format, shipped to the customer's log aggregation system.
- System event monitoring with export to a metrics aggregator.
9. Module Structure
- Must conform to the customer's standard remote frontend module structure for uniform deployment.
10. Design
- Implement against customer-provided mockups using the customer's design system.
- Must embed other customer remote components when available.
Architecture
Source structure:
src/routes/— File-based routing (React Router v7)src/features/— Feature modules (online-board, schedule, flights-map, popular-requests)src/ui/— Reusable UI primitives (never import routes/mf from here)src/shared/— Cross-cutting concerns (API client, SignalR, storage, hooks)src/observability/— Logger, metrics (OTel), analyticssrc/i18n/— Internationalization (9 languages)
Entry points:
src/routes/page.tsx— Root redirect to/{lang}/onlineboardsrc/routes/layout.tsx— Root layout with global providerssrc/routes/[lang]/layout.tsx— Locale-scoped layout with i18n
Module Federation:
- Remote name:
aeroflot_flights - Exposes:
./OnlineBoard,./Schedule,./FlightsMap,./PopularRequests - mf-manifest.json at
https://<domain>/mf-manifest.json
Critical Constraints
-
Side-effect-free components — No
fetchoutsideuseEffect. API calls viaApiClientfrom context. -
Dynamic imports — Use
React.lazy()for code splitting. Wrap browser-only components (Leaflet) inClientOnly. -
SSR safety — SignalR (
@microsoft/signalr) is dynamically imported. Never import in SSR bundle (routes/, server/). -
Layered architecture — Enforced by ESLint:
features/→ cannot importroutes/ormf/ui/→ cannot importfeatures/,routes/,mf/shared/→ cannot importfeatures/,routes/,mf/,observability/observability/→ cannot importfeatures/,routes/,mf/
-
Restricted imports (ESLint rules):
- OTel SDK → use
@/observability/metrics/otel(getMeter/getTracer) - react-i18next → use
@/i18n/provider - localStorage/sessionStorage → use
@/shared/storage
- OTel SDK → use
-
Environment variables — Read via
getEnv()from@/env/index.ts. SSR injectswindow.__ENV__.
Dev Server Details
- Port 8081 — Modern.js dev server (SSR + HMR)
- Port 8080 —
pnpm dev:fullproxy with:/api/*and/flights/*→https://flights.test.aeroflot.ru(via curl to bypass WAF)/*→ Modern.js on 8081
Testing
- Unit tests — Vitest (globals enabled, V8 coverage)
- E2E tests — Playwright (baseURL:
http://localhost:8080) - Angular E2E — Separate config for legacy app (port 4203)
Coverage gates:
- Line coverage ≥ 65%
- Bundle size (gzip) ≤ 2000 kB for remote target
Build Artifacts
dist/standalone/— SSR server (Node entrypoint)dist/remote/— MF remote withmf-manifest.jsondist/remote/static/js/— JS bundles for bundle-size gate
Deployment
- Standalone — Dockerfile.react (Node 24-slim, serves SSR)
- Remote — Dockerfile.remote (nginx serving static files)
- CI/CD:
.github/workflows/ci.yml,.github/workflows/deploy.yml
Commit Rules
- Never add
Co-Authored-Bylines to commit messages. - Commit messages in English, concise, focused on "why" not "what".
- Commit autonomously when changes are complete and stable — no need to ask for permission. Group related edits into logical commits. Still ask before pushing, force-pushing, or any destructive git operation.