# Vue Flow Custom Nodes Migration Guide ## 🎯 Problem Solved Custom nodes defined inline (using template strings or object definitions) **do not load in production** with Vue Flow. The solution is to use **separate .vue component files** that are properly imported. ## ✅ Production-Safe Approach: File-Based Custom Nodes ### 1. Create Separate .vue Files for Each Node Type Instead of defining nodes inline in `composables/processFlowNodes.js`, create individual `.vue` files: ``` components/process-flow/custom/ ├── StartNode.vue ├── FormNode.vue ├── EndNode.vue ├── ConditionalNode.vue ├── ScriptNode.vue ├── ApiNode.vue ├── NotificationNode.vue └── ... (other node types) ``` ### 2. Standard Vue Component Structure Each node component should follow this pattern: ```vue ``` ### 3. Import Components in Your Main File In `pages/process-builder/index.vue`: ```javascript // Import all custom node components import StartNode from "~/components/process-flow/custom/StartNode.vue" import FormNode from "~/components/process-flow/custom/FormNode.vue" import EndNode from "~/components/process-flow/custom/EndNode.vue" import ConditionalNode from "~/components/process-flow/custom/ConditionalNode.vue" import ScriptNode from "~/components/process-flow/custom/ScriptNode.vue" import ApiNode from "~/components/process-flow/custom/ApiNode.vue" import NotificationNode from "~/components/process-flow/custom/NotificationNode.vue" // ... import other nodes ``` ### 4. Create nodeTypes Object ```javascript import { markRaw } from 'vue' // Map node types to components (use markRaw to prevent reactivity issues) const nodeTypes = { 'start': markRaw(StartNode), 'form': markRaw(FormNode), 'end': markRaw(EndNode), 'conditional': markRaw(ConditionalNode), 'script': markRaw(ScriptNode), 'api': markRaw(ApiNode), 'notification': markRaw(NotificationNode), // ... other node types } ``` ### 5. Use nodeTypes in VueFlow Component ```vue ``` ## 🚫 What NOT to Use (Breaks in Production) ### ❌ Template Slots Approach ```vue ``` ### ❌ Inline Object Definitions ```javascript // This breaks in production const nodeTypes = { 'start': { props: ['id', 'data'], template: `
{{ data.label }}
` } } ``` ## 📋 Migration Checklist ### Current State Analysis - [ ] Review `composables/processFlowNodes.js` for all node type definitions - [ ] Identify unique node types used in your process builder - [ ] Note any complex computed properties or methods in existing nodes ### Migration Steps 1. [ ] Create individual `.vue` files for each node type in `components/process-flow/custom/` 2. [ ] Convert existing node logic from `processFlowNodes.js` to Vue component format 3. [ ] Import all node components in main process builder file 4. [ ] Create `nodeTypes` object mapping types to components with `markRaw` 5. [ ] Update VueFlow component to use `:node-types` prop instead of template slots 6. [ ] Remove old `processFlowNodes.js` file 7. [ ] Test all node types render correctly 8. [ ] Test in production environment ### Key Node Types to Migrate Based on your `processFlowNodes.js`, you have these node types: - `start` - Start nodes - `form` - Form nodes - `end` - End nodes - `conditional` - Conditional/gateway nodes - `script` - Script execution nodes - `api` - API call nodes - `notification` - Notification nodes - `subprocess` - Subprocess nodes - Various shape nodes (rectangle, circle, diamond, etc.) ## 🔧 Common Patterns for Migration ### Computed Properties Convert computed properties from options API to composition API: ```javascript // OLD (in processFlowNodes.js) computed: { nodeLabel() { return this.data?.label || 'Default' } } // NEW (in .vue component) const nodeLabel = computed(() => { return props.data?.label || 'Default' }) ``` ### Event Handlers ```javascript // OLD methods: { onClick() { this.$emit('node-click', this.id) } } // NEW const emit = defineEmits(['node-click']) const onClick = () => { emit('node-click', props.id) } ``` ### Complex Node Logic For nodes with complex logic (like ConditionalNode), maintain the same patterns but convert to composition API: ```vue ``` ## 🚀 Benefits of File-Based Approach 1. **Production Compatibility** - Works reliably in all environments 2. **Better Performance** - Proper component compilation and tree-shaking 3. **Developer Experience** - Full IDE support, syntax highlighting, linting 4. **Maintainability** - Separate files are easier to manage and debug 5. **Reusability** - Components can be imported and used elsewhere 6. **Scoped Styles** - No CSS conflicts between node types ## 🐛 Debugging Tips ### Error Handling Add error handling to catch Vue Flow issues: ```javascript const handleVueFlowError = (error) => { console.error('Vue Flow Error:', error) if (isErrorOfType(error, ErrorCode.MISSING_VIEWPORT_DIMENSIONS)) { console.error('Container needs explicit width/height') } } ``` ### Node ID Conflicts Ensure all node IDs are unique across your application to prevent rendering conflicts. ## 📁 File Structure After Migration ``` components/process-flow/custom/ ├── StartNode.vue ├── FormNode.vue ├── EndNode.vue ├── ConditionalNode.vue ├── ScriptNode.vue ├── ApiNode.vue ├── NotificationNode.vue ├── SubprocessNode.vue ├── RectangleShapeNode.vue ├── CircleShapeNode.vue ├── DiamondShapeNode.vue ├── TriangleShapeNode.vue ├── PentagonShapeNode.vue ├── HexagonShapeNode.vue └── OctagonShapeNode.vue pages/process-builder/ └── index.vue (updated to import and use file-based nodes) # Remove after migration: composables/processFlowNodes.js ❌ ``` --- ## 🎯 Ready to Migrate? When you're ready to start the migration, provide: 1. Your current `pages/process-builder/index.vue` file 2. Your current `composables/processFlowNodes.js` file 3. Any specific node types you want to prioritize The assistant will help you convert each node type to the production-safe file-based approach! 🚀