The marketing site for CGE — built as static HTML/CSS/JS with a small PHP contact handler. Designed to be hosted on Afrihost Linux (shared) and auto-deployed via GitHub Actions over FTP.
- HTML / CSS / vanilla JS for the standalone pages (About, Work, Blog, Contact, 404)
- React 18 + Babel-in-browser for the marketing pages that render from JSX (
/index.html,/services/*.html). Source lives in/site/*.jsx. Loads React from unpkg. - PHP 7+ for the contact-form handler (
/contact.php) — usesmail(), no extensions required. - .htaccess for pretty URLs, security headers, caching, and gzip.
.
├── index.html # Home (renders all sections from JSX)
├── about.html
├── work.html
├── contact.html
├── 404.html
├── contact.php # Form handler
├── .htaccess # Apache config
├── robots.txt
├── sitemap.xml
├── site/ # JSX source (React components)
│ ├── tokens.jsx # Design tokens + primitives
│ ├── sections-1.jsx # Nav, Hero, Marquee, Manifesto, Services
│ ├── sections-2.jsx # Method, CaseSpotlight, Stack
│ ├── sections-3.jsx # Thinking, About, Testimonials, Pricing, FAQ, BigCTA, Footer
│ ├── service-data.jsx # SERVICE_DETAILS dictionary
│ ├── service-page.jsx # ServicePage template
│ └── app.jsx # Home composition
├── services/
│ ├── web-development.html # Each renders <ServicePage slug="..."/>
│ ├── ppc.html
│ ├── tracking.html
│ ├── business-software.html
│ ├── optimization.html
│ ├── analytics.html
│ └── automation.html
├── blog/
│ ├── index.html # Field-notes index
│ └── the-best-growth-teams-ship-faster.html
├── assets/
│ ├── css/site.css
│ ├── js/contact.js
│ └── img/favicon.svg
└── .github/workflows/deploy.yml
The site is static — any HTTP server will do.
# from the repo root
python3 -m http.server 8000
# or
npx serve .Open http://localhost:8000/. Note: contact.php needs a PHP-capable server to submit:
php -S localhost:8000Every push to main triggers .github/workflows/deploy.yml, which mirrors the repo to your Afrihost
public_html/ over SFTP (port 22) using lftp. Afrihost's firewall blocks plain passive FTP, so
SFTP is the supported transport. This GitHub Action is the single deploy mechanism — there is no
cPanel auto-deploy (the old .cpanel.yml was removed to avoid two systems writing to public_html).
-
Push this repo to GitHub (see the next section).
-
Get FTP credentials from Afrihost. Log into the Afrihost ClientZone → cPanel for
chiefgrowthengineer.com. Either use the main cPanel FTP account or create a dedicated one:- Server: usually
ftp.chiefgrowthengineer.com(or the Afrihost server hostname shown in cPanel) - Username: typically
youraccount@chiefgrowthengineer.comfor an additional account, or your main cPanel user - Password: as set
- Target dir: usually
public_html/(Afrihost shared default). If your account routes the domain to a different folder, note that path.
- Server: usually
-
Add the secrets to the GitHub repo at https://github.com/roblouw2nd/cge/settings/secrets/actions:
FTP_SERVER— the SFTP/cPanel host (e.g. the Afrihost server hostname, orchiefgrowthengineer.com)FTP_USERNAME— your cPanel usernameFTP_PASSWORD— the cPanel password- (optional)
FTP_PORT— defaults to22. Override if Afrihost uses a custom SSH/SFTP port. - (optional)
FTP_TARGET_DIR— defaults topublic_html. Override if the domain routes elsewhere.
-
Trigger a deploy: push any commit to
main, or go to the Actions tab → "Deploy to Afrihost" → "Run workflow".
- Transport is SFTP over port 22 (set
FTP_PORTto override). SFTP/SSH access must be enabled on the Afrihost account — if it isn't, request it via Afrihost support, otherwise the connection step fails. mirror --reverse --deletemakes the server match the repo, so files removed from the repo are also removed frompublic_html. Anything that must live only on the server should sit outsidepublic_html.- The
excludeblock keeps.git/,.github/,README.md,node_modules/, etc. off the live server.
The remote is https://github.com/roblouw2nd/cge. From this folder:
git init
git add .
git commit -m "Initial CGE site"
git branch -M main
git remote add origin https://github.com/roblouw2nd/cge.git
git push -u origin mainAfter the push, configure the FTP secrets (above) and the next push will deploy automatically.
contact.php handles the contact page and all /tools/ lead forms. On every valid submission it:
- Logs the lead to
~/cge-leads.jsonl(one directory abovepublic_html, never deployed, never in git) before attempting mail — a mail outage can't lose a lead. - Emails the enquiry to
rob@chiefgrowthengineer.comwith Reply-To set to the sender. - Sends the sender a branded thank-you (multipart plain-text + HTML) containing the booking
link (
https://calendar.app.google/vXohio54MnjJy57X7) and a copy of what they submitted — for tool leads that means their own scorecard lands in their inbox. Auto-reply failures are logged but never fail the request.Auto-Submitted: auto-repliedprevents responder loops.
Protections: honeypot (company_url must be empty), per-IP rate limit (5/hour, timestamp files
in ~/cge-ratelimit/, fails open), field-length caps, header-injection stripping.
Transport: if /home/<cpanel-user>/cge-mail-config.php exists (returns
['smtp_user' => ..., 'smtp_pass' => ..., 'smtp_host' => 'smtp.gmail.com', 'smtp_port' => 587]),
mail goes out via authenticated Google Workspace SMTP; otherwise it falls back to PHP mail().
Test with a real submission after any deploy.
- Marketing/services copy — edit the JSX files in
/site/. The browser will Babel-transform on reload. - Static pages (About, Work, Blog, Contact) — edit the corresponding
.htmldirectly. - New blog post — copy
blog/the-best-growth-teams-ship-faster.htmlto a new file with a clean URL slug, edit the content, and add it toblog/index.html+sitemap.xml.
Babel-in-browser is fine for launch but slower on first paint than pre-rendered HTML. When the site has traffic worth optimising for, swap the JSX pages for either:
- An Astro / Next.js static build (export the same components,
astro build→dist/→ FTP) - Server-side render the React components once via
react-dom/serverin a Node build step.
Either way, no Afrihost config changes needed — the deploy target stays static public_html/.
© CGE Group · chiefgrowthengineer.com