Enforce strict architectural boundaries between application folders in Vite.
This plugin prevents one app (e.g. Front) from importing code from
another app (e.g. Pro) at build time and dev time, not just via
linting.
If a boundary is violated, Vite errors immediately.
Lint rules are easy to bypass. Aliases hide real paths. Large multi-front apps rot over time.
This plugin makes architecture non-negotiable by enforcing rules directly in Vite's module resolution graph.
- ✅ Enforce boundaries between any number of apps
- ✅ Errors in dev AND build
- ✅ Alias-aware (uses Vite's resolver)
- ✅ Configurable allowlists
- ✅ Zero runtime cost
- ✅ Works with Vite 5 / 6 / 7
resources/js/Apps/
├── Front/
├── Pro/
└── Shared/Rules:
- ❌
Frontcannot import fromPro - ❌
Procannot import fromFront - ✅ Both can import from
Shared
npm install -D vite-plugin-app-boundariesor
pnpm add -D vite-plugin-app-boundariesimport { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { enforceAppBoundaries } from "vite-plugin-app-boundaries";
export default defineConfig({
plugins: [
enforceAppBoundaries({
root: "resources/js/Apps",
apps: {
Front: {
path: "Front",
allowImportsFrom: ["Shared"],
},
Pro: {
path: "Pro",
allowImportsFrom: ["Shared"],
},
Shared: {
path: "Shared",
},
},
}),
react(),
],
});// Apps/Front/pages/welcome.tsx
import Editor from "@/Apps/Pro/components/editorjs";⬇️
🚫 App boundary violation
Importer:
.../Apps/Front/pages/welcome.tsx
(app: Front)
Imported:
.../Apps/Pro/components/editorjs.tsx
(app: Pro)
Allowed imports for Front:
SharedVite stops immediately.
Root directory that contains all apps.
root: "resources/js/Apps"Each app has:
path: folder name underrootallowImportsFrom: optional list of app names it may import from
apps: {
Front: {
path: "Front",
allowImportsFrom: ["Shared"],
},
Admin: {
path: "Admin",
allowImportsFrom: ["Shared", "Pro"],
},
}Enable verbose logging to see exactly how Vite resolves imports.
enforceAppBoundaries({
debug: true,
...
});Useful when diagnosing aliases or unexpected resolution.
This plugin enforces boundaries at build time.
For editor errors, mirror the rules using ESLint.
npm install -D eslint-plugin-boundariesmodule.exports = {
plugins: ["boundaries"],
settings: {
"boundaries/include": ["resources/js/**/*"],
"boundaries/elements": [
{ type: "front", pattern: "resources/js/Apps/Front/**" },
{ type: "pro", pattern: "resources/js/Apps/Pro/**" },
{ type: "shared", pattern: "resources/js/Apps/Shared/**" },
],
},
rules: {
"boundaries/element-types": [
"error",
{
default: "disallow",
rules: [
{ from: "front", allow: ["shared"] },
{ from: "pro", allow: ["shared"] },
{ from: "shared", allow: ["shared"] },
],
},
],
},
};- ❌ It does not replace ESLint
- ❌ It does not rewrite imports
- ❌ It does not enforce runtime isolation
Recommended setup:
- This plugin → build-time enforcement
- ESLint boundaries rules → editor feedback
MIT