Interactive Vue Complexity Estimator

How tangled is your Vue app?

Drop your stack into the estimator. We'll tell you exactly which deep-dive to read next.

ComplexityEstimator.vue
45
5200
Server-Side Rendering
Nuxt / custom SSR setup
60%
0%100%
Manageable

Your app is in good shape. Focus on establishing patterns before it grows.

0MANAGEABLE
45
components
60%
TypeScript
OFF
SSR
dependency graph
AppStoreRouterListCompFormCompDetailCompuseData()
recommended reads for your stacklow
Props & Injectionpattern 01
PROBLEM

Prop drilling six levels deep

You passed `user` as a prop from App.vue → Layout → Page → Section → Card → Avatar. Now the Avatar needs `user.permissions`. Everyone in between touches props they don't use.

BrokenComponent.vue
1// App.vue
2
5
6// Layout.vue — receives user, passes it down
7defineProps<{ user: User }>()← 🐛
8
9// Page.vue — same thing
10defineProps<{ user: User }>()← 🐛
11
12// Avatar.vue — finally uses it
13const props = defineProps<{ user: User }>()
14const canEdit = props.user.permissions.edit← 🐛
✕ [Vue warn]: Missing required prop: "user" on <Page>
✕ [Vue warn]: Extraneous non-props attributes (user) were passed to component
SOLUTION

provide / inject with typed symbols

Define the injection key once at the root. Any descendant — at any depth — injects it directly. Zero prop tunneling. Full TypeScript safety.

FixedComponent.vue
1// injectionKeys.ts
2import { InjectionKey } from 'vue'
3export const UserKey: InjectionKey =
4 Symbol('user')
5
6// App.vue — provide once at root
7import { provide } from 'vue'
8provide(UserKey, user)
9
10// Avatar.vue — inject anywhere
11import { inject } from 'vue'
12const user = inject(UserKey)!
13const canEdit = user.permissions.edit
Reactivity chain resolved. 0 warnings.
6 levels
before
0 levels
after
prop tunnel depth
provide/inject: The Pattern Mid-Level Vue Devs Skip
Props & Injection11 min read
Read the Deep Dive
Reactivitypattern 02
PROBLEM

The watcher that watches itself

A `watch` on `filters` calls `fetchData()`, which updates `results`, which triggers a side effect that mutates `filters`. Stack overflow at 11:43pm on a Friday deploy.

BrokenComponent.vue
1// ❌ circular watch chain
2const filters = reactive({ sort: 'asc', page: 1 })
3const results = ref([])
4
5watch(filters, async () => {← 🐛
6 results.value = await fetchData(filters)← 🐛
7})← 🐛
8
9// somewhere else in the component...
10watch(results, (data) => {← 🐛
11 if (data.length === 0) {← 🐛
12 filters.page = 1 // ← triggers first watch again← 🐛
13 }
14})
✕ [Vue warn]: Maximum recursive updates exceeded. You may have code that is mutating state inside a watch.
✕ RangeError: Maximum call stack size exceeded
SOLUTION

computed + explicit dependency tracking

Replace the circular watch chain with a computed that derives state deterministically. One direction. No cycles. The Vue reactivity graph can't loop on a DAG.

FixedComponent.vue
1// ✓ unidirectional data flow
2const filters = reactive({ sort: 'asc', page: 1 })
3
4const queryKey = computed(() =>
5 `${filters.sort}-${filters.page}`
6)
7
8const { data: results } = useQuery({
9 queryKey: [queryKey],
10 queryFn: () => fetchData(filters),
11})
12
13// page resets live in the action, not a watcher
14function setSort(s) { filters.sort = s; filters.page = 1 }
Reactivity chain resolved. 0 warnings.
∞ renders
before
1 per query
after
reactivity triggers
The watchEffect Trap: 4 Infinite Loops I Shipped to Production
Reactivity10 min read
Read the Deep Dive
Architecturepattern 03
PROBLEM

State scattered across 12 components

User auth state lives in App.vue. Cart state is in a Vuex module nobody understands. Form state is local. Every refactor touches 8 files. The tech lead wants to rewrite in React.

BrokenComponent.vue
1// state in 4 different places
2const user = ref(null) // App.vue← 🐛
3
4// store/cart.js (Vuex, no types)
5state: () => ({ items: [], total: 0 }),← 🐛
6mutations: { ADD_ITEM(state, item) {← 🐛
7 state.items.push(item) // no validation← 🐛
8}}
9
10// ProductCard.vue — needs both
11const store = useStore()← 🐛
12const canBuy = computed(() =>← 🐛
13 store.state.cart.total < user.value?.limit)← 🐛
✕ [Vuex] unknown mutation type: cart/ADD_ITEM
✕ [Vue warn]: Property "limit" was accessed during render but is not defined
SOLUTION

Domain composables + Pinia stores

Encapsulate each domain in a composable that owns its state, actions, and derived values. Pinia for cross-component persistence. Everything else stays local. Rewrite cancelled.

FixedComponent.vue
1// stores/cart.ts — typed Pinia store
2export const useCartStore = defineStore('cart', () => {
3 const items = ref([])
4 const total = computed(() =>
5 items.value.reduce((s, i) => s + i.price, 0))
6 function addItem(item: CartItem) {
7 if (!item.inStock) return // validation here
8 items.value.push(item)
9 }
10 return { items, total, addItem }
11})
12
13// ProductCard.vue — clean
14const cart = useCartStore()
Reactivity chain resolved. 0 warnings.
12 files
before
3 stores
after
state surface area
Composables as Architecture: How to Never Need a Rewrite
Architecture16 min read
Read the Deep Dive
14,200+
Monthly Readers
47
Deep-Dive Articles
3.2M
Lines of Vue Debugged
11pm
Avg. Read Time
Developers who've been there

Written at 11pm, for the devs debugging at 11pm

watchEffect
"I'd been staring at the same watchEffect loop for 3 hours. Found Reactive at 11:47pm, read the deep dive, fixed it by midnight. The code examples are exactly how I write code — not some sanitized tutorial version."
M
Marcus Webb
Senior Frontend Engineer · Veritas Health · Austin, TX
Migration
"We were 6 weeks into a Vuex → Pinia migration and completely lost. The architecture article gave us a migration playbook we actually used. Saved at least two weeks of argument in Slack."
P
Priya Nair
Tech Lead · Groww · Bengaluru, IN
Composables
"I picked Vue because Laravel Breeze told me to. A year later I had no idea what I was doing with composables. Reactive is the resource I wish existed when I started."
C
Callum Fraser
Solo Founder · Trackflow.io · Edinburgh, UK
SSR / Nuxt
"The SSR hydration article is the most technically honest piece of writing I've read about Nuxt. No hand-waving, just the actual edge cases with reproduction steps."
Y
Yuki Tanaka
Fullstack Developer · Monolith Studio · Tokyo, JP
The Reactivity Feed

New article drops when the bug is fixed

Not on a schedule. Not a newsletter. A feed that updates when a real Vue problem gets solved and documented. No fluff, no announcements.

No marketing. No re-engagement campaigns. Just Vue.