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-boundaries
or
pnpm add -D vite-plugin-app-boundaries
import { 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: Shared
Vite 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-boundaries
module.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