Skip to content

Architecture

One Laravel API, four React apps, a CRM middleware to three Microsoft Dynamics 365 orgs, a PDF service, and payments. If you hold this picture, every flow makes sense.

flowchart TB
subgraph Personas
  P1(Shopper):::person
  P2(Broker / Sales-Manager):::person
  P3(Sales-Man):::person
  P4(Shopper-Admin):::person
  P5(Admin):::person
end
subgraph Frontend["Frontend — Nx monorepo (React 18 · Vite)"]
  A1[Shopper SPA]:::fe
  A2[Broker SPA]:::fe
  A3[Sales-Man SPA]:::fe
  A4[Shopper-Analytics SPA]:::fe
end
BE[Backend API<br/>Laravel 10 · PHP 8.2]:::be
VOY[Voyager admin /admin]:::be
MW[crms-middleware<br/>Laravel 9]:::mw
PDF[PDF service<br/>Node · Puppeteer]:::svc
DB[(MySQL 8)]:::store
RD[(Redis)]:::store
LA{{Azure Logic Apps}}:::ext
D365[(Dynamics 365<br/>Egypt · Oman · Montenegro)]:::ext
PAY[Paymob · Thawani · WSPG]:::ext
TP[Sentry · Firebase · Azure AD · S3 · Infobip · GA]:::ext

P1 --> A1
P2 --> A2
P3 --> A3
P4 --> A4
P5 --> VOY
A1 & A2 & A3 & A4 -->|HTTPS REST · Bearer| BE
BE --> DB
BE -.->|cache/queue| RD
BE -->|OAuth client_credentials| MW
BE -->|HTTPS| PDF
BE -->|HTTPS| PAY
BE --> TP
PAY -.->|webhook callback| BE
MW -->|writes: Logic App| LA
MW -->|reads: OData v9.1/v9.2| D365
LA --> D365
classDef person fill:#e7eef6,stroke:#2563A8,color:#0b1b2b;
classDef fe fill:#e7eef6,stroke:#2563A8,color:#0b1b2b;
classDef be fill:#dff0f0,stroke:#0C7C84,color:#0b1b2b;
classDef mw fill:#efe7f7,stroke:#7A4FB5,color:#0b1b2b;
classDef svc fill:#f7efdc,stroke:#B7791F,color:#0b1b2b;
classDef store fill:#eceff1,stroke:#5B6B7A,color:#0b1b2b;
classDef ext fill:#f6e7dc,stroke:#C4622D,color:#0b1b2b;
Orascom Portals — container view (current)
  • One backend, many frontends. Four React SPAs (one per persona group) from a single Nx workspace all talk only to the Laravel backend — never to a CRM directly.
  • The backend is the hub. Business logic, auth, payment orchestration, the Voyager admin, and all outbound integrations.
  • CRM access goes through the middleware. The crms-middleware service is the only thing that talks to the CRMs.
Repo Stack Prod?
backend Laravel 10 · PHP 8.2 · MySQL 8 · Passport + Sanctum · Voyager
frontend Nx · React 18 · TypeScript · Vite · Yarn 1 — 4 apps + 5 libs
crms-middleware Laravel 9 · PHP 8.1 — the CRM proxy
backend-pdf-service Node 20 · Express · Puppeteer · TypeScript
crm-mock Laravel 12 · SQLite — dev CRM stand-in dev only
middleware-package PHP Composer library — proposed replacement for crms-middleware not wired

From Robusta’s handover documentation, the production system runs on AWS:

flowchart TB
U(Client) --> DNS(DNS) --> WAF[AWS WAF & Shield]
WAF --> ALB[Application Load Balancer]
subgraph VPC
  subgraph Public
    ALB
    NAT[NAT Gateway]
  end
  subgraph Private
    FE[Frontend — AWS Amplify]
    BEASG[Backend EC2 AutoScaling]
    CRMASG[CRM EC2 AutoScaling]
    RDS[(RDS MySQL · Multi-AZ)]
    REDIS[(Redis)]
    S3[(S3 media)]
    CF[CloudFront]
  end
end
ALB --> FE
ALB --> BEASG
ALB --> CRMASG
BEASG --> RDS
BEASG --> REDIS
BEASG --> CF --> S3
CRMASG --> RDS
GL[GitLab] -.->|per handover docs · unverified| CP[CodePipeline] -.-> CD[CodeDeploy] -.-> BEASG
Production topology (AWS)
  • Frontend = AWS Amplify (serverless static hosting). Backend + CRM = EC2 AutoScaling groups (t3a.small) behind the ALB. DB = RDS MySQL (db.t3.small, Multi-AZ). Plus Redis, S3 (media via CloudFront), WAF + Shield, CloudWatch.
  • Branch → environment: develop → staging, uat → UAT, main → production.