Vue 3 frontend framework for building specialized back-office applications on VirtoCommerce Platform.
vc-shell is a monorepo containing the core UI framework, CLI tools, shared configs, and reference applications for VirtoCommerce back-office development. It provides a complete Vue 3 design system, a blade-based navigation paradigm, and a dynamic module system for building extensible admin applications.
- Blade Navigation — stacked panel navigation with
useBlade()composable for opening, closing, and communicating between blades - Component Library — Atomic Design hierarchy (atoms, molecules, organisms) with Tailwind CSS styling
- Dynamic Module System — runtime-loaded Vue plugins with semver compatibility, extension points, and Module Federation remotes
- VcDataTable — compositional table with declarative
<VcColumn>API, virtual scroll, column switching, global filters, inline editing, row grouping, drag-and-drop reorder, and state persistence inlocalStorageor the URL query - VcScheduler — calendar organism for date-bound periods with a Month grid and Day/Week timeline views, event lanes, and drag-to-edit
- Keyboard Shortcuts — declarative
hotkeybuilder on toolbar items, built-in blade shortcuts, and OS-aware tooltips (Cmd on macOS, Ctrl elsewhere) - Accessibility — WCAG 2.2 A/AA axe-core audit over every Storybook story, keyboard-operable navigation, dashboard, and menus
- Rich Text Editor — Tiptap-based editor with tables, images, links, and markdown support
- Dashboard & Widgets — grid-based dashboard with GridStack, customizable widget system, keyboard-driven widget rearrangement
- Responsive Design — mobile-first with dedicated mobile component variants
- i18n — built-in internationalization via vue-i18n
- Core Composables — reusable logic for API clients, assets, notifications, settings, permissions, and more
- Overview
- Tech Stack
- Monorepo Structure
- Getting Started
- Development
- Contributing
- Architecture
- Component Library
- Documentation
- License
| Layer | Technology |
|---|---|
| Framework | Vue 3 (Composition API, <script setup>) |
| Language | TypeScript (strict mode) |
| Build | Vite 6 |
| Styling | Tailwind CSS 3 (tw- prefix) + SCSS custom properties |
| Package Manager | Yarn 4 Berry (workspaces) |
| Testing | Vitest 3 + Vue Test Utils |
| Storybook | Storybook 10 |
| Linting | ESLint 9 + Prettier + Stylelint |
| Accessibility | axe-core (WCAG 2.2 A/AA) |
| Charts | Unovis |
| Forms | VeeValidate |
| Editor | Tiptap 3 |
| Dashboard Grid | GridStack |
| Drag & Drop | SortableJS |
| i18n | vue-i18n 11 |
vc-shell/
├── framework/ # @vc-shell/framework — main UI library
│ ├── core/ # API clients, composables, plugins, services
│ │ ├── api/ # Generated API clients
│ │ ├── blade-navigation/ # Blade stack state machine and registry
│ │ ├── composables/ # Composables (useBlade, useAsync, etc.)
│ │ ├── interceptors/ # Fetch interceptors (auth, errors)
│ │ ├── notifications/ # Notification contracts and store
│ │ ├── plugins/ # Modularity, extensions, permissions, i18n, AI agent
│ │ └── services/ # Menu, Dashboard, Toolbar, GlobalSearch, Settings
│ ├── ui/ # Vue components (Atomic Design)
│ │ └── components/
│ │ ├── atoms/ # Base components (Button, Badge, Icon...)
│ │ ├── molecules/ # Form & interactive components (Input, Select, Editor...)
│ │ └── organisms/ # Complex components (Table, Blade, Scheduler, Gallery...)
│ ├── shell/ # App chrome: sidebar, auth, dashboard, settings
│ ├── modules/ # Built-in modules (assets, assets-manager)
│ └── assets/styles/ # SCSS theme & CSS custom properties
│
├── cli/ # CLI tools
│ ├── api-client/ # @vc-shell/api-client-generator
│ ├── create-vc-app/ # @vc-shell/create-vc-app — project scaffolder
│ ├── docs-sync/ # @vc-shell/docs-sync — publishes *.docs.md to vc-docs (internal)
│ ├── migrate/ # @vc-shell/migrate — migration tool
│ └── vc-app-skill/ # @vc-shell/vc-app-skill — AI-assisted app generation
│
├── configs/ # Shared configurations
│ ├── ts-config/ # @vc-shell/ts-config
│ └── vite-config/ # @vc-shell/config-generator
│
├── packages/ # Module Federation packages
│ ├── mf-config/ # @vc-shell/mf-config
│ ├── mf-host/ # @vc-shell/mf-host
│ └── mf-module/ # @vc-shell/mf-module
│
├── apps/ # Apps for local framework development & debugging
│ └── ... # Place vc-shell apps here (see "Local Development via portal: Protocol")
│
├── migration/ # Per-topic v1 → v2 migration guides
├── scripts/ # Repo automation (app linking, release, a11y audit, layer checks)
│
└── .storybook/ # Storybook configuration
- Node.js >= 22
- Yarn 4.x (Corepack:
corepack enable)
There are two official workflows for creating vc-shell applications:
- CLI scaffolder (
@vc-shell/create-vc-app) — deterministic project bootstrap from templates - AI skill (
@vc-shell/vc-app-skill) — intent-driven app and module generation in AI coding tools
Create a new project interactively:
npx @vc-shell/create-vc-app my-appOr use non-interactive flags:
npx @vc-shell/create-vc-app my-app --type standalone --module-name "Products" --dashboard --mocksAdd a module to an existing app:
npx @vc-shell/create-vc-app add-module ordersSee full options and project types in cli/create-vc-app/README.md.
Install skill runtime:
# Claude Code / Cursor / GitHub Copilot (default runtime)
npx @vc-shell/vc-app-skill@latest install
# Other runtimes
npx @vc-shell/vc-app-skill@latest install --runtime codex
npx @vc-shell/vc-app-skill@latest install --runtime opencode
npx @vc-shell/vc-app-skill@latest install --runtime geminiRestart your AI tool session, then use slash commands in your app workspace:
/vc-app create # Scaffold a new app
/vc-app connect # Connect to a platform API and generate clients
/vc-app add-module orders # Add a module to the current app
/vc-app generate # Generate blades from intent
/vc-app design # Plan the UI before generating
/vc-app promote orders # Promote a local module to a package
/vc-app migrate # Migrate an app to a newer framework version
See full command reference in cli/vc-app-skill/README.md.
# Clone the repository
git clone https://github.com/VirtoCommerce/vc-shell.git
cd vc-shell
# Install dependencies (also sets up Husky git hooks)
yarn install
# Build all packages
yarn buildyarn build # Build all publishable packages
yarn build:framework # Build only @vc-shell/framework (hidden source maps)
yarn build:framework:debug # Build framework with full source maps (browser auto-loads)
yarn build:analyze # Build with bundle analyzer
yarn build:cli:config # Build @vc-shell/config-generator
yarn build:cli:api-client # Build @vc-shell/api-client-generator
yarn build:cli:create-vc-app # Build @vc-shell/create-vc-app
yarn build:storybook # Production Storybook build to storybook-static/
yarn build:storybook:compress # Pre-compress the Storybook build for static hostingyarn dev:storybook # Storybook dev server at :6006yarn test # Run tests (single run, CI-friendly)
yarn test:watch # Run tests in watch mode (interactive)
yarn test:unit # Run unit tests against framework/vitest.config
yarn test:coverage # Tests with coverage report
yarn test:storybook # Run Storybook interaction tests
yarn test:snapshot:update # Update Storybook snapshots
yarn test:a11y # axe-core WCAG 2.2 A/AA audit over a running Storybooktest:a11y drives a real Chromium against an already-running Storybook — start yarn dev:storybook
first, or point it at another instance with SB_BASE=http://host:port yarn test:a11y.
yarn lint # ESLint with --fix (dev)
yarn lint:check # ESLint verification (CI)
yarn format # Prettier --write (dev)
yarn format:check # Prettier verification (CI)
yarn stylelint # Stylelint --fix (dev)
yarn stylelint:check # Stylelint verification (CI)
yarn typecheck # Framework type check
yarn check # Umbrella: all verifications (lint + format + stylelint + typecheck + locales + circular + layers)yarn check:locales # Validate locale files
yarn check:circular # Detect circular dependencies (madge)
yarn check:layers # Enforce layer dependency directionGenerate TypeScript API clients from VirtoCommerce Platform modules:
yarn generate:api-client*.docs.md files co-located with the source are the source of truth for the public docs site.
CI syncs them on framework releases; run them locally to validate before pushing:
yarn docs:lint # Validate *.docs.md template compliance
yarn docs:sync # Sync docs to ../vc-docs (sibling checkout required)
yarn docs:screenshot # Capture Storybook screenshots for the docsSee RELEASING.md for the release process.
yarn release:dry # Dry run (preview changes)
yarn publish:packages # Publish managed packages (used by CI)
yarn generate:changelogs # Seed per-package changelogsyarn clean # Remove all node_modules + dist directories
yarn changed # List commits since last release tag
yarn diff # Diff stats since last release tag
yarn setup:apps # Link apps/* against this repo via portal: (see below)
yarn unsetup:apps # Roll back portal: linkingEvery push to a PR in this repository automatically publishes preview versions of all managed packages to npm with a pr-<N> dist-tag. The preview workflow comments on the PR with install instructions.
Install a PR preview in a consuming project:
npm install @vc-shell/framework@pr-<N>See CONTRIBUTING.md — Testing PR Previews for details, including the fork-PR caveat and exact-commit install pattern.
This repository supports one local-linking approach: Yarn portal:.
If your app lives outside this monorepo and you want to debug against a local build of @vc-shell/framework without moving the app.
Quick setup — drop your app into apps/<name>/ (this directory is gitignored and not a Yarn workspace) and run:
yarn setup:appsThe script rewrites every @vc-shell/* dependency in the app's package.json to a portal: path pointing at the matching package in this repository, enables preserveSymlinks in app tsconfig and Vite config, stores a rollback snapshot at .vc-shell/setup-apps-backup.json, and runs yarn install inside the app directory. After setup, start the app from its own directory (cd apps/<name> && yarn dev).
To rollback app coupling and restore original files:
yarn unsetup:appsManual setup (same flow in full detail):
-
Build framework locally in the vc-shell clone:
yarn build:framework
The
portal:protocol symlinks to the package directory — it does not build on demand. Re-runyarn build:frameworkafter each framework change (no watch mode yet). -
Replace the
@vc-shell/*entries in your app'spackage.jsonwith absoluteportal:paths to the corresponding packages in this repository:{ "dependencies": { "@vc-shell/framework": "portal:/absolute/path/to/vc-shell/framework", "@vc-shell/config-generator": "portal:/absolute/path/to/vc-shell/configs/vite-config", "@vc-shell/api-client-generator": "portal:/absolute/path/to/vc-shell/cli/api-client" } }Include every
@vc-shell/*package the app actually imports — portal entries are not auto-discovered like workspace deps. -
Enable preserveSymlinks on the app side so the app's bundler and TypeScript follow the portal symlink back to the real package on disk. Skipping this creates two copies of Vue (one through the symlink, one through the app's own
node_modules), breaking reactivity with warnings like "Vue has already been registered".If you used
yarn setup:apps, this step is applied automatically.In the app's
tsconfig.json:{ "compilerOptions": { "preserveSymlinks": true } }In the app's Vite config:
export default defineConfig({ resolve: { preserveSymlinks: true, }, });
-
Match peer-dependency versions. The portal-linked framework brings its own
node_modules/; if the app has a differentvueorvue-routerversion, you still end up with dual instances. Verify with:# Inside the app yarn why vue # Inside the vc-shell clone yarn why vue
Both commands should report the same version. If they diverge, bump the app's
package.jsonto match the vc-shell framework peer range. -
Install and run the app as usual:
yarn install yarn dev # or whatever the app's dev script is called
- "Vue has already been registered" / lost reactivity —
preserveSymlinksis not enabled on either Vite or TypeScript. Check both configs. - Changes in
framework/not reflected in the app —portal:doesn't trigger rebuilds. Runyarn build:frameworkin the vc-shell clone after edits, then restart the app's dev server (Vite HMR may not pick up changes to symlinkeddist/). - Type errors after rebuild — stale
.tsbuildinfoordist/remnants. Clean vc-shell withyarn clean(and rebuild) before retrying. - Yarn refuses to install with lockfile conflicts — the app's
yarn.lockmay reference npm-registry versions of@vc-shell/*. Delete the app'syarn.lockand re-runyarn installso Yarn re-resolves through portal entries.
The framework build always generates .map files so source maps are available when you need them:
| Build command | Source maps | Browser auto-loads? |
|---|---|---|
yarn build:framework |
Hidden (.map files generated, no sourceMappingURL in bundle) |
No |
yarn build:framework:debug |
Full (.map files + sourceMappingURL comment) |
Yes |
For local debugging, use yarn build:framework:debug — Chrome DevTools will automatically load source maps and show original TypeScript/Vue sources.
For production builds, .map files are still generated (hidden mode) but not referenced from the bundle. To use them, open Chrome DevTools → Sources tab, right-click the JS file → "Add source map...", and point to the .map file.
See CONTRIBUTING.md for development setup, workflow, and PR requirements.
vc-shell follows a blade-first modular architecture:
- Blade Navigation — stacked panel UX with context-aware navigation and blade-to-blade messaging
- Module Runtime — modules are Vue plugins that register blades, locales, and notification contracts
- Extension Points — cross-module composition via named slots and registration APIs
For implementation details, patterns, and code examples, see:
The framework follows Atomic Design methodology:
VcBadge VcBanner VcButton VcButtonGroup VcCard VcCol VcContainer VcEnvironmentBanner VcHint VcIcon VcImage VcLabel VcLink VcLoading VcProgress VcRow VcScrollableContainer VcSkeleton VcStatus VcStatusIcon VcTooltip VcVideo VcWidget
VcAccordion VcBreadcrumbs VcCheckbox VcCheckboxGroup VcColorInput VcDatePicker VcDropdown VcEditor VcField VcFileUpload VcForm VcImageTile VcInput VcInputCurrency VcInputDropdown VcInputGroup VcLanguageSelector VcMenu VcMultivalue VcPagination VcPopover VcRadioButton VcRadioGroup VcRating VcSelect VcSlider VcSwitch VcTextarea VcToast
VcApp VcAuthLayout VcBlade VcDataTable (with VcColumn) VcDynamicProperty VcGallery VcImageUpload VcPopup VcScheduler VcSidebar
VcTable is the legacy-API adapter over VcDataTable, kept for backwards compatibility.
Explore all components interactively: Storybook
| Resource | Description |
|---|---|
| Storybook | Interactive component explorer |
| ARCHITECTURE.md | Architecture guide and patterns |
| CONTRIBUTING.md | Development setup, workflow, PR requirements |
| create-vc-app README | Scaffolder usage and flags |
| vc-app-skill README | AI skill commands for app/module generation |
| ACCESSIBILITY.md | Accessibility standards and known exceptions |
| Storybook README | Story conventions and the story standard |
| docs-sync README | How *.docs.md is transformed and published |
| WHATS_NEW.md | v2.0.0 feature highlights |
| MIGRATION_GUIDE.md | Migration from v1 to v2 |
| migration/ | Per-topic v1 → v2 migration guides |
| RELEASING.md | Release process documentation |
| CHANGELOG.md | Full changelog |
Copyright (c) Virto Solutions LTD. Licensed under the Virto Commerce Open Software License.