Skip to content

Supply Chain Sustainability School architecture

The Supply Chain Sustainability School is a WordPress multisite network of country websites, plus a separate Carbon Calculator application, all sitting in front of a set of Moodle LMS instances that own identity, membership and learning content.

Repository: StrategiQ/www.supplychainschool.co.uk (Bitbucket). Hosting: WP Engine. Local: Local by Flywheel at supplychainschool.build.

flowchart TB
  subgraph Moodle["Moodle / Titus Learning (one per school)"]
    M1[UK] 
    M2[AU]
    M3[FR]
    M5[SBCC]
    M6[IE]
    M7[US]
    CRM[local_scssusers_* web services]
  end

  subgraph WP["WordPress multisite"]
    subgraph Main["theme: supplychainschool"]
      B1[blog 1 UK]
      B2[blog 2 AU]
      B3[blog 3 FR]
      B5[blog 5 SBCC]
      B7[blog 7 US]
    end
    subgraph Carbon["theme: carboncalculator + plugin: carboncalc"]
      B6[blog 6 Carbon staging]
      B8[blog 8 Carbon production]
    end
  end

  CH[Companies House API]

  Main -->|login, resources, members, stats| Moodle
  Carbon -->|login, roles, company details| CRM
  Carbon -->|CRN lookup| CH

One moodlelogin cookie, scoped to a shared parent domain, spans the main site and the Carbon subsite — which is why the Carbon Calculator can be a separate theme on a separate subsite and still share a session.

LayerWhere
Identity, membership, coursesMoodle. No member has a wp_users row.
Presentation, marketing contentwp-content/themes/supplychainschool (an _s/underscores derivative)
Carbon Calculator UIwp-content/themes/carboncalculator (Tailwind + SASS)
Carbon Calculator domain logic and datawp-content/plugins/carboncalc (~20k lines, the only versioned plugin)
Third-party pluginsInstalled per environment, not in the repo

The split between the Carbon theme and the Carbon plugin is not clean: the plugin owns the database, REST API for reports, and wp-admin; the theme owns the pages and the entire supply-chain REST API (themes/carboncalculator/functions.php, 5,295 lines). If you are looking for supplier code, it is in the theme, not the plugin.

cc_* tables live on one subsite — blog 6 on staging, blog 8 in production — and are reached from any blog through CarbonCalc\DB (plugins/carboncalc/includes/DB.php), which resolves the Carbon blog id by checking CARBONCALC_CARBON_BLOG_ID, then the current blog, then probing blogs 8 and 6 for populated tables.

TableHolds
cc_users, cc_user_rolesSynced Moodle users and role shortnames
cc_company, cc_company_supplierCompanies (by CRN) and buyer→supplier joins per year
cc_reporting_year, cc_step, cc_field, cc_metric, cc_categoryThe questionnaire, as data
cc_metric_factorConversion factors per metric per year
cc_report, cc_report_answer, cc_report_meta, cc_report_resultReports and their totals
cc_report_shareCross-company read access
cc_sic_codesEmissions intensity per SIC code per year

Schema version is CARBONCALC_SCHEMA_VERSION in plugins/carboncalc/carboncalc.php, currently 22, applied by Migrations::maybe_migrate() on plugins_loaded.

On the main sites, LMS data lands in the lms_users table and the resources / member custom post types.

Main network

  • [[moodle-sso-and-sessions]] — login, the moodlelogin cookie, per-blog constants
  • [[lms-resource-sync]] — the resource library sync from Moodle
  • [[member-directory-and-stats]] — member/partner directory and headline stats
  • [[site-chrome-and-navigation]] — header, footer, mega menu, country switching
  • [[acf-flexible-content-blocks]] — how pages are built from 27 block types
  • [[site-search]] — grouped search and blog filtering
  • [[forms-spam-and-marketing-tracking]] — CF7, honeypot, Force24, consent
  • [[multisite-content-copy]] — copying pages and media between country sites
  • [[build-and-deploy]] — Bitbucket Pipelines, git ftp push, cache busting

Carbon Calculator

  • [[carbon-access-gates]] — company, CRN, partner and role gates
  • [[carbon-report-questionnaire]] — the data-driven multi-step form
  • [[emissions-calculation-and-submission]] — factors, scopes, direct reporting, locking
  • [[company-emissions-dashboard]] — My Company Emissions
  • [[supply-chain-emissions]] — supplier upload, EEIO estimates, supplier-reported data
  • [[report-sharing]] — company-to-company report access
  • [[reporting-year-config-and-importer]] — setting up a new reporting year
  • [[company-lookup-integrations]] — Moodle CRM and Companies House
  • [[carbon-admin-and-debug-tools]] — the wp-admin surface, debug output, log files

Cross-cutting things worth knowing before you touch anything

Section titled “Cross-cutting things worth knowing before you touch anything”

Blog ids are hard-coded, in many places. LMSClient.php (per-blog constants), header.php (which nav renderer), force24-functions.php (tracking ids), functions.php (which navigation stylesheet), DB.php and Migrations.php ([6, 8]). Adding a subsite is a multi-file change and a missing LMS_URL constant is a fatal error, not a warning.

Environment is detected by hostname allow-list, at themes/supplychainschool/inc/classes/LMSClient.php:5. A staging host not in that list talks to production Moodle.

Nothing is tested. No PHPUnit, no JS tests, no lint or test step in the pipeline. phpcs.xml.dist exists in the main theme but is not run. Verify by hand; every feature page lists what to check.

Log files accumulate in wp-content/, JSON one object per line, all gitignored: carboncalc-login-denied.log, carboncalc-companieshouse.log, carboncalc-crm.log, carboncalc-supplier-upload.log. Nothing rotates them.

The main theme’s build toolchain is old (Laravel Elixir on Gulp 3, Node

= 10.9); the Carbon theme’s is current (Gulp + Tailwind + PostCSS). Compiled assets are committed in both.

Constants in wp-config.php (gitignored — reference by name only): MOODLE_WS_TOKEN, COMPANIES_HOUSE_API_KEY, CARBONCALC_CARBON_BLOG_ID, CARBONCALC_SKIP_AUTH, CARBONCALC_DEV_BYPASS, CARBONCALC_LMS_DEBUG, TOP_LEVEL_DOMAIN, plus the standard multisite constants.

Carbon feature flags are WordPress options on the Carbon subsite, read through FeatureSettings: sharing, partners-only access, S3-partners-only access, debug mode, SIC lookup indicator, the CRN gate, and the site banner.

Everything else — the questionnaire, factors, SIC intensities, page content — is data.

See [[onboarding]] for getting it running locally.