Files
agent-skills/skills/vue-best-practices/reference/multiple-app-instances.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

3.8 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
Use Multiple App Instances for Partial Page Control MEDIUM Mounting single app to entire page when only controlling parts wastes resources and complicates SSR efficiency
vue3
createApp
mount
ssr
progressive-enhancement
architecture

Use Multiple App Instances for Partial Page Control

Impact: MEDIUM - When Vue only controls specific parts of a page (common with server-rendered HTML or progressive enhancement), mounting a single large app instance to the entire page is inefficient and can complicate server-side rendering integration.

Vue's createApp API explicitly supports multiple application instances on the same page. Each instance has its own isolated scope for configuration and global assets, making this pattern safe and recommended.

Task Checklist

  • Assess whether Vue controls the entire page or just specific parts
  • For partial control, create separate app instances for each Vue-managed section
  • Each instance can have its own plugins, components, and configuration
  • Consider shared state via external stores if instances need to communicate

Incorrect:

// Server-rendered page with Vue only needed for a few interactive widgets
// WRONG: Mounting to entire page

// index.html (server-rendered)
// <body id="app">
//   <header>...</header>        <!-- static -->
//   <nav>...</nav>              <!-- static -->
//   <div class="widget-1">...</div>  <!-- needs Vue -->
//   <main>...</main>            <!-- static -->
//   <div class="widget-2">...</div>  <!-- needs Vue -->
//   <footer>...</footer>        <!-- static -->
// </body>

import { createApp } from 'vue'
import BigApp from './BigApp.vue'

// WRONG: Vue now controls entire page, including static content
createApp(BigApp).mount('#app')

Correct:

// CORRECT: Mount separate instances to specific elements

import { createApp } from 'vue'
import SearchWidget from './widgets/SearchWidget.vue'
import CartWidget from './widgets/CartWidget.vue'
import { createPinia } from 'pinia'

// Shared store for cross-widget state
const pinia = createPinia()

// Widget 1: Search functionality
const searchApp = createApp(SearchWidget)
searchApp.use(pinia)
searchApp.mount('.widget-search')

// Widget 2: Shopping cart
const cartApp = createApp(CartWidget)
cartApp.use(pinia)  // Same Pinia instance = shared state
cartApp.mount('.widget-cart')

// Rest of page remains server-rendered static HTML

Benefits of Multiple Instances

// 1. Isolated configuration per section
const adminApp = createApp(AdminPanel)
adminApp.config.errorHandler = adminErrorHandler
adminApp.use(adminOnlyPlugin)
adminApp.mount('#admin-panel')

const publicApp = createApp(PublicWidget)
publicApp.config.errorHandler = publicErrorHandler
// Different plugins, components, configuration
publicApp.mount('#public-widget')

// 2. Independent lifecycle
// Can unmount/remount sections independently
const app1 = createApp(Widget1).mount('#widget-1')
const app2 = createApp(Widget2).mount('#widget-2')

// Later, unmount just one widget
// app1.$destroy() in Vue 2, use app.unmount() for the app instance in Vue 3

Shared State Between Instances

// Option 1: Shared Pinia store
const pinia = createPinia()

createApp(App1).use(pinia).mount('#app1')
createApp(App2).use(pinia).mount('#app2')
// Both apps share the same Pinia stores

// Option 2: Shared reactive state module
// sharedState.js
import { reactive } from 'vue'
export const sharedState = reactive({
  user: null,
  cart: []
})

// Both apps import and use sharedState directly

Reference