Customer Support Collaboration Hub
A hands-on migration tutorial for a mixed-code project based on the Vue + React ecosystem.
Overview
This is a hands-on migration tutorial that helps you implement full ecosystem enablement and finish a closed-loop controllable mixed-coding migration with VuReact in real-world business scenarios, using: Vue + Vue Router + Ant Design (React) + Zustand (React).
Playground
Before getting started, you can preview and experience the tutorial in advance via the playground and preview.
Video Demonstration
You can also quickly understand the entire migration process through the following video:
Prerequisites
- Node.js 19+
- Cloned the customer-support-hub repository and installed dependencies
Step 1: Prepare the Example and Configuration
1.1 Commands
cd customer-support-hub
npm install1.2 What You'll See
- Dependencies installed successfully, with
vr:watchandvr:buildexecutable in the project'spackage.json.
"scripts": {
"vr:watch": "vureact watch",
"vr:build": "vureact build"
}vureact.config.tsexists in the root directory, along with thesrc/folder.The routing configuration entry is declared as
src/router/index.tsinvureact.config.ts.
router: {
configFile: 'src/router/index.ts',
},1.3 Troubleshooting Failed Installations
npmcommand unavailable: Check Node/npm installation.- Installation failed: Prioritize resolving lock file conflicts and retry.
- Unresolved issues: Copy the error message and seek help from AI.
1.4 Pass Criteria
npm installcompletes without blocking errors.npm run vr:buildcan be executed in the root directory.
Step 2: Execute VuReact Compilation
2.1 Commands
npm run vr:buildOptional: Use watch mode for incremental migration.
npm run vr:watch2.2 What You'll See
- Console output showing compilation statistics (number of SFC/script/style processed).

- A
.vureact/react-appdirectory is generated, mirroring the structure of the Vue source code.

- After successful compilation, React entry style imports are automatically processed according to
vureact.config.tsconfiguration (completed by theonSuccesshook).
{
onSuccess: async () => {
/*
Inject missing styles/app.css import into main.tsx
*/
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const entryFile = path.resolve(__dirname, './.vureact/react-app/src/main.tsx');
const data = fs.readFileSync(entryFile, 'utf-8');
const newData = data.replace('index.css', 'styles/app.css');
fs.writeFileSync(entryFile, newData, 'utf-8');
};
}2.3 Troubleshooting Compilation Failures
- Network/NPM errors: Check internet connectivity.
- SFC syntax errors: Fix source Vue files before recompiling.
- Missing output directory: Confirm commands are executed in the project root and
vureact.config.tsexists.
2.4 Pass Criteria
- Output directory exists and contains React project files such as
src/main.tsxandsrc/router. - Re-executing
npm run vr:buildconsistently generates the output.
Step 3: Inspect the Output Routing
3.1 What You'll See
- The React output app entry
main.tsxis uniformly hosted byRouterProvider.
createRoot(document.getElementById('root')!).render(
<StrictMode>
<RouterInstance.RouterProvider />
</StrictMode>,
);- Route guards allow access to
meta.publicpages (e.g., login page); other pages redirect to login if no session exists.
// react-app/src/router/index.ts
router.beforeEach((to, _from, next) => {
if (to.meta.public) {
next();
return;
}
const session = appStore.getState().session;
if (!session.user) {
next({ name: 'login', query: { redirect: to.fullPath } });
return;
}
next();
});- Page routes (e.g., Dashboard/Tickets/Customers/Agents/Knowledge/SLA/Settings) are accessible.

3.2 Troubleshooting Routing Issues
- Blank page: Usually caused by
main.tsxstill directly rendering<App />. - Route component errors: Check if
router/indexexports androutesimports are correct. - Redirection after login: Verify session read/write logic (synchronization between
localStorageand store).
3.3 Pass Criteria
- Login page is accessible after launch; business routes switch normally after login with no global blank screen.
Step 4: Observe Vue + Zustand
In this section, we'll examine the usage of Zustand from the perspective of Vue source code.
4.1 What You'll See
- State is centralized in
src/store/useAppStore.ts, withappStorecreated usingzustand/vanilla
import { createStore } from 'zustand/vanilla';
// Core: Create store + actions
export const appStore = createStore<AppState>((set) => ({...}));- Key state fields to focus on:
session,ticketFilters,slaConfig,activities
{
session: { ... },
ticketFilters: { ... },
slaConfig: { ... },
activities: [],
}- Key actions to focus on:
login/logout,setTicketFilters,setSlaConfig,appendActivity
{
login: (user) => set((state) => ({ ... })),
setTicketFilters: (patch) => set((state) => ({ ... })),
appendActivity: (text) => set((state) => ({ ... }))
// ...
}- Route guards read
session.userfrom the store; unauthenticated users are redirected to login
// src/router/index.ts
import { appStore } from './store/useAppStore';
router.beforeEach((to, _from, next) => {
// ...
const session = appStore.getState().session;
// ...
});- Business pages trigger filtering/refresh via
appStore.subscribe(...)orgetState(), driving page data updates
// src/App.vue
appStore.subscribe((state) => {
userName.value = state.session.user?.name || 'Guest';
});4.2 Troubleshooting State Issues
- Redirection after login: Prioritize checking if
router.beforeEachcorrectly readssession.user - Filtering not working: Verify if the page subscribes to
ticketFiltersand ifsetTicketFiltersis called with refresh after clicking filters - Activity feed not updating: Check if the trigger chain calls
appendActivity
4.3 Pass Criteria
- You can clearly map:
session -> route guards,ticketFilters -> page list refresh, andappendActivity -> dynamic/activity feed display
Step 5: Observe Vue + Ant Design
In this section, we'll examine the usage of Ant Design from the perspective of Vue source code.
5.1 What You'll See
- Ticket processing main area:
AntTable+AntSelect+AntButton(table/filter/claim/escalate)
<!-- src/pages/TicketsList.vue -->
<AntTable
:columns="columns"
:data-source="rows"
:pagination="pagination"
row-key="id"
:loading="loading"
@change="onTableChange"
/>
...- Customer details:
AntDrawer(drawer) for information display and "quick ticket creation"
<!-- src/pages/Customers.vue -->
<AntDrawer :open="drawerOpen" width="560" title="Customer Details" @close="onCloseDrawer">
...
</AntDrawer>- Customer risk display:
AntDescriptions/AntTag/AntProgress(profile trends, risk scores, risk factor progress bars)
<!-- src/pages/Customers.vue -->
...
<AntProgress :percent="point.score" :stroke-color="point.color" :show-info="false" />- SLA dashboard:
AntRadioGroup + AntTable(switch filter results for "All/Risk/Overdue")
<!-- src/pages/SlaBoard.vue -->
<AntRadioGroup :value="riskFilter" @change="onFilterChange">
...
</AntRadioGroup>
...- Verification method: Locate component imports from
antdin the output or source code to quickly map to corresponding page areas
5.3 Troubleshooting UI Issues
- Table not displaying/incorrect columns: Prioritize checking if
columnsdataIndexmatchesrowsfields and ifrow-keyis stillid - Selector unresponsive: Verify if the bound
:valuefield and callbacks (e.g.,onActiveTicketChange) are correct - Drawer/form not working: Check if the drawer
openstate toggles correctly and if submission actions call mock APIs (e.g., ticket creation)
5.4 Pass Criteria
- You can complete key interactions in the page such as "filter/claim/escalate/create ticket", and observe changes in page data and state updates
Step 6: Launch the React Output
6.1 Commands
In the .vureact/react-app directory:
npm run dev6.2 What You'll See
- Vite dev server starts successfully (default local port).
- Browser opens to the login page.

- After login, enter the customer support collaboration main interface.

- Hot reload is available: Modify Vue source files and React output pages update synchronously.
In the customer-support-hub root directory:
npm run vr:watch6.3 Troubleshooting Launch Failures
- Missing dependencies: Install missing packages from the installation log and restart.
- TS errors: Prioritize checking route entries, runtime package imports, and path aliases.
- Vite errors: Verify compatibility with the current Node.js version.
6.4 Pass Criteria
- React output is accessible, supports hot reload, and launches without blocking errors.
Step 7: Page Acceptance (Business Closure)
Manually verify the following paths in the running page.
7.1 What You'll See
- Login and guards: Accessing business pages without login redirects to login; after login, redirect back to the target page.
- Ticket list and details: Filter/search tickets; view timeline and SLA snapshots after entering details page.

- Ticket action linkage: After performing claim, assign, escalate, or status update actions, corresponding records are added to the activity feed.

- SLA dashboard linkage: After ticket escalation or approaching deadline, dashboard risk status updates synchronously; SLA configuration updates take effect immediately.
- Customer page linkage: View customer risk scores, create new tickets via "quick ticket creation", and retrieve them in the ticket list.

- Knowledge base search: Filter articles by keywords or tags with normal pagination data.

7.2 Troubleshooting Business Linkage Issues
- Linkage not triggering: Check if mock API methods are called by the page (e.g.,
claimTicket/escalateTicket/updateTicketStatus). - Activity feed not updating: Verify if
appendActivityin the store is executed. - Abnormal search results: Check for conflicts between Fuse.js keyword fields and filter conditions.
7.3 Pass Criteria
- Complete end-to-end flow: "Ticket actions -> Activity feed/SLA -> Dashboard or dashboard".
- Complete end-to-end flow: "Customer ticket creation -> Ticket list retrieval -> Detail processing".
Step 8: Proximity Debugging (By Symptom)
8.1 Commands
# Recompile
npm run vr:build
# Restart output
cd .vureact/react-app && npm run devOr delete output and recompile:
rm -rf .vureact
npm run vr:build
cd .vureact/react-app && npm install && npm run dev8.2 What You'll See
- Most issues fall into categories: route entry, missing dependencies, source file syntax, type constraints, version incompatibility.
8.3 Troubleshooting Persistent Issues
- Blank route page: Review Step 3 routing integration checks first.
- Compilation failure: Go back to the error file, fix source code, and recompile.
- Type errors: Check if route/runtime package imports in generated output are correct.
- Watch mode not syncing: Confirm
npm run vr:watchis running in the root directory.
8.4 Pass Criteria
- Can locate and fix common blocking errors within 10 minutes.
Appendix A: Command Quick Reference
# Vue example directory
cd customer-support-hub
npm install
npm run vr:build
# React output directory
cd .vureact/react-app
npm install
npm run devAppendix B: Capability Mapping (This Case)
- Templates: Covers common directives, events, etc.
- Components:
defineProps/defineEmits/ slot - Scripts:
ref/computed/watch, etc. - UI Library: Full use of Ant Design for layout, tables, forms, etc.
- State: Zustand store for cross-page state management
- Routing:
createRouter/ guards / nested routes / dynamic routes - Styles:
scoped/ Sass syntax - Business: Ticket flow, SLA risk, knowledge base search, customer risk scoring
Appendix C: Troubleshooting Index
- Blank route page: First check Router Adaptation Guide
- Syntax coverage: See Capability Matrix
- Compilation warning handling: See Best Practices
- Issue feedback:
Appendix D: Continued Learning Navigation
After completing this tutorial, we recommend continuing with the following sequence:
- CLI Guide: Master usage of
build/watch, input scope, and engineering commands. - Configuration API: Systematically understand core configuration items like
input/exclude/output/router. - Compilation Conventions: Clarify compiler behavior boundaries and code conventions to reduce migration deviations.
- Best Practices: Establish a rollbackable, verifiable, and extensible migration process.
