RepMojo Multi-tenant R2 — Fresh Namecheap Installation
Read first: This release is a functional staging foundation and new public website, NOT a complete paid production ERP. It implements the correct physical multi-tenant architecture, with one independent folder and database per wholesale company. The website, Office, Sales Rep and Master interfaces are included, but real GoCardless checkout/reconciliation, end-to-end accounting/purchasing, and hands-off paid tenant deployment are not complete. Do not take subscription payments yet.
Final architecture
/home/YOUR_CPANEL_USER/
├── public_html/ ← main repmojo.com website
│ ├── index.html ← redesigned marketing site
│ ├── assets/
│ ├── api/lead.php ← public enquiry endpoint, no payments
│ ├── control/ ← CENTRAL MASTER CONTROL, installed once
│ │ ├── index.html
│ │ ├── setup.php ← delete after first master setup
│ │ ├── install-company.php ← staging-only, Master-authenticated
│ │ ├── api/index.php
│ │ └── webhook.php ← event inbox only
│ ├── abc/ ← COMPANY ABC: created by staging installer
│ │ ├── office/index.html ← ABC Office Admin
│ │ ├── rep/index.html ← ABC Sales Rep iPad app
│ │ ├── api/index.php ← ABC tenant-locked API
│ │ └── assets/ ...
│ └── 2nd-company/ ← SECOND independent wholesaler
│ ├── office/ ├── rep/ ├── api/ └── assets/
└── repm-private/ ← MUST be outside public_html
├── config.php ← Master database credentials
├── master-encryption.key ← created during setup
├── tenants/abc.json ← private ABC database credentials
├── tenants/2nd-company.json ← separate database credentials
├── tenant-template/ ← approved reusable company release
└── backend/ ← shared PHP source and business services
Important: each company has its own physically installed release files in /slug/ (office, rep, API, assets). The source engine is currently shared, but company database access is isolated and its entry points are forced to that company. Tenant API paths and sessions are restricted to their own company URL. Future per-company backend version pinning will require copying/versioning the backend engine per release; it is NOT implemented yet. Do not claim company releases can be updated independently in the current backend.
Step 0 — What you need
- Namecheap cPanel for
repmojo.comwith your confirmed emptypublic_html. - HTTPS working for
https://repmojo.com(create/fix SSL in Namecheap before setup). - PHP 8.2 or newer, with
pdo_mysql,sodium,openssl,json,session;curlis needed later for GoCardless. - Two strong different cPanel MySQL user passwords: one for Master, one for Company ABC. Do not send any passwords here.
- DO NOT upload
05-Developer-Source.zipinto public_html; it is developer source and design references. - For cPanel accounts, database names are automatically prefixed (example
cpusername_rm_master). Use the actual full name shown in cPanel.
Step 1 — Create the main Master Control database
- Open Namecheap → Hosting List → Go to cPanel → Database Wizard.
- Create database e.g.
rm_master(cPanel will show something likecpusername_rm_master). - Create its own MySQL user and strong password. Give that user privileges only on that database.
- Open phpMyAdmin; select the Master database only. Import these files from
04-Databases.zipin exactly this order:database/01_master_control.sqldatabase/05_unified_security.sql
- Confirm you see
master_users,master_user_totp,tenants,plans,subscription_contracts, andmaster_audit_logs.
Step 2 — Upload the website to the EMPTY public_html
- Go to cPanel → File Manager → public_html.
- Upload
01-Public-Website.zip, then Extract it there. The ZIP contains website files directly (index.html,assets/,api/), so extraction insidepublic_htmlplaces them correctly. If cPanel creates a wrapper folder, move its contents into actualpublic_html. - The actual docroot should show
index.html,assets/,api/, and.htaccessimmediately insidepublic_html. - Open
https://repmojo.com/to view the redesigned sales website. The subscription form remains enquiry only, with no payment.
Step 3 — Upload the PRIVATE backend (outside public_html)
- In File Manager, navigate to
/home/YOUR_CPANEL_USER/(the parent ofpublic_html). - Create folder
repm-privatedirectly in your home directory. Open that new folder and upload/extract04-Private-PHP-Engine.zipINSIDE it. The ZIP containsbackend/,tenant-template/,config.example.php, etc. Make sure the final path is exactly/home/YOUR_CPANEL_USER/repm-private/and NOTpublic_html/repm-private/. - Copy
repm-private/config.example.phptorepm-private/config.php. - Open
config.phpand enter your real Master DB host/name/user/password. Use'environment'=>'staging'initially. - Keep the file private. Permissions
600for credentials where supported (you can set permissions using cPanel File Manager).
Step 4 — Upload and set up Master Control
- In
public_html, create thecontrolfolder, then OPENcontrol. Upload and extract02-Master-Control.zipINSIDEpublic_html/control/. This ZIP containsindex.html,api/,setup.php, etc. DO NOT extract it directly inpublic_htmlor it would overwrite the public website. - Verify
public_html/control/index.htmlandpublic_html/control/setup.phpexist. - Visit
https://repmojo.com/control/setup.phpover HTTPS. The setup script creates a random private key on first use. - In cPanel File Manager read the random setup key at
repm-private/install-secrets/setup.key. Keep it private. - In your browser setup page enter your own Master email and a unique 14+ character password.
- Setup generates a 2FA authenticator secret shown once. Enter it in an authenticator app (e.g. Google Authenticator or Microsoft Authenticator) and keep a secure backup.
- DELETE
public_html/control/setup.phpimmediately after successful setup. - Open
https://repmojo.com/control/and sign in with your Master email, password and six-digit authenticator code. - Master Control should show Companies and other existing modules using the integrated PHP API. If it shows empty tables, that is normal until you create tenants.
Step 5 — Create a SEPARATE ABC wholesale-company database
- In cPanel → Database Wizard, create a second database e.g.
rm_abcand a new different MySQL user. - Grant this user privileges only over the ABC database; do not grant access to the Master DB.
- In phpMyAdmin, select ABC's database, import
database/02_tenant_company.sqlfrom04-Databases.zip. - For a harmless test only, you may subsequently import
database/03_staging_seed_EXAMPLE_ONLY.sql(it contains fictional data; never import into a real tenant database). - Check that the ABC database has
users,roles,user_roles,customers,products,orders, andorder_items.
Step 6 — Create ABC's OWN /abc/ folder using Master Control
- Remain signed in at
https://repmojo.com/control/with Master administrator access. - Expand Install a staging wholesale company at the bottom of the Master workspace.
- Fill in:
- Company folder:
abc(this becomeshttps://repmojo.com/abc/). - Company name and ABC company administrator's email and strong password.
- The full ABC database host/name/username/password from Step 5, NOT the Master credentials.
- Company folder:
- Click Prepare company folder & administrator. The wizard checks the database tables, creates a
company_adminlogin, copies the complete company-template files topublic_html/abc/(including a company landing page at/abc/), and writesrepm-private/tenants/abc.jsonsecurely. - Verify the new URLs:
https://repmojo.com/abc/office/— ABC Office Adminhttps://repmojo.com/abc/rep/— ABC iPad orderinghttps://repmojo.com/abc/api/index.php?route=/v1/health— ABC API
- Sign in to ABC Office with the ABC administrator email/password. Your Master login will not sign in to ABC's Office.
- The company is marked internal staging only. A successful staging sign-in is NOT evidence of a paid subscription.
Note: cPanel may restrict file permissions or disk operations. If the provisioning step fails, read the cPanel PHP Error Log, check directory permissions and whether a partial abc/ folder or abc.json was created. Do not delete a partially created database or blindly retry if duplicate records exist. Run a fresh test with a separate slug if needed. Automated restoration/rollback on a partial multi-database failure is not yet complete.
Step 7 — Create the second company's INDEPENDENT installation
Repeat Steps 5 and 6, but create its own new MySQL DB/user (e.g. cpusername_rm_second) and enter the slug 2nd-company. The wizard creates:
public_html/2nd-company/office/public_html/2nd-company/rep/public_html/2nd-company/api/repm-private/tenants/2nd-company.json
Never point multiple company folders at the same tenant DB. Each company must have unique DB credentials, separate users and separate customer/product/order data.
Step 8 — Isolation and functionality checks
- ABC Office must display only ABC database records. A second company's Office must display only second company's records.
- Sign in to ABC, then try the 2nd-company API from the ABC page. The browser has different session cookie paths, and server route bindings must reject cross-tenant access.
- On
/abc/office/, test searching Orders/Customers/Products, adding a customer and making a simple order. The backend recalculates prices and VAT. - Test the row popups, columns, CSV export, audited stock adjustments and document preview-only actions.
- On
/abc/rep/, sign in online, select customer and take a simple test order. Check that Office receives it. Offline orders are queued and submitted only after server acceptance. - Check
https://repmojo.com/abc/api/index.php?route=/v1/office/data/customerswithout an authenticated ABC session — it should give 401. - Verify every account/password is different for Master and companies. Never send credentials in a support screenshot.
Step 9 — GoCardless status: IMPORTANT
No customer should be charged or activated yet. Main website packages are enquiry-only; there is no working GoCardless checkout/subscription creation or fully verified payment reconciliation. The central endpoint /control/webhook.php?route=/v1/webhooks/gocardless only validates event signatures and stores events in Master DB. After provider sandbox testing, paid onboarding needs a billing worker that verifies payment status server-to-server, then authorises a non-demo company provisioning job. Webhook received ≠ successful payment. Never mark a new tenant active solely from a browser form or GoCardless mandate authorisation.
Step 10 — Development sources (Node.js, Next.js, React/Vite)
06-Developer-Source.zip includes Next.js marketing source, React/Vite Office and Master starter projects, and the approved Prototype 23 design reference. The uploaded, ready-to-run frontend in R2 is built static HTML/CSS/JavaScript backed by PHP/MySQL. It is not yet a compiled Next.js/React replacement with full Prototype 23 parity. The Node source is for the future compiled release, not to be uploaded over these interfaces without testing.
Step 11 — Security and maintenance
- Turn on Namecheap backups and make independent copies of the Master and every tenant's database. Test a real restore.
- Use HTTPS and protect
/control/with strong logins and TOTP. The Master and company sessions are scoped to separate URL paths. - Keep
/repm-private/outsidepublic_htmland delete setup.php. - Customer-specific application files exist in their own folder, but this R2 build shares a PHP engine in
repm-private/backend/. It is not yet capable of independent PHP backend version upgrades per company. - Master staging installer is deliberately disabled when
environmentbecomesproduction; paid onboarding and per-company deployments need billing and rollback gates. - Remove or disable the staging company installer before accepting live subscriptions. Consider cPanel Directory Privacy for Master Control until audited.
- Financial posting, purchase-order workflow, full accounting, multi-warehouse automation, automatic upgrades/backups, offline privacy controls and end-to-end payments are NOT production-ready in R2.
Troubleshooting (without sharing secrets)
| Symptom | Check |
|---|---|
setup.php says extension missing |
Enable pdo_mysql and sodium in cPanel PHP Selector |
503 Database |
Full cPanel DB prefixes, hostname and privileges, SQL import order |
| Master login requests MFA | Authenticator secret from first setup |
| Tenant installer rejects slug | Lowercase letters, numbers or hyphens, 3–39 chars, unique slug, not reserved |
| Company exists but shows no records | Company DB is empty or optional sample seed wasn't imported |
| Installer 403 | You must be signed into Master Control with valid session/CSRF, and environment must be staging |
Directory not found |
Check actual ZIP extract location and avoid nested public_html |
| GoCardless not collecting | This release does not include a live GoCardless checkout; do NOT enable real subscriptions |
Acceptance criteria to move out of staging: real MySQL CRUD and isolation tests on two companies, payment sandbox reconciliation tests, security audit, double-entry accounting and inventory integration, offline queue security, backup restore, independent release pinning and automatic provisioning with safe rollback.