Internal Learning & Development application for the Avana Group (AMD = Avana Medical Devices, ASS = Avana Surgical Systems, ATS = Avana Technology Services). Live at https://academy.avanasurgical.com.
prototype/index.html — a single-file clickable prototype of the full
product, built from the LD Application Requirements Checklist. Everything
runs client-side on sample data. It is the working spec: when building a
module, open the prototype and match its behaviour and fields. It stays
browsable at https://academy.avanasurgical.com/prototype/ (simulated login).client/ + server/) on the
same stack as the company’s Maverick app. Phase 1 (below) is live.client/ — React 18 + Vite + react-router SPA. Design tokens in
client/src/styles.css are carried over from the prototype (cream/gold
theme, Fira Sans / Arimo) — keep new UI consistent with them.server/ — Express API. PostgreSQL via pg. No ORM: plain SQL.
src/migrations/*.sql — forward-only migrations, applied automatically at
server start (src/db.js). Never edit an applied migration; add a new one.src/auth.js — DB-backed sessions (SHA-256 token hash in sessions),
requireAuth / requireRole('admin') middleware, audit() helper.src/zoho.js + src/routes/auth.js — Zoho OAuth (authorization code).server/.env (see .env.example). Secrets are NEVER committed./api route passes through
requireAuth, which joins the session to users and requires active=TRUE.
Disabling a user deletes their sessions → instant revocation.super_admin > admin > manager. Only super admins manage super
admins. Self-deactivation is blocked.reason recorded in audit_log. Keep every new module on this pattern./var/www/academy-next (tracks main).academy → server/src/index.js on port 3200./etc/nginx/sites-available/academy): serves client/dist static,
proxies /auth, /api, /healthz to :3200, aliases /prototype/ to the
prototype/ folder. Let’s Encrypt auto-renews.academy, user academy_user (password only in
server/.env on the droplet and /root/.academy_dbpass).https://academy.avanasurgical.com/auth/zoho/callback. Credentials only in
the droplet .env.main, then on the droplet:
cd /var/www/academy-next && git pull
(+ cd client && npm ci && npm run build if the client changed;
cd server && npm ci if server deps changed) then pm2 restart academy.
Migrations run automatically on restart.pm2 restart all, never touch other vhosts.server/: copy .env.example → .env, point DATABASE_URL at a local
Postgres, set DEV_LOGIN=true (e-mail-only login on the sign-in screen —
the user must exist in users; insert one by hand or via npm run seed
with SEED_ADMIN_EMAIL set). npm install && npm start.client/: npm install && npm run dev → http://localhost:5174 (proxies
/api and /auth to :3200).DEV_LOGIN is for. It is hard-disabled when
NODE_ENV=production.#att/), admin corrections with reason..xlsx export.Business rules baked into the checklist: INR, IST, Apr–Mar financial year, 80% pass mark, 75% attendance eligibility, Zoho employee IDs.
--update-env does not re-read an ecosystem file; recreate the
process (pm2 delete + pm2 start) after env changes. Plain .env via
dotenv (current setup) only needs pm2 restart academy.pkill -f 'node src/index.js' kills its own shell
(pattern matches itself) — write it as pkill -f 'node src/[i]ndex.js'.PUSHPA~1) crashes its
file watcher — always use full long paths.Secure when BASE_URL is https — for local http
testing BASE_URL must be http or the browser drops the cookie./var/www/academy (prototype era);
that directory is only a rollback artifact now.