Getting Started โ
Mono-repo is a way to build a large-scale, modular front-end on top of the Vue ecosystem. The goal is a maintainable, clean, complex project that takes minimum effort to grow.
Concept โ
Vue gives every project the same predictable shape:
src/pagesโ routingsrc/layoutsโ layouts
Inside a layout you usually find the same generic pieces: Sidebar, Navbar, Login, Logout, Middleware. Every normal website needs them.
Mono-repo makes this simple. Those generic pieces live once in the Host, and every Remote can use them without rebuilding.
A Remote only adds its own modules. It does not re-create Login, Logout, or any of the generic things โ the Host already handles all of that.
Because of this modular concept, the Host can have many Remotes, and all of them live inside the Host. Think about a house that have many rooms.
Visual Example โ
One Host owns the shell; each finance module plugs in as its own Remote:
Host โ owns the shell of the app.
host/
โโโ src/
โโโ pages/ # login, logout, etc.
โโโ layouts/ # sidebar, navbar, etc.
โโโ ...etc/Remote โ just adds modules, for example a Budget module.
remote/
โโโ src/
โโโ pages/ # budget module
โโโ ...etc/Install โ
Both the Host and every Remote are standalone pnpm apps. They install the EJI libraries from a private git repo and pin every dependency through a pnpm workspace catalog โ a single pnpm-workspace.yaml that both apps share so their versions never drift. Your package.json then just points at the catalog with catalog:<group>.
Prerequisites โ
- pnpm (the catalog feature below needs a recent pnpm).
- A GitHub classic token โ the libraries live in the private
EJI-ICT/libsrepo, so the git URLs are token-authenticated. The snippets below use<GITHUB_CLASSIC_TOKEN>as a placeholder; replace it with your token.
1. pnpm-workspace.yaml โ
This is the single source of truth for versions. The internal catalog pulls the four EJI libraries from git; the other groups pin the dependencies those libraries expect (their peers).
yaml
shellEmulator: true
trustPolicy: no-downgrade
packages: []
catalogs:
# Internal EJI-ICT libraries (private git repo, token-authenticated)
internal:
esw-utils: git+https://<GITHUB_CLASSIC_TOKEN>@github.com/EJI-ICT/libs#path:/packages/esw-utils
mono-devextreme: git+https://<GITHUB_CLASSIC_TOKEN>@github.com/EJI-ICT/libs#path:/packages/mono-devextreme
mono-helper: git+https://<GITHUB_CLASSIC_TOKEN>@github.com/EJI-ICT/libs#path:/packages/mono-helper
mono-utils: git+https://<GITHUB_CLASSIC_TOKEN>@github.com/EJI-ICT/libs#path:/packages/mono-utils
# Build pipeline: Vite, bundler plugins, OData codegen
build:
'@odata2ts/http-client-api': ^0.6.3
'@odata2ts/odata-query-objects': ^0.28.1
'@odata2ts/odata-service': ^0.23.1
'@odata2ts/odata2ts': ^0.40.1
'@vitejs/plugin-vue': ^6.0.7
unocss: ^66.7.0
unplugin-auto-import: ^21.0.0
unplugin-vue-components: ^32.1.0
vite: 8.0.16
vite-plugin-mkcert: ^2.1.0
vite-plugin-vue-devtools: ^8.1.2
vite-plugin-vue-layouts: ^0.11.0
# Dev tooling: type-checking, env helpers, upgrades
dev:
'@iconify/json': ^2.2.483
'@tsconfig/node22': ^22.0.5
'@vue/tsconfig': ^0.9.1
dotenv: ^17.4.2
dotenv-cli: ^11.0.0
taze: ^19.14.1
typescript: ~6.0.3
vue-tsc: ^3.3.3
# Frontend runtime: shipped to the browser bundle
frontend:
'@unhead/vue': 3.1.3
'@vueuse/core': 14.3.0
'@vueuse/integrations': 14.3.0
devextreme: 25.1.6
devextreme-vue: 25.1.6
jwt-decode: ^4.0.0
notivue: ^2.4.5
pinia: 3.0.4
universal-cookie: ^8.1.2
vue: 3.5.24
vue-router: 5.0.4
yup: ^1.7.1
# Type definitions
types:
'@types/node': ^25.9.2
onlyBuiltDependencies:
- esbuildThe Host adds a couple of extras to its
frontend/buildcatalogs (@sentry/vue,@sentry/integrations,@sentry/vite-plugin) for error reporting. A Remote doesn't need them.
2. package.json โ
Reference the catalog with catalog:<group> โ pnpm resolves the version from pnpm-workspace.yaml, so you never repeat version numbers per app.
json
{
"dependencies": {
"mono-devextreme": "catalog:internal",
"@unhead/vue": "catalog:frontend",
"@vueuse/core": "catalog:frontend",
"@vueuse/integrations": "catalog:frontend",
"dotenv": "catalog:dev",
"jwt-decode": "catalog:frontend",
"notivue": "catalog:frontend",
"pinia": "catalog:frontend",
"universal-cookie": "catalog:frontend",
"vue": "catalog:frontend",
"vue-router": "catalog:frontend",
"yup": "catalog:frontend"
},
"devDependencies": {
"esw-utils": "catalog:internal",
"mono-helper": "catalog:internal",
"mono-utils": "catalog:internal",
"@iconify/json": "catalog:dev",
"@odata2ts/http-client-api": "catalog:build",
"@odata2ts/odata-query-objects": "catalog:build",
"@odata2ts/odata-service": "catalog:build",
"@odata2ts/odata2ts": "catalog:build",
"@tsconfig/node22": "catalog:dev",
"@types/node": "catalog:types",
"@vitejs/plugin-vue": "catalog:build",
"@vue/tsconfig": "catalog:dev",
"devextreme": "catalog:frontend",
"devextreme-vue": "catalog:frontend",
"dotenv-cli": "catalog:dev",
"taze": "catalog:dev",
"typescript": "catalog:dev",
"unocss": "catalog:build",
"unplugin-auto-import": "catalog:build",
"unplugin-vue-components": "catalog:build",
"vite": "catalog:build",
"vite-plugin-mkcert": "catalog:build",
"vite-plugin-vue-devtools": "catalog:build",
"vite-plugin-vue-layouts": "catalog:build",
"vue-tsc": "catalog:dev"
}
}3. Why these deps โ peer dependencies โ
The EJI libraries don't bundle their runtime dependencies; they declare them as peerDependencies. That means your app installs them once โ so there's a single copy of vue, vue-router, etc., and you control the versions (via the catalog above). The list above already covers them; here's the full picture so you know what each library expects:
| Library | Declares as peers (you must provide) |
|---|---|
mono-helper | (none) โ it bundles its own lit + flatpickr, so just install it. |
mono-utils | vue, vue-router, jwt-decode, @unhead/vue, dotenv, dotenv-cli, esw-utils, mono-devextreme |
esw-utils | vue, vue-router, yup, notivue, @odata2ts/odata-query-objects, @odata2ts/http-client-fetch, json-server, change-case, chokidar |
A few esw-utils peers are feature-specific โ add them only if you use that feature:
json-serverโ the local mock API for development.change-case,chokidar,@odata2ts/*โ OData type generation (see OData Types).
Install everything declared in package.json:
sh
pnpm iFor the UI components and theming, continue with Mono-UI โ Getting started and Theme.