G. Frontend Architecture Assessment
Two Frontends, One Being Modernized
The Soreto ecosystem has two separate frontend applications, both in active development:
| App | Status | Tech (current) | Tech (target) | Purpose |
|---|---|---|---|---|
reverb-react |
🔄 Modernizing → Next.js 16 | React 17/16, Babel 6, Webpack 4, Node 10 | Next.js 16, React 19, TypeScript 6, Node 24 | Admin + client portal (being modernized) |
soreto-melissa |
✅ Active development | Next.js 13, React 18, TypeScript | Next.js 16, React 19 | Admin + client portal (new platform UI) |
Both applications are live simultaneously and cross-reference each other. reverb-react is undergoing a controlled rewrite to Next.js 16 inside apps/legacy-portal/ — parallel to ongoing melissa development.
reverb-react Assessment
Cannot Be Upgraded In-Place — Rewrite Required
Attempting an in-place upgrade of reverb-react would require all of the following simultaneously, with compounding risk:
1. Babel 6 → Babel 7 (all presets and plugins must be updated)
2. Webpack 4 → Webpack 5 or Vite (config rewrite)
3. React 16/17 → React 19 (hooks audit, Concurrent Mode compatibility, React 19 new APIs)
4. react-router@3 + react-router-dom@4 → react-router@7 (two separate mismatches; complete API rewrite across 4 major versions)
5. Redux 3 → Redux Toolkit (Redux 5 requires a different pattern)
6. Remove Flux (Flux was abandoned by Meta in 2019)
7. @@PLACEHOLDER@@ config → proper env vars
8. Node 10 → 24
The correct approach is a controlled rewrite to Next.js 16 — starting on a clean scaffold inside apps/legacy-portal/, porting business logic while discarding the outdated tooling layer entirely. This avoids all compounding upgrade risks.
Recommendation: Modernize reverb-react to Next.js 16 + React 19 via a controlled rewrite inside apps/legacy-portal/. Do not attempt an in-place upgrade — the gaps are too large to bridge incrementally. See F — Version Standardization and K — Target Architecture for the full modernization target and effort estimate.
Next.js 16 Rewrite — Route & Feature Scope
The following areas need porting from the current reverb-react codebase into the Next.js 16 App Router scaffold. This is the input for the Phase 5 rewrite scope:
[ ] Admin dashboard (global)
[ ] Client dashboard and analytics
[ ] Campaign management
[ ] Campaign version management
[ ] A/B test management
[ ] Reward pool management
[ ] User management
[ ] Email template management
[ ] Affiliate configuration
[ ] Marketplace management
[ ] Report generation and export
[ ] User segmentation
[ ] By-channel analytics (BiAnalytics)
[ ] Zendesk lead management
[ ] Social sharing configuration
[ ] Asset management
[ ] Client user management
soreto-melissa Assessment
Architecture: Next.js 13 App Router
soreto-melissa correctly uses the Next.js 13 App Router with route groups:
app/
├── (client)/ ← role-guarded: CLIENT_USER, SAAS
├── (full-page)/ ← auth, subscribe, public
├── (landing)/ ← marketing
└── (main)/ ← admin routes
The role guard in (client)/layout.tsx is implemented as a client component that checks the StoreContext and redirects non-authorized users. This is appropriate for an admin portal.
SSR vs CSR Tradeoffs
| Pattern | Used in Melissa | Assessment |
|---|---|---|
| Server Components | Layouts, metadata | ✓ Correct — static structure |
Client Components ('use client') |
Interactive pages | ✓ Correct — data-dependent pages |
| Server-side data fetching | Not observed | ⚠️ May be missing — some pages could fetch on server |
| API routes | Not observed | ⚠️ All calls go to reverb-backend directly |
Opportunity: Admin dashboard pages that load large data tables could benefit from server-side data fetching (reducing client-side bundle size and first paint time). Currently all data fetching appears to be client-side via the service layer.
Next.js Version: 13.4.9 → Target 16
| Version | Status | Notes |
|---|---|---|
| 13.4.9 (current) | Security patches limited | Stable but 3 majors behind |
| 14.x | Stable | App Router stable, Server Actions added |
| 15.x | Stable | async/await request APIs, improved caching |
| 16.2.6 (latest) | Current stable | ~87% faster startup, Turbopack default, AI-ready dev tools |
Upgrade path: 13 → 14 is lower risk (image component change, minor breaking changes). 14 → 15 involves changes to how cookies(), headers(), and searchParams are accessed (now async). 15 → 16 requires reviewing Turbopack compatibility and updated error boundaries. Do not skip major versions. Start with 14 in the next 3 months.
State Management: React Context
The current Context approach is appropriate for this use case:
// store/Context.ts
type StoreContextType = {
isAuthenticated: boolean;
user: User | null;
isAuthLoading: boolean;
selectedCurrency: string;
login: (email: string, password: string) => Promise<void>;
logout: () => Promise<void>;
passwordlessLogin: (email: string, token: string) => Promise<void>;
changeSelectedCurrency: (currency: string) => void;
};
Auth state, user profile, and currency selection are the right things to put in Context. This is not over-engineered.
Watch for: As melissa grows, if multiple separate domains (campaigns, rewards, etc.) start needing global state, Context will become insufficient. At that point, consider Zustand (lightweight) or TanStack Query (for server state). Do not introduce Redux — it would be a regression from the current clean approach.
UI Library: PrimeReact 10.2.1 (current) → shadcn/ui + Tailwind CSS v4 (target)
soreto-melissa currently uses PrimeReact 10.2.1 with primeflex@3.3.0. For the monorepo migration, both portals (apps/platform-ui/ and apps/legacy-portal/) are targeting shadcn/ui (CLI v4) + Tailwind CSS 4.2.0 as the unified UI stack. This eliminates the PrimeReact dependency and gives both portals identical tooling, making the @soreto/ui shared component package viable.
reverb-react legacy: primereact@1.5.1 — 9 major versions behind melissa, completely incompatible APIs. Not an upgrade path — both mismatches are eliminated when legacy-portal is rewritten from scratch on shadcn/ui.
Why shadcn/ui + Tailwind CSS v4
This is the recommended UI stack for both apps/platform-ui/ (melissa migration) and apps/legacy-portal/ (reverb-react rewrite). The decision is motivated by developer velocity, AI-assisted development gains, and long-term maintainability.
Tailwind CSS 4.2.0 — What Changed
Tailwind v4 is a ground-up rewrite with a CSS-first configuration model:
| Capability | Tailwind v3 | Tailwind v4.2 |
|---|---|---|
| Configuration | tailwind.config.js (JavaScript) |
@theme directive in CSS — no config file |
| Full build speed | baseline | 5× faster |
| Incremental rebuild | baseline | 100× faster (critical for dev server) |
| Color system | HSL | OKLCH — perceptually uniform, better dark mode |
| Cascade control | No layers | CSS cascade layers — predictable specificity |
| Custom properties | Manual | @property — registered, animated |
| Webpack support | Plugin required | First-class webpack plugin (v4.2) |
/* Tailwind v4: all design tokens in CSS — no tailwind.config.js */
@import "tailwindcss";
@theme {
--color-brand: oklch(55% 0.2 260);
--font-sans: "Inter", sans-serif;
--radius: 0.5rem;
}
shadcn/ui CLI v4 — What It Provides
shadcn/ui is not a component library — it is a component registry and CLI. Components are copied directly into your codebase via the CLI. This means:
- No package version to pin, upgrade, or conflict with — components are your code
- No runtime overhead — pure Radix UI primitives + utility CSS
- Full customization — modify any component file directly without fighting library internals
- AI-agent native —
shadcn/skills(CLI v4, March 2026) gives coding agents (including Claude) direct context on component APIs, registry patterns, and Radix primitives
# Initialize project — creates components.json, adds Tailwind v4 config
npx shadcn@latest init
# Add a component — copies source into components/ui/
npx shadcn@latest add button
npx shadcn@latest add data-table
npx shadcn@latest add form
Components land in components/ui/ as plain TypeScript files you own completely.
Developer Velocity vs PrimeReact
| Dimension | PrimeReact 10 | shadcn/ui + Tailwind v4 |
|---|---|---|
| Version lock-in | Package version pinned — 9 major versions behind reverb-react | No version — components live in your repo |
| Customization | Override via CSS specificity battles | Edit the component file directly |
| Bundle size | Full library imported even if unused | Only the components you add |
| Accessibility | Good (PrimeReact 10+) | Built in — Radix UI primitives (WAI-ARIA, keyboard, focus) |
| Dark mode | Theme via CSS variables | Tailwind v4 OKLCH color system — automatic |
| AI-assisted work | No agent context | shadcn/skills gives agents component API context |
| Design system | PrimeFlex utility layer (separate dep) | Tailwind v4 — unified, no separate utility package |
| Shared across portals | Requires both apps on same PrimeReact major | @soreto/ui package: shared shadcn components, no version drift |
Impact on @soreto/ui Package
With both portals on shadcn/ui + Tailwind v4, the @soreto/ui shared package becomes a component extension library — custom Soreto-specific wrappers built on top of shadcn primitives, shared across both apps with zero version compatibility concerns.
Frontend Modernization Roadmap
Phase 1: stabilize melissa (0–3 months)
- [ ] Add CI/CD pipeline (GitHub Actions: lint + type-check + test + build)
- [ ] Confirm deployment target and document it
- [ ] Fix
jest.setup.tsreference (ensure file exists) - [ ] Remove or justify
babel.config.js(may conflict with SWC) - [ ] Replace
@rjsf/core@6.0.0-beta.10with stable version when available - [ ] Evaluate
react-force-graphvsreact-force-graph-2d— remove unused one
Phase 2: reverb-react modernization (3–9 months)
- [ ] Stand up Next.js 16 scaffold in
apps/legacy-portal/—app/at root, nosrc/, Node 24, React 19, TypeScript 6 - [ ] Create
app/(admin)/andapp/(client)/route groups with guarded layouts - [ ] Build
store/with Zustand (replaces Redux 3 + Flux — business logic preserved) - [ ] Build
service/layer using@soreto/api-client(replaces reverb-react's hand-rolled service utilities) - [ ] Add Tailwind CSS v4.2 — CSS-first
@themedirective inglobals.css, notailwind.config.js - [ ] Run
npx shadcn@latest init— createscomponents.json, wires Tailwind v4 - [ ] Build
components/with shadcn/ui (CLI v4) — components added vianpx shadcn@latest add <component> - [ ] Replace
@@PLACEHOLDER@@tokens →process.env.NEXT_PUBLIC_*in.env.example - [ ] Deploy WAF in front of existing Heroku reverb-react app during transition
Phase 3: cut over and decommission (9–12 months)
- [ ] Cut over traffic from old Heroku reverb-react to modernized
apps/legacy-portal/ - [ ] Decommission original Heroku reverb-react app
- [ ] Remove
NEXT_PUBLIC_LEGACY_PORTAL_URLlinks pointing to old app from melissa'sconstants.ts
Do Not: Next.js for reverb-backend
reverb-backend is a pure API server. There is no benefit to adding Next.js API routes as a proxy — this would add complexity and a new process without providing value. The reverb-backend Express server should remain a dedicated API server.