Skip to content
sam.
Back to projects

Rouic Ltd

SSG-Cloud / SSG-React

An integrated operating system for training and consultancy businesses: sell it in the CRM, schedule and book it in the course manager, deliver it via e-learning, take payment through Stripe, and measure all of it in a live analytics dashboard, across one secure, multi-tenant platform.

SSG-Cloud / SSG-React screenshot
Type
Enterprise multi-tenant SaaS platform (B2B, realm-isolated)
Status
Live in production
Role
Full-stack engineering

// what it does

SSG replaces the half-dozen disconnected tools a training provider would otherwise stitch together (CRM, booking system, LMS, invoicing, reporting) with one platform where every part shares the same data.

CRM & sales pipeline

Organisations, contacts, opportunities, tasks, teams, and an activity/transaction history. Opportunities move through configurable stages with quotes, invoices, discounts, and approval workflows.

Course & session management

Scheduling, delegate bookings, tutors, exams, certificates, locations, and joining instructions, including private/onsite courses and multi-block sessions.

E-learning

Native integration with LearnWorlds and UKATA: enrolments and completions sync back into the platform so online learners are reported alongside classroom delegates.

Assessments & audits

Form-driven safety assessments and contractor audits with submission queues and AI-assisted analysis.

Payments & finance

Stripe checkout and webhooks, identity verification, invoicing, and Xero accounting sync.

Analytics dashboard

A configuration-driven, drag-and-drop widget system (charts, gauges, KPIs, tables, lists) built on a dynamic SQL query-builder, with live auto-refresh and per-tier gating.

Automation

A rules engine with triggers, delayed actions, and a database-backed job queue for emails and notifications fired by CRM events.

Multi-tenancy

Every customer (realm) is logically isolated; realm scoping is enforced on essentially every query, with per-realm settings and feature flags.

// the app suite

web

Public marketing site and course catalogue.

crm

The core operator app (~300 routes): contacts, organisations, opportunities, tasks, bookings, dashboards, team management.

admin

Platform governance, configuration, scheduling, and reporting.

account

User account, security, and preferences.

pay

Stripe-backed payment and invoice flows.

checkin

QR-based delegate attendance and roll-call.

tutor

Tutor scheduling and availability (FullCalendar).

assessed / audit

Safety assessments and contractor audits.

forms

Dynamic form builder and submissions.

pdf

Document generation, viewing, and annotation.

recorder

rrweb session recording and playback.

go

Branded short-link and redirect service.

// screenshots

account.ssg.co.uk

Configurable analytics dashboard with drag-and-drop chart, KPI and gauge widgets.

// tech stack

Monorepo
Turborepo (npm workspaces): 13 apps + shared packages
Frontend
Next.js 15, React 18, TypeScript (strict)
UI
Tailwind CSS 3, Radix UI + Headless UI, a large in-house component package
State / data
Redux Toolkit + redux-persist, SWR
Charts
ApexCharts, Recharts, Tremor, Nivo, Billboard.js
Rich text
TipTap, Slate, Lexical, Plate, with Yjs + HocusPocus for multiplayer editing
Scheduling
FullCalendar, date-fns
Maps
Mapbox GL, Google Maps
Documents
PDFTron WebViewer, pdf.js, react-pdf, jsPDF
Layout / DnD
react-grid-layout (dashboards), dnd-kit
Search
Algolia InstantSearch
Auth
Firebase Auth + session cookies, WebAuthn passkeys, OTP/2FA
Session replay
rrweb (custom recorder app + SDK)
Backend
Node.js + Express (REST), modular by domain
Database
MySQL 8 on Google Cloud SQL: raw mysql2, no ORM, ~371 tables
Caching
MySQL-backed query/widget cache (no Redis dependency)
Integrations
Stripe, Nylas, Xero, Mailchimp, Zapier, LearnWorlds, UKATA, OpenAI, CloudConvert, SendGrid
Storage / media
Google Cloud Storage, Sharp image processing
Hosting
Vercel (frontend), Google App Engine + Firebase (backend)
Monitoring
Highlight.run, OpenReplay, Google Cloud Logging

// architecture & engineering

Realm-based multi-tenancy

A realm column on virtually every table provides logical isolation for hundreds of independent client organisations on one database. Realm is resolved from the authenticated session and threaded into queries server-side, so a client can never read across the tenant boundary, and per-realm settings and feature flags allow gradual, tenant-by-tenant rollout.

Configuration-driven dashboard engine

The analytics dashboard is fully data-driven: widgets are JSON configurations (data source, filters, grouping, aggregation, display options) rendered through a responsive drag-and-drop grid. A backend query-builder service translates that config into SQL across multiple data sources, handling time-bucketing, entity grouping, multi-series charts, and gauge targets, with results cached in MySQL on a per-widget TTL.

Append-only opportunity model

Opportunities are immutable-versioned: every edit inserts a new row sharing a composite ID, giving a built-in audit trail. Reads deduplicate to the latest revision (MAX(id) per composite ID), a subtlety that has to be respected in every aggregate query, or values multiply by the number of edits.

Booking-accurate revenue attribution

E-learning revenue is derived from the booking graph (bookings, courses, delegate slots) rather than from invoice line totals, with order-level web coupons resolved through the coupon-usage tables and apportioned across basket items, so per-course figures reflect what was actually sold, net of discounts, instead of double-counting shared invoices.

Live-ish dashboards

Widget data refreshes on a polling cadence plus tab-focus revalidation (SWR), with the auto-refresh path deliberately bypassing the read cache so a sale appears within the refresh window while the cache still protects cold loads and concurrent viewers. This also surfaced and fixed a class of bug where cache expiry was computed on the app clock but compared on the database clock.

Database-backed everything-else

Rather than adding Redis/Bull, the platform leans on MySQL for both caching (hashed query + params with TTL) and job queues (trigger queues and delayed actions polled on an interval), one fewer moving part to operate.

Deep third-party integration surface

Stripe (checkout, webhooks, identity), Nylas (two-way email/calendar sync), Xero (accounting), LearnWorlds and UKATA (e-learning), Mailchimp, Zapier, Algolia, and OpenAI are wired into the relevant domains rather than bolted on.

// notable problems solved

  • Tenant isolation at scale: consistent realm scoping across ~371 tables and a thousand-plus endpoints, so multi-tenancy is enforced by construction, not convention.
  • Correct aggregation over an append-only table: deduplicating opportunity revisions in every analytics query to avoid silent multiplied totals.
  • Accurate e-learning revenue: moving from fragile invoice-notes parsing to a booking-graph calculation that mirrors the live basket, eliminating per-course over-counting from shared transactions.
  • Dynamic, gated analytics: a JSON-configured widget system that compiles to SQL and caches per widget, with subscription/permission gating enforced server- and client-side.
  • A maintainable 13-app front end: shared design system and domain logic in one ui package, with independent deploys per app via Turborepo.

// scope & results

  • 13 front-end applications in one monorepo, sharing a single component/utility library.
  • ~300 routes in the CRM app alone; tens more across web and admin.
  • ~371 database tables spanning CRM, courses, sessions, bookings, opportunities, delegates, assessments, automation, payments, and integrations.
  • Domain-modular Express backend (CRM, courses, opportunities, payments, e-learning, assessments, forms, integrations, sessions, and more) over MySQL with no ORM.
  • Live in production with custom auth (Firebase + passkeys), live Stripe payments, and a broad integration ecosystem (Nylas, Xero, LearnWorlds, Mailchimp, Zapier).

// selected features

CRM & sales

Organisations, contacts, customers · opportunity pipeline with configurable stages, types, and tabs · quotes and invoices · line and order-level discounts · approval workflows · tasks with tags and assignments · teams and team-based filtering · activity feed and append-only transaction history · bulk export (chunked/scheduled) · Algolia-powered search.

Courses & bookings

Course catalogue · multi-block sessions · open and private/onsite courses · delegate bookings with per-delegate pricing · tutors and availability · exams, results, and certificates · joining instructions · QR check-in and roll-call · LearnWorlds and UKATA enrolment/completion sync · unified classroom + online delegate reporting.

Analytics dashboard

Drag-and-drop responsive widget grid · chart / mixed-chart / KPI / gauge / list / table widgets · JSON-configured data sources, filters, grouping, aggregation · time-bucketing and entity grouping · gauge targets · per-widget caching · live auto-refresh and focus revalidation · click-through view-data deep links · dashboard sharing and email snapshots · subscription/permission gating.

Platform

Realm-based multi-tenancy with per-realm settings and feature flags · Firebase auth with WebAuthn passkeys and OTP/2FA · Stripe payments, webhooks, and identity verification · Xero / Nylas / Mailchimp / Zapier integrations · automation engine with triggers and database-backed job queues · dynamic form builder · PDF generation and annotation · rrweb session replay · collaborative rich-text editing (Yjs/HocusPocus).