Jira progress: loading…
EcoWorld Academy Platform — Deployment Guide
Viroway Ltd | Phase 1
Prerequisites
- AWS CLI installed and configured:
aws configure - Node.js 20+ installed:
node --version - AWS CDK installed:
npm install -g aws-cdk - Active HubSpot account with Private Apps access
Step 1 — HubSpot setup (15 minutes)
1.1 Create Private App
- In HubSpot: Settings → Integrations → Private Apps → Create Private App
- Name:
EcoWorld Academy Sync - Description:
Syncs Academy learner registrations as HubSpot contacts - Required scopes:
crm.objects.contacts.readcrm.objects.contacts.writecrm.objects.companies.readcrm.objects.companies.writecrm.schemas.contacts.read
- Click Create app → copy the access token
1.2 Add custom Company properties
In HubSpot: Settings → Properties → Company properties → Create property
| Property name (internal) | Label | Type |
|---|---|---|
ecoworld_company_code | EcoWorld company code | Single-line text |
ecoworld_seats_purchased | Academy seats purchased | Number |
ecoworld_course_assigned | Course assigned | Single-line text |
ecoworld_cohort_start | Cohort start date | Date |
ecoworld_enrolment_status | Academy enrolment status | Dropdown: Pending / Active / Completed |
ecoworld_completion_pct | Training completion % | Number |
ecoworld_certificates_issued | Certificates issued | Number |
ecoworld_last_dashboard_sync | Last dashboard sync | Date |
1.3 Add custom Contact properties
| Property name (internal) | Label | Type |
|---|---|---|
ecoworld_user_id | EcoWorld user ID (Cognito) | Single-line text |
ecoworld_completion_pct | Training completion % | Number |
ecoworld_certificate_issued | Certificate issued date | Date |
ecoworld_last_active | Last active in Academy | Date |
1.4 Populate company records
For each client company:
- Find their Company record in HubSpot
- Set
ecoworld_company_codeto a unique code (e.g.,NORSK-HYDRO-2026) - Set
ecoworld_seats_purchased,ecoworld_course_assigned,ecoworld_cohort_start - This code is what you include in the learner invite link:
https://academy.ecoworld.ai/register?company=NORSK-HYDRO-2026
Step 2 — Store secrets in AWS (5 minutes)
# HubSpot Private App token
aws secretsmanager create-secret \
--name ecoworld/hubspot-token \
--secret-string '{"token":"YOUR_HUBSPOT_TOKEN_HERE"}' \
--region eu-west-1
# HubSpot Portal ID (find in HubSpot Settings → Account Setup)
aws secretsmanager create-secret \
--name ecoworld/hubspot-portal-id \
--secret-string '{"portalId":"YOUR_PORTAL_ID"}' \
--region eu-west-1
Step 3 — Deploy AWS infrastructure (10 minutes)
cd infra
# Install CDK dependencies
npm init -y
npm install aws-cdk-lib constructs
# Bootstrap CDK (first time only, per account/region)
npx cdk bootstrap aws://YOUR_ACCOUNT_ID/eu-west-1
# Preview what will be created
npx cdk diff
# Deploy everything
WEBFLOW_ORIGIN=https://academy.ecoworld.ai npx cdk deploy EcoWorldAcademy
Save the outputs — you'll need them for Step 4:
EcoWorldAcademy.UserPoolId = eu-west-1_XXXXXXXXX
EcoWorldAcademy.UserPoolClientId = XXXXXXXXXXXXXXXXXXXXXXXXXX
EcoWorldAcademy.ApiEndpoint = https://XXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/v1
EcoWorldAcademy.CognitoHostedUI = https://ecoworld-prod.auth.eu-west-1.amazoncognito.com
Step 4 — Configure Webflow (10 minutes)
4.1 Update the JS config
Open frontend/ecoworld-academy.js and update the CONFIG section:
const CONFIG = {
userPoolId: "eu-west-1_XXXXXXXXX", // From CDK output
clientId: "XXXXXXXXXXXXXXXXXXXXXXXXXX", // From CDK output
cognitoDomain: "ecoworld-prod.auth.eu-west-1.amazoncognito.com",
apiBase: "https://XXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/v1",
siteUrl: "https://academy.ecoworld.ai",
postLoginPath: "/academy",
};
4.2 Add to Webflow
- In Webflow: Site Settings → Custom Code → Footer Code
- Paste the entire
frontend/ecoworld-academy.jscontent inside<script>tags - Publish the site
4.3 Add Webflow page attributes
On each page body element, add:
- Workbook page:
data-eco-page="workbook" - Dashboard page:
data-eco-page="dashboard" - Risk tool page:
data-eco-page="risk-tool"
On buttons:
- Login button:
data-eco-action="login" - Logout button:
data-eco-action="logout"
On nav elements:
- User name:
data-eco-user="name" - Company name:
data-eco-user="company"
Show/hide by login state:
- Logged-in elements:
data-eco-auth="logged-in" - Logged-out elements:
data-eco-auth="logged-out"
Step 5 — Test the full flow (30 minutes)
5.1 Create a test company in HubSpot
- Add company:
Test Company Ltd - Set
ecoworld_company_code=TEST-2025 - Set
ecoworld_seats_purchased=5
5.2 Test learner registration
- Open:
https://academy.ecoworld.ai/register?company=TEST-2025 - Should redirect to Cognito hosted login
- Register a new user with a real email
- Confirm email
- Check:
- ✓ DynamoDB
ecoworld-progresshas a newLEARNER_PROFILErow - ✓ HubSpot has a new Contact linked to
Test Company Ltd - ✓ Cognito user has
custom:hubspot_company_idattribute set
- ✓ DynamoDB
5.3 Test the workbook
- Log in and navigate to
/academy - Type in a workbook exercise textarea (must have
data-eco-exercise="1.1:exercise-name") - After 2 seconds, should auto-save
- Refresh the page — answer should be restored
- Progress bar should show updated %
5.4 Test the admin dashboard
- In Cognito console, set a user's
custom:roleattribute toadmin - Log in as that user
- Navigate to the dashboard page
- Should see all learners and their progress
Monitoring and troubleshooting
CloudWatch Logs
Each Lambda writes to its own log group:
/aws/lambda/ecoworld-prod-post-confirmation
/aws/lambda/ecoworld-prod-hubspot-sync
/aws/lambda/ecoworld-prod-save-answer
/aws/lambda/ecoworld-prod-get-progress
/aws/lambda/ecoworld-prod-risk-score
/aws/lambda/ecoworld-prod-dashboard
Common issues
| Issue | Likely cause | Fix |
|---|---|---|
| HubSpot sync not firing | Cognito trigger not attached | Re-deploy CDK stack |
| Company not found in HubSpot | ecoworld_company_code not set | Add the custom property in HubSpot and set it on the company record |
| Token exchange fails | Redirect URI mismatch | Add your Webflow URL to the Cognito app client callback URLs |
| CORS errors in browser | Wrong WEBFLOW_ORIGIN | Update the env var and re-deploy |
| Progress not loading | User not logged in | Check Cognito token expiry (1hr default) |
Cost estimate (monthly)
At 200 active learners across 10 client companies:
| Service | Estimated cost |
|---|---|
| AWS Cognito | Free (first 50k MAU) |
| DynamoDB (on-demand) | ~€2 |
| Lambda (200 users × 50 calls/day) | Free (1M calls/month included) |
| API Gateway | ~€1 |
| CloudWatch Logs | ~€1 |
| Secrets Manager | ~€0.40 |
| Total | ~€4–5/month |
Next phases
- Phase 2: Supplier questionnaire portal (suppliers get a link, fill form, responses stored)
- Phase 3: Full supplier monitoring dashboard with CAP tracking
- Phase 4: LearnWorlds → AWS completion sync (so quiz scores flow into the unified dashboard)