A multi-tenant platform: form builder, requests, approval chains, logs, an admin panel with IAM permissions. No screenshots — the project is internal. So this case is built on diagrams and reasoning.
Vue 3multi-tenantIAMinternal product
The task
Several tenant companies work in one system: they build forms for their processes, run requests through approval chains, keep logs. Permissions live at the IAM level: who sees, who approves, who administers.
I work as a frontend developer on the product team: interfaces for the form builder, requests, logs and admin panel, plus the client-side architecture.
What was hard
01
A frontend architecture you cannot break by accident
Three layers between the server and the screen: api.js knows HTTP, services know the domain, composables know state. Components are “dumb”: they only render, hold no logic, and never call api.js directly — forbidden by linter rules, not by verbal agreement. The allowlist of legacy imports is pinned down and keeps shrinking.
02
One filter, two data strategies
Stages belong to a form, but request lists come in two kinds: logs bound to a single form, and mixed lists whose rows come from different forms with different stage sets. There is no single way to build the options — so two strategies hide behind one filter. A capability matrix pins down which section supports which filters, so the UI never draws a filter the backend will not accept.
03
A bug whose symptom and cause live in different layers
Navigation broke in the navbar, but the cause lived two layers below: while parsing the IAM response, a role string was spread — turning into an array of characters. Each “character role” was then faithfully processed by the whole chain. Bugs like this are the argument for layered architecture: the search path was short because the layers were not mixed.
What was done
Form builder and requests flowing through approval chains
Operation logs and an admin panel with IAM permissions
A three-layer frontend architecture enforced by linter rules
A stage filter with two encapsulated data strategies
The result
Architecture rules are checked by the linter in CI and do not depend on team memory. The platform keeps growing; the project is ongoing.