Skip to content

K. Recommended Target Architecture

← Back to README


Target: Monorepo with npm Workspaces + Turborepo

Tooling: npm workspaces + Turborepo Node version: 24 LTS (unified; Active LTS as of May 2026) Language: TypeScript everywhere (reverb-backend migration phased) Package manager: npm (already used across all repos — no migration required)


Proposed Repository Structure

soreto-platform/
│
├── apps/
│   ├── platform-api/          ← reverb-backend (migrated, renamed)
│   │   ├── src/
│   │   │   ├── routes/api/
│   │   │   ├── services/
│   │   │   ├── middleware/
│   │   │   ├── config/
│   │   │   └── common/
│   │   ├── migrations/        ← stays here (reverb schema)
│   │   ├── test/
│   │   ├── package.json
│   │   ├── tsconfig.json      ← extends ../../tooling/tsconfig/base.json
│   │   ├── .env.example
│   │   └── CLAUDE.md
│   │
│   ├── platform-ui/           ← soreto-melissa (migrated)
│   │   ├── app/               ← Next.js App Router
│   │   ├── components/
│   │   ├── service/
│   │   ├── shared/
│   │   ├── store/
│   │   ├── types/
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   ├── .env.example
│   │   └── CLAUDE.md
│   │
│   ├── zoe/                   ← soreto-zoe (migrated, refactored)
│   │   ├── src/
│   │   │   ├── modules/
│   │   │   ├── services/
│   │   │   └── database/
│   │   ├── processors/        ← eventually typed
│   │   ├── migrations/        ← stays here (zoe schema)
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   ├── config.js          ← replace with @soreto/config
│   │   └── CLAUDE.md
│   │
│   └── legacy-portal/         ← reverb-react (modernized → Next.js 16 + React 19 + Node 24)
│       ├── src/
│       │   ├── actions/       ← Redux action creators (admin, client, shared, user)
│       │   ├── components/    ← React components (admin, client, sharePopup, shared, user)
│       │   ├── config/        ← config.js with @@PLACEHOLDER@@ tokens
│       │   ├── constants/
│       │   ├── decorators/
│       │   ├── dispatchers/   ← Flux app-dispatcher
│       │   ├── middleware/
│       │   ├── mixins/        ← Flux storeWatchMixin
│       │   ├── reducers/      ← Redux reducers (admin, client, shared, user)
│       │   ├── stores/        ← Flux stores
│       │   ├── utils/         ← helpers, services, wrappers
│       │   └── main.js        ← entry point
│       ├── public/            ← static assets (images)
│       ├── dist/              ← compiled output (webpack — do not touch)
│       ├── index.js           ← Express static file server (Procfile: web: node index.js)
│       ├── webpack.config.js  ← pinned, do not update
│       ├── .babelrc           ← Babel 6 config — pinned
│       ├── .travis.yml        ← migrate to GitHub Actions (build only)
│       ├── package.json       ← pinned, do not update dependencies
│       ├── package-lock.json
│       ├── README.md          ← "MODERNIZING: Next.js 16 rewrite in progress — add to app/, not src/"
│       └── CLAUDE.md          ← "Rewriting to Next.js 16 + React 19. New features go in app/ router."
│
├── packages/
│   ├── types/                 ← @soreto/types
│   │   ├── src/
│   │   │   ├── entities/      ← Campaign, Order, Reward, SharedUrl, User
│   │   │   ├── enums/         ← RoleName, OrderStatus, RewardStatus
│   │   │   ├── api/           ← ApiResponse, PaginatedResponse
│   │   │   └── index.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   │
│   ├── api-client/            ← @soreto/api-client
│   │   ├── src/
│   │   │   ├── client.ts      ← ReverbClient class
│   │   │   ├── postReward.ts
│   │   │   ├── notification.ts
│   │   │   ├── zendesk.ts
│   │   │   └── index.ts
│   │   ├── test/
│   │   ├── package.json
│   │   └── tsconfig.json
│   │
│   ├── constants/             ← @soreto/constants
│   │   ├── src/
│   │   │   ├── roles.ts
│   │   │   ├── countries.ts
│   │   │   ├── campaignTypes.ts
│   │   │   └── index.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   │
│   ├── config/                ← @soreto/config
│   │   ├── src/
│   │   │   ├── loader.ts      ← validated env loading
│   │   │   └── schemas/       ← per-app schemas
│   │   ├── package.json
│   │   └── tsconfig.json
│   │
│   └── auth-utils/            ← @soreto/auth-utils
│       ├── src/
│       │   ├── cookieHandler.ts   ← from soreto-cookie-jam
│       │   └── jwtDecode.ts
│       ├── package.json
│       └── tsconfig.json
│
├── tooling/
│   ├── eslint-config/         ← @soreto/eslint-config
│   │   ├── index.js
│   │   ├── next.js
│   │   ├── node.js
│   │   └── package.json
│   │
│   ├── tsconfig/              ← @soreto/tsconfig
│   │   ├── base.json
│   │   ├── nextjs.json
│   │   ├── node.json
│   │   └── package.json
│   │
│   └── jest-config/           ← @soreto/jest-config
│       ├── jest.base.js
│       ├── jest.node.js
│       ├── jest.react.js
│       └── package.json
│
├── docs/
│   ├── architecture/
│   │   ├── SYSTEM_OVERVIEW.md
│   │   ├── DATABASE_SCHEMA.md
│   │   ├── API_CONTRACT.md
│   │   └── AUTH_FLOW.md
│   ├── adr/
│   │   ├── 001-monorepo-migration.md
│   │   ├── 002-node-standardization.md
│   │   ├── 003-typescript-adoption.md
│   │   ├── 004-modernize-reverb-react.md
│   │   └── 005-seneca-decision.md
│   ├── spec/
│   │   ├── DOMAIN_MODEL.md
│   │   ├── API_ENDPOINTS.md
│   │   └── JOB_PROCESSORS.md
│   ├── migration/
│   │   ├── REVERB_REACT_PARITY.md
│   │   └── NODE_UPGRADE_TRACKER.md
│   └── dependencies/
│       ├── INTER_REPO_COUPLING.md
│       └── UPGRADE_BLOCKERS.md
│
├── turbo.json                 ← Turborepo task pipeline
├── package.json               ← Root workspace (engines, scripts, workspaces field)
├── .nvmrc                     ← 24 (Active LTS)
├── .env.example               ← Shared env var documentation
└── CLAUDE.md                  ← Root AI context document

System Architecture Diagram

╔═══════════════════════════════════════════════════════════════════╗
║                    SORETO PLATFORM                                ║
║                                                                   ║
║  ┌─────────────────┐     ┌───────────────────────────────────┐  ║
║  │   platform-ui   │────►│           platform-api            │  ║
║  │  (Next.js 16)   │     │  (Express 5, Node 24, TypeScript) │  ║
║  │  React 19        │     │                                   │  ║
║  │  PrimeReact     │     │  Routes: /api/v1/*                │  ║
║  │  TypeScript     │     │  Auth: Passport (cookie/bearer)   │  ║
║  └─────────────────┘     └────────────┬──────────────────────┘  ║
║                                        │                          ║
║  ┌─────────────────┐                   │                          ║
║  │  legacy-portal  │     ┌─────────────▼─────────┐              ║
║  │  (→ Next.js 16) │     │     PostgreSQL          │              ║
║  │  reverb-react   │     │  schema: reverb         │              ║
║  └─────────────────┘     │  schema: zoe            │              ║
║                           └─────────────▲─────────┘              ║
║  ┌─────────────────┐                    │                         ║
║  │      zoe        │────────────────────┘                         ║
║  │  (Bull queues)  │     ┌──────────────────────┐               ║
║  │  TypeScript     │────►│        Redis          │               ║
║  │  12+ affiliate  │     │  Sessions + Bull Q    │               ║
║  │  processors     │     └──────────────────────┘               ║
║  └─────────────────┘                                              ║
║                                                                   ║
║  ─ ─ ─ ─ ─ ─ ─ ─ shared packages ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  ║
║                                                                   ║
║  @soreto/types    @soreto/api-client    @soreto/constants         ║
║  @soreto/config   @soreto/auth-utils    @soreto/eslint-config     ║
╚═══════════════════════════════════════════════════════════════════╝

Key Configuration Files

npm-workspaces (in package.json)

{
  "workspaces": [
    "apps/*",
    "packages/*",
    "tooling/*"
  ]
}

turbo.json

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"]
    },
    "lint": {
      "outputs": []
    },
    "typecheck": {
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Root package.json

{
  "name": "soreto-platform",
  "private": true,
  "engines": {
    "node": ">=24.0.0",
    "npm": ">=10.0.0"
  },
  "workspaces": [
    "apps/*",
    "packages/*",
    "tooling/*"
  ],
  "scripts": {
    "build": "turbo build",
    "test": "turbo test",
    "lint": "turbo lint",
    "typecheck": "turbo typecheck",
    "dev": "turbo dev --parallel"
  }
}

Migration Sequence

Apps migrate into this structure one at a time, not simultaneously. See L — Migration Plan for the full phased sequence.

Order: 1. Create the monorepo scaffold (empty structure) 2. Migrate soreto-melissaapps/platform-ui/ (first — cleanest codebase) 3. Extract @soreto/types and @soreto/constants 4. Move reverb-reactapps/legacy-portal/ (stand up Next.js 16 scaffold; rewrite begins) 5. Migrate reverb-backendapps/platform-api/ 6. Migrate soreto-zoeapps/zoe/ (after AMD TypeScript refactor) 7. Extract @soreto/api-client (replace local_modules/reverb)


Legacy Portal: Modernization Target

apps/legacy-portal/ (reverb-react) is modernized, not frozen. The existing stack (Babel 6, Webpack 4, Node 10, React 17/dom 16.5 mismatch, react-router@3 + react-router-dom@4 mismatch) cannot be incrementally upgraded — the gaps are too large and compound. The correct path is a controlled rewrite to Next.js 16 + React 19 inside the monorepo.

Modernize to Next.js 16

Target stack:

Layer Current Target
Framework CRA-style Webpack 4 bundle Next.js 16.2.6 (App Router)
React 17.0.1 + react-dom 16.5.0 ⛔ React 19.2.6
Routing react-router@3 + react-router-dom@4 ⛔ react-router@7.15.1 (or Next.js file routing)
Language JavaScript/JSX TypeScript 6.0.3
State Redux 3.7.2 + Flux (mixed) React Context + Zustand or Redux Toolkit 2.x
Bundler Webpack 4.7.0 Turbopack (Next.js 16 default)
Node ~10.15.3 ⛔ 24 LTS
Styling PrimReact 1.5.1 PrimeReact 10.9.8 (matches platform-ui)
Build config .babelrc (Babel 6) tsconfig.json + SWC

Target structure after modernization:

apps/legacy-portal/    ← modernized as Next.js 16 App Router app
├── app/
│   ├── (admin)/       ← admin routes (migrated from src/components/admin/)
│   ├── (client)/      ← client routes (migrated from src/components/client/)
│   └── layout.tsx
├── components/        ← migrated from src/components/shared/
├── store/             ← Zustand or Redux Toolkit (replaces Redux 3 + Flux)
├── service/           ← API calls (replaces src/utils/services/)
├── types/             ← TypeScript definitions
├── package.json       ← Next.js 16, React 19, TypeScript 6
├── tsconfig.json      ← extends ../../tooling/tsconfig/nextjs.json
├── next.config.ts
└── CLAUDE.md

Effort estimate: 6–10 weeks for one frontend engineer. This is a controlled rewrite — Babel 6, Flux, and the react-router v3/v4 dual installation cannot be incrementally migrated. The business logic (Redux action creators, API calls, reducers) can be preserved; the rendering and tooling layers are rewritten.

While the rewrite is in progress: Deploy a WAF (Cloudflare or AWS WAF) in front of the existing reverb-react Heroku app to compensate for Node 10 EOL exposure during the transition window.


What Does Not Change

Item Reason
Database schemas (reverb, zoe) Schema changes are separate from repo structure
PostgreSQL / Redis / RabbitMQ Infrastructure stays the same
Heroku deployment App-level, not repo-level
Existing git history Each app preserves its history via git subtree or history import
Business logic No business logic changes during the structural migration