1. What Empever achieves
Empever is an operational platform delivered from a single domain (empever.com). Employers find leads, manage CRM accounts, and build hiring teams; candidates find matched jobs and onboard into payroll; Marketing runs outreach and placement pipelines; and Payrolls handles staff records — all from one hub with shared navigation and a client switcher per organisation.
| Department | Public path | Primary capability |
|---|---|---|
| Hub | / | Landing, master login gate, workspace shell, client switcher |
| HR / Payrolls | /hr/ | Invoices, payroll runs, HRMS, compliance, per-client payroll DBs |
| Jobs | /jobs/ | Candidate apply, employer roster, interview invites, shortlists, academy |
| Empever Marketing | /marketing/ | Lead pool ingestion (Reddit, LinkedIn, web), CRM accounts, skill-matched project leads, outreach pipeline |
| Technical | /technical/ | Academy, assessments, interview prep — often embedded in Jobs |
Company: Empever is a new venture — the operational platform at empever.com for leads, hiring, CRM, and payroll. Sevendyne is a platform client: a tech consultancy in Kochi, India, whose customers are managed through Empever (alongside other tenants such as Ansif).
2. System context
flowchart TB
subgraph users [Users]
Team[Internal team]
Candidates[Candidates / employers]
end
subgraph dns [DNS]
Apex[empever.com]
Www[www.empever.com]
end
subgraph gcp [GCP asia-southeast1]
Web[empever-web nginx hub + gateway]
HR[empever-hr Next.js + Django]
Mkt[empever-marketing Express + Vite]
Tech[empever-technical Vite SPA]
Jobs[empever-jobs static + Flask]
end
Team --> Apex
Team --> Www
Candidates --> Apex
Apex --> Web
Www --> Web
Web -->|/hr/| HR
Web -->|/marketing/| Mkt
Web -->|/technical/| Tech
Web -->|/jobs/| Jobs
Mkt --> CRM[(SQLite CRM per tenant)]
HR --> PayrollDB[(Payroll DBs per client)]
Jobs --> PortalDB[(Candidates workspace DB)]
Request flow (production):
- Browser hits
https://empever.com/hr/login. - DNS resolves to Cloud Run domain mapping on
empever-web. empever-webnginx matcheslocation /hr/and proxies toEMPEVER_HR_UPSTREAM, preserving the path prefix.empever-hrserves the Next.js shell and Django HRMS behind its own nginx layer.
Hub static assets (index.html, login/, js/, config/) are served directly from empever-web without proxying.
3. Monorepo layout
empever/ ├── index.html, login/, hub/, workspace/, invest/ # Static hub ├── js/, css/, config/ # Shared hub runtime ├── architecture/ # This page ├── docker/ # Hub Dockerfile + nginx ├── scripts/ # Deploy, gateway, auth ├── payrolls/ # HR department ├── jobs/ # Hiring — talent apply & employer hire ├── marketing/ # Placement outreach & CRM ├── devkits/ # Technical / academy (embedded in Jobs) └── Dockerfile + cloudbuild.yaml # empever-web build
Hub (repo root)
Static HTML + JavaScript — no Node server in production. Key files: config/platform-clients.json (client registry), config/platform-nav.json (nav paths), js/platform-clients.js (URL builder), js/master-auth.js (hub login → Marketing API).
HR — payrolls/
Stack: Next.js + Django HRMS + nginx · Service: empever-hr · Path: /hr/
Jobs — jobs/
Stack: Static HTML + Flask API · Service: empever-jobs · Path: /jobs/. Candidate profiles, employer matching, interview pipeline, workspace auth.
Empever Marketing — marketing/
Stack: Express API + Vite/React SPA + nginx · Service: empever-marketing · Path: /marketing/. Lead pool ingestion, CRM accounts, skill-first employer/candidate matching, outreach pipeline. Hub login integration (embedded iframe skips second login).
Technical — devkits/
Stack: Vite/React SPA · Service: empever-technical · Path: /technical/. Academy and interview prep — embedded in Jobs candidate workspace.
4. Gateway architecture
Production uses a single ingress service (empever-web) with nginx path proxies — one TLS certificate, one domain mapping, four upstream backends.
| Location | Upstream env var | Behavior |
|---|---|---|
/ | (local static) | Hub HTML, JS, CSS, config JSON |
/hr/ | EMPEVER_HR_UPSTREAM | Reverse proxy, 300s read timeout |
/marketing/ | EMPEVER_MARKETING_UPSTREAM | Reverse proxy + WebSocket headers |
/technical/ | EMPEVER_TECHNICAL_UPSTREAM | Reverse proxy |
/jobs/ | EMPEVER_JOBS_UPSTREAM | Reverse proxy |
docker/start-empever-web.sh renders the gateway config via envsubst when all four upstream env vars are set; otherwise it falls back to static-only nginx (hub works; department paths 404).
After deploy, scripts/configure-empever-gateway.sh discovers each Cloud Run URL and sets upstream env vars on empever-web.
5. Platform clients (multi-tenancy)
Empever is a multi-client platform. The hub Switch client picker drives isolated data and outbound identity across departments.
| File | Purpose |
|---|---|
config/platform-clients.json | Hub UI: slug, CRM subdir, jobs tenant, payroll DB |
marketing/data/crm/client_outbound.json | From name/email + SMTP env prefix |
marketing/data/crm/outreach_profiles.json | Placement outreach copy per client |
marketing/channel/backend/.env.local | SMTP/IMAP secrets (gitignored) |
Hub Switch client
→ sessionStorage: empever_platform_client
→ App URLs: ?platform_client= & ?crm_subdir= & ?payroll_db=
→ API headers: X-Empever-Platform-Client, X-Empever-Crm-Subdir
→ CRM SQLite: data/crm/tenants/{subdir}/crm.db
→ SMTP: SMTP_{PREFIX}_* from .env.local
Default clients: sevendyne (production ICP) and dummy_client (sandbox).
6. Authentication architecture
There is no single sign-on across all apps today. Each department maintains its own session, coordinated by a global auth switch and hub master login.
| App | Login URL | Session |
|---|---|---|
| Hub / workspace | /login/ | Marketing API hub-login |
| Marketing | /marketing/login | Express session leads.sid |
| HR (Next) | /hr/login | JWT cookie |
| Django HRMS | /accounts/login/ | Django session |
| Jobs | /jobs/login.html | sessionStorage |
| Technical | Via Jobs embed | No standalone login |
Global switch: config/platform-auth.json · Toggle: scripts/enable-platform-auth.sh / disable-platform-auth.sh
Production defaults (June 2026)
Marketing production image sets EMPEVER_MARKETING_SKIP_LOGIN=0 and LEADSAPP_REQUIRE_AUTH=1. Local dev keeps auth off via marketing/docker-compose.dev.yml.
Hub iframe embed does not rely on SKIP_LOGIN — it uses hubEmbedAuth (?empever_embed=1 + X-Empever-Platform-Client header, or hub-login cookie after POST /marketing/api/auth/hub-login).
deploy-empever-gcp.sh runs configure-empever-production-auth.sh when EMPEVER_HUB_PASSWORD is set.
7. GCP deployment architecture
| Service | Source | Memory / CPU |
|---|---|---|
empever-web | repo root | 512Mi / 1 |
empever-hr | payrolls/ | 2Gi / 2 |
empever-marketing | marketing/ | 1Gi / 1 |
empever-technical | devkits/ | 1Gi / 1 |
empever-jobs | jobs/ | 512Mi / 1 |
Region: asia-southeast1 · Project: empever-platform-ansifi
EMPEVER_GCP_PROJECT=empever-platform-ansifi bash scripts/deploy-empever-gcp.sh
Deploy pipeline: enable auth → bootstrap GCP → build & deploy 5 services → wire gateway upstreams → optional production auth secrets → print domain mapping commands.
gcloud beta run domain-mappings create --service=empever-web --domain=empever.com --region=asia-southeast1 gcloud beta run domain-mappings create --service=empever-web --domain=www.empever.com --region=asia-southeast1
Deploy performance & timing
A full platform deploy via deploy-empever-gcp.sh typically takes 25–30+ minutes. Individual service deploys are much faster, but every gcloud builds submit still runs the full Cloud Build pipeline.
Observed build times (empever-platform-ansifi, June 2026)
| Service | Archive size | Build duration | Notes |
|---|---|---|---|
empever-web | 280.8 MiB (3,410 files) | 2m 42s | Hub static + nginx gateway image |
empever-hr | 1.2 GiB (57,057 files) | 6m 43s | Largest bottleneck — see below |
empever-marketing | 4.0 MiB (263 files) | 2m 47s | Small source; fixed pipeline overhead dominates |
empever-technical | 4.6 MiB (142 files) | 3m 30s | Small source |
empever-jobs | 4.5 MiB (202 files) | 2m 51s | Small source |
| Full script total | — | ~27 min | Sequential builds + gateway wiring |
Why the full deploy takes long
- Five independent deploys, run sequentially —
deploy-empever-gcp.shwaits for eachgcloud builds submitto finish before starting the next. You pay ~3–7 minutes per service, added together. - HR upload is ~1.2 GiB —
payrolls/has no.gcloudignore, so localnode_modules(~959 MB) anddebugs/(~101 MB) are bundled and uploaded on every HR build. Marketing, Jobs, and Technical each ship only ~4–5 MiB. - Full Cloud Build pipeline per service — Every submit: compress locally → upload tarball to GCS → queue build →
docker build→ push to Artifact Registry → deploy new Cloud Run revision. Even a 4 MiB app spends ~3 minutes on pipeline overhead. - Docker layer cache — Cold or partial cache means longer npm/pip installs inside the remote build.
- Cloud Run revision rollout — After each image push, GCP creates a new revision and routes traffic (usually fast, but one step per service).
Single-service deploys
Deploying only what changed is the fastest day-to-day workflow:
# Hub only (architecture page, index.html, etc.) cd /home/ansif/works/empever EMPEVER_GCP_PROJECT=empever-platform-ansifi gcloud builds submit --config=cloudbuild.yaml . # Marketing only (~3–5 min) cd marketing && gcloud builds submit --config=cloudbuild.yaml .
A single marketing deploy still takes ~3–5 minutes because the Cloud Build steps (upload, remote Docker build, registry push, Cloud Run deploy) run regardless of archive size.
What would speed up deploys
| Change | Impact |
|---|---|
Add payrolls/.gcloudignore (exclude node_modules, debugs/) | Largest win — HR upload drops from ~1.2 GiB to tens of MB |
| Deploy only changed services | Avoid re-running all five builds |
Parallel gcloud builds submit | Cut wall-clock time; harder to debug failures |
| CI/CD with cached Docker layers | Faster repeat builds on every git push |
| Pre-built images (skip source submit) | Build locally or in CI, push image directly |
8. Local development architecture
Local dev does not mirror production path routing by default. Each app runs on its own port.
| App | Local origin | Production path |
|---|---|---|
| Hub | http://127.0.0.1:8092 | https://empever.com/ |
| HR | http://127.0.0.1:3001 | /hr/ |
| Marketing | http://127.0.0.1:5175 | /marketing/ |
| Jobs | http://127.0.0.1:3080 | /jobs/ |
| Technical | http://127.0.0.1:5174 | /technical/ |
./docker-up-all.sh bash scripts/run-localhost.sh
9. Cross-app integration
- Shared platform chrome —
EmpeverPlatformBarin HR, Marketing, Jobs;platform-nav-bar.json hub. - Hiring pipeline — Jobs shortlist API, interview confirm links, in-app notifications; employer status updates through to payroll onboarding (manual today).
- Marketing API as integration layer — syncs candidate intake from Jobs, talent pool, placement CRM, and outreach.
- Hub shell embedding —
/hub/#/{app}loads department apps in an iframe shell.
10. Skill-first lead matching (June 2026 rebuild)
Employer project leads and candidate matched jobs use a shared skill-matching pipeline. External posts are ingested into a central pool; UI refresh filters by profile skills in under one second — no blocking live scan in the request path.
flowchart LR
subgraph sources [External sources]
Reddit[Reddit]
LinkedIn[LinkedIn via web search]
HN[HN / GitHub / SO]
end
subgraph background [Background ingest]
Bulk[hiringBulkIngest cron]
Pool[(web_intel_leads)]
end
subgraph sync [UI refresh - fast]
JobsUI[Jobs workspace]
Match[profileSkillLeadMatch]
EmpStore[(employer_project_leads)]
CandStore[(candidate_job_leads)]
end
sources --> Bulk --> Pool
JobsUI --> Match --> Pool
Match --> EmpStore
Match --> CandStore
Request flow:
- Jobs UI calls
POST /jobs/api/workspace/me/project-leads/match(employer) or.../matched-jobs/match(candidate). - Flask
candidate_api.py→markets_employer_leads.py/markets_candidate_leads.py. - Marketing
POST /api/portal/employer/:user/match-projectsor/candidate/:uuid/match-jobs. runHiringEmployerMatch/runHiringCandidateMatchscan the pool viaprofileSkillLeadMatch.js— technical skills only, minimum hit count, junk filters.- Background
hiringBulkIngest.js(cron + startup) fetches from Reddit, LinkedIn, and web intoweb_intel_leadsfor the next refresh.
Key files changed
| File | Role |
|---|---|
marketing/.../lib/profileSkillLeadMatch.js | Core matcher — pool scan, skill scoring, discovery helpers |
marketing/.../lib/hiringBulkIngest.js | Background bulk ingestion cron |
marketing/.../lib/runHiringEmployerMatch.js | Employer project-lead match (pool-first) |
marketing/.../routes/talentMatch.js | runHiringCandidateMatch — candidate job match |
marketing/.../routes/portalResolve.js | Internal portal APIs for Jobs bridge |
marketing/docker/start-cloudrun.sh | Wait for Node health before nginx (fixes 502 cold start) |
jobs/backend/markets_employer_leads.py | Jobs → Marketing employer match bridge |
jobs/backend/markets_candidate_leads.py | Jobs → Marketing candidate match bridge |
jobs/js/employer-project-leads.js | Employer workspace UI |
jobs/js/candidate-matched-jobs.js | Candidate matched jobs UI |
marketing/data/crm/outreach_profiles.json | Employer match_skills per client (e.g. Sevendyne) |
Env tuning: HIRING_WEB_INTEL_POOL_LIMIT, EMPLOYER_PROJECT_MATCH_MIN, TALENT_MATCH_INTERNAL_MIN, HIRING_BULK_INGEST_DISABLED, TAVILY_API_KEY (web/LinkedIn search quality).
11. Data layer
| Store | Location | Scope |
|---|---|---|
| CRM | marketing/data/crm/tenants/{subdir}/crm.db | Per platform client |
| Outreach | outreach_profiles.json | Per outreach client ID |
| Payroll | Per payroll_db key | HR department |
| Jobs / candidates | jobs/backend/data/rxx_candidates.db | Per jobs_tenant |
| Jobs workspace | jobs/data/workspace/workspace.db | Portal logins |
| Devkits | devkits/data/devkits.sqlite | Technical assessments |
Production persistence (GCS)
Cloud Run has no persistent disk. Each data service syncs SQLite to gs://empever-platform-ansifi-empever-db via EMPEVER_DB_GCS_BUCKET:
| Service | GCS prefix | Sync script |
|---|---|---|
empever-marketing | marketing/ | marketing/docker/db-gcs-sync.sh |
empever-jobs | jobs/ | jobs/docker/db-gcs-sync.sh |
empever-hr | hr/ | payrolls/docker/db-gcs-sync.sh |
empever-technical | technical/ | devkits/docker/db-gcs-sync.sh |
Boot: GCS restore → app start → backup on shutdown (HR: every 5 min). Git SQL seeds run only when EMPEVER_FORCE_SEED_DB=1 — never on routine redeploys. empever-hr stays at max-instances=1 (SQLite single-writer). See jobs/docker/CLOUD_DB_TODO.md.
12. Operational scripts
| Script | Purpose |
|---|---|
deploy-empever-gcp.sh | Full Empever deploy |
configure-empever-gateway.sh | Wire empever-web upstreams |
configure-empever-production-auth.sh | Production auth env on Cloud Run |
pause-empever-gcp.sh | Delete services + domain mappings |
run-localhost.sh | Python static hub on :8092 |
docker-up-all.sh | Local Docker stacks |
14. Current state (June 2026)
| Component | Status |
|---|---|
| All 5 Cloud Run services | Deployed in asia-southeast1 |
| Gateway upstreams | Wired on empever-web |
| Domain | empever.com live |
| Skill-first lead matching | Pool-first refresh + background bulk ingest |
| Production auth | Marketing SKIP_LOGIN=0; hub-login + embed bypass |
| GCS DB persistence | empever-platform-ansifi-empever-db on all data services |
| HR SQLite writer | max-instances=1 + periodic GCS backup |
| Marketing cold start | min-instances=1 + Node health wait before nginx |
| Architecture page | empever.com/architecture |
15. Known gaps
- Dual branding — Empever and Empever share one repo with separate deploy scripts.
- Project ID drift — Older docs reference
empever-497411; live deploy usesempever-platform-ansifi. - No SSO — Hub login gates workspace but does not issue tokens for HR or Jobs.
- GCS stopgap, not Cloud SQL — SQLite file sync survives redeploys; Payrolls should migrate to Cloud SQL long-term.
- payrolls/.gcloudignore — Missing; HR deploy uploads ~1.2 GiB including local node_modules.
16. Architecture principles
- One domain, many services — Users see empever.com; operators deploy five Cloud Run services.
- Hub is static + gateway — Minimal hub container; department complexity lives in child services.
- Client switch is the tenancy boundary — Registry JSON + headers, not separate subdomains.
- Marketing owns hub auth and CRM — Natural integration point for cross-app APIs.
- Independent deployability — Each cloudbuild can run alone; gateway script reconnects upstreams.
- Local-first velocity — Auth off, separate ports, Docker Compose; production adds gateway, auth, DNS.