YDM Lean Platform
Imagine Office 365, except every tool actually talks to the others, there are 22 of them, and the whole thing exists to out-lean the factories that invented lean
Screenshots
Operational excellence teams run on a dozen disconnected tools: 5S audits in one spreadsheet, kaizen suggestions in another, the QMS in a binder, and OKRs in a slide deck nobody opens twice. YDM is one platform where all of it is the same data model, so a near-miss report can become a corrective action, which can close a finding on an internal audit, without anyone re-typing anything.
Twenty-two modules ship in the box: 5S and gemba, HES/SEC/YAK safety cycles, kaizen workshops and idea pipelines, OKRs and KPI deviation, the full QMS (audits, plans, question pools, non-conformities, change requests, corrective actions), supplier management with 8D and a supplier portal, calibration with reminders, meetings and decisions, surveys, tickets, tasks, and the executive dashboard that reads across all of them.
One instance, one database each
Every tenant gets its own MySQL database. Not a tenant_id column but an actual
separate database, so there is no query in the codebase that could leak a row
across customers even if someone forgot a where.
Routing makes that invisible. Traefik terminates TLS for *.ydmsoftware.com
with automatic Let’s Encrypt certificates and forwards to the Next.js frontend.
The API reads the host, resolves the tenant slug, and injects a Prisma client
built from that tenant’s connection string, cached in an LRU pool so the
hundredth request doesn’t open the hundredth connection. Adding a customer is a
row in the master database and a migration run; no restart, no redeploy, no
per-tenant container.
The parts that are actually hard
Keeping schemas in step. Twenty-two modules under active development, times every tenant database. Migrations run across all active tenants from one script, and the tenant iterator that powers it is the same one the cron jobs use.
Work that has to happen whether or not anyone logs in. Audits generate themselves on their cycle. Meetings open and auto-close. Field tours and workshops close on schedule. Calibration reminders and supplier 8D chasers go out by email. All of it iterates every active tenant, which means every job is written as if it will be run against a hundred databases, because it will be.
Not being the reason a factory stops. Helmet, a CORS allowlist, Redis-backed sessions and rate limiting, JWT with refresh, bcrypt, an API-key gate in front of the API, IP blocking managed from the superadmin, request size and timeout guards, and an audit log on anything sensitive. Health endpoints report Redis liveness and the tenant connection-pool stats, because “is it up” and “is it about to fall over” are different questions.
Around the edges
A separate upload service normalises images to WebP with Sharp and writes them under a per-tenant path that Nginx serves from a CDN subdomain, so business logic never holds a binary. A superadmin dashboard governs tenants, partners, API keys, exhibition leads, support tickets and blocked IPs across the whole platform. Socket.IO carries notifications. Gemini and Groq power summaries and generative helpers inside the reporting modules.
Backups dump the master database, every tenant database, and the whole upload tree, then rotate. It is the least interesting script in the repository and the one I would miss first.
▸ stack