They had a PHP monolith and no CRM. Two years on, they are still building on what replaced it.
A global non-profit serving 180+ countries ran its community on a custom PHP platform with no CRM behind it — member records, course enrolments and donations in separate systems that never agreed. We rebuilt it as a Next.js platform with Salesforce as the backbone and six external systems behind one backend layer. The client has been extending it ever since.
- Client
- A global non-profit, 180+ countries
- Sector
- Non-Profit
- Platforms
- Full-Stack · Salesforce
- Engagement
- Ongoing (2+ years)
- Systems integrated
- Six, behind one Node.js backend layer.
- Study
- 01 of five
One platform, before and after
Struck through: the way it used to workWhy it stayed that way.
Four constraintsSoftware that still works can still be finished. The client had run its global community on a custom PHP platform for years, and it still served — but every new feature had become a negotiation with the code already in place. Here it was one organisation, 180+ countries, and nothing underneath that agreed on who a member was.
- 01
No CRM connectivity — member records, course enrolments, and user activity lived in separate systems with no single source of truth and no automation between them.
- 02
Feature delivery was slow. New requests required navigating a legacy PHP codebase with no modern tooling, no standardised patterns, and no onboarding documentation for new contributors.
- 03
Traffic spikes during major course launches and enrolment windows pushed the PHP system toward its scalability ceiling.
- 04
Without standardised development patterns, every new contributor increased the risk of regressions and maintenance became progressively harder with every release.
What we built instead.
Five parts of one platformCloudAlgo led a full-platform rebuild — not a gradual migration, but a deliberate re-architecture. The new platform is a Next.js 14 application (React 18, Pages Router) deployed on Heroku, with a Node.js backend that normalises data contracts across six external systems, Salesforce as the unified CRM backbone, and Salesforce Marketing Cloud for campaign and transactional email automation.
Course & Event Platform
Next.js → StripeA complete enrolment system for in-person courses, online workshops, ticketed events, youth programmes, and retreats. Users can discover offerings via geo-based centre finder (Google Maps + Autocomplete), register, pay via Stripe with saved payment methods and coupon support, and receive Apple Wallet passes and QR codes for in-person check-in — in one pass, without leaving the site.
Authentication & Identity
Next.js → AWS CognitoAuthentication runs on AWS Cognito with Cognito Passwordless Auth — enabling one-tap magic link and OTP logins alongside traditional email/password flows. This reduced friction at account creation and login significantly, critical for an audience spanning a wide age range and range of technical comfort across 180+ countries.
Membership & Content Platform
Salesforce → Next.jsA complete membership lifecycle covering tier selection, billing, renewal, and personalised content gating. The content layer includes a daily inspiration feed, a guided meditation audio/video library, a members-only Q&A archive, a long-form article and video collection, and a global audio player that persists playback state across page navigation.
Donation Platform
Stripe → SalesforceA full donation lifecycle built on Salesforce, Stripe, and Salesforce Community Cloud — one-time and recurring giving options, automated Salesforce sync per transaction, a donor self-service portal (giving history, tax receipts, payment method management), campaign and fund attribution, and Marketing Cloud acknowledgement emails triggered on transaction confirmation. This replaced a manual, spreadsheet-driven process with the organisation's first fully auditable, end-to-end donation tracking system.
CRM-Connected Analytics
Segment → SalesforceEvery significant user action — page views, course views, checkout initiation, purchases — is tracked through Segment into Salesforce, enabling the marketing team to build audience segments, trigger Marketing Cloud automations, and report on enrolment funnel performance with no manual data entry.
FrameworkNext.js 14 (Pages Router), React 18
StylingSCSS, Tailwind CSS, React Bootstrap 5
AuthenticationAWS Cognito, Cognito Passwordless Auth (magic link + OTP)
PaymentsStripe (one-time, subscriptions, saved payment methods)
CRMSalesforce, Salesforce Community Cloud
Email / SMS AutomationSalesforce Marketing Cloud
Analytics PipelineSegment → Salesforce
Server StateReact Query (TanStack)
FormsFormik, React Hook Form, Yup, Zod
Hosting & DeploymentHeroku (multi-environment pipelines)
Error TrackingSentry
LoggingPino (structured, leveled JSON)
MapsGoogle Maps, Google Places Autocomplete
MediaVimeo, YouTube, React Player
AnimationsFramer Motion
BuildSWC, Next.js Bundle Analyzer, WebP conversion scripts
Engineering notes.
What keeps it navigable at 4,500 commitsSix external systems, one backend layer
The platform integrates Salesforce, Salesforce Community Cloud, Stripe, AWS Cognito, Segment, and Salesforce Marketing Cloud — each with distinct data models and failure modes. CloudAlgo built a Node.js backend layer that normalises data contracts, handles retries, and decouples the frontend from individual vendor APIs. A Salesforce schema change doesn't cascade into the UI. A Stripe webhook failure doesn't leave the client state inconsistent.
Conventions the tooling enforces, not the reviewer
With a large team and 4,500+ commits over two years, ad-hoc patterns accumulate fast. Enforced conventions kept the codebase navigable: a custom useRouter hook that automatically preserves UTM parameters across every navigation; a useEntityTracking hook that standardises analytics event payloads so no developer can accidentally fire a malformed track event; Pino structured logging replacing console.log throughout; React Query for consistent server-state management; and global modal and alert context providers preventing z-index conflicts and duplicated state logic scattered across features.
The centres page ships 42 kB, not 228
One major performance initiative reduced a key centres page SSR payload from 228 kB to 42 kB — an 82% reduction — by selectively deferring non-critical data to client-side fetches. Combined with Next.js SWC compilation, WebP image conversion at build time, and ongoing bundle analysis via @next/bundle-analyzer, the platform handles course launch traffic spikes without degradation.
Three environments, one pipeline, Sentry across all of them
Three environments — development, QA, and production — each with distinct API credentials, feature flags, and Salesforce org connections. Heroku pipelines coordinate promotion from QA to production. Sentry monitors error rates post-deploy, and structured Pino logs give the engineering team clean, searchable production visibility without opening a dashboard.
What it settled.
Three figures, still trueOngoing client engagement — platform continuously expanding
SSR payload reduction on centres page (228 kB → 42 kB)
External systems behind one Node.js backend layer, each with its own failure mode
What this one shows
Four things you can hold us to.
A case study is only worth reading if it generalises. These are the parts of this build that would show up again on yours.
- We rebuild when rebuilding is right.A gradual migration would have preserved the constraints of the PHP platform while adding complexity. We made the case for a clean break, designed the new architecture to handle the client's actual integration requirements from day one, and delivered a platform the team could own and extend without re-engaging us for every change.
- Integration depth requires an abstraction layer.Six external systems with distinct data models is a coordination problem, not a configuration problem. Our Node.js backend treats integration complexity as a first-class architectural concern — not something left for the frontend to handle ad hoc.
- Enforced conventions pay for themselves.A custom useRouter hook, a standardised analytics event contract, global context providers for modals and alerts — these feel like overhead in week one. By year two, with 4,500+ commits from a large team, they're the reason the codebase is still navigable and safe to work in.
- Ongoing engagement is the real metric.The strongest signal that a platform was built right is that the client keeps building on it. Two years in, the client is adding course types, membership tiers, content features, and integrations — not rewriting.