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>
5.9 KiB
5.9 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Organize Composition API Code by Logical Concern, Not Option Type | MEDIUM | Poor code organization in Composition API leads to spaghetti code worse than Options API | best-practice |
|
Organize Composition API Code by Logical Concern, Not Option Type
Impact: MEDIUM - The Composition API removes the "guard rails" of Options API that force code into data/methods/computed buckets. Without intentional organization, Composition API code can become more disorganized than Options API. Group related code together by feature or logical concern.
The key insight is that Composition API gives you flexibility - which requires discipline. Apply the same code organization principles you would use for any well-structured JavaScript code.
Task Checklist
- Group related state, computed, and methods together by feature
- Extract related logic into composables when it grows
- Don't scatter related code throughout the script section
- Use comments or regions to delineate logical sections in larger components
- Consider splitting large components into smaller ones or composables
Disorganized (Bad):
<script setup>
// Scattered code - hard to understand what relates to what
import { ref, computed, onMounted, watch } from 'vue'
const searchQuery = ref('')
const items = ref([])
const selectedItem = ref(null)
const isModalOpen = ref(false)
const sortOrder = ref('asc')
const filterCategory = ref('all')
const isLoading = ref(false)
const error = ref(null)
const filteredItems = computed(() => {
return items.value.filter(i => i.category === filterCategory.value)
})
function openModal() { isModalOpen.value = true }
const sortedItems = computed(() => {
return [...filteredItems.value].sort(/* ... */)
})
function closeModal() { isModalOpen.value = false }
watch(searchQuery, async (query) => { /* fetch */ })
function selectItem(item) { selectedItem.value = item }
const searchResults = computed(() => {
return items.value.filter(i => i.name.includes(searchQuery.value))
})
onMounted(() => { fetchItems() })
async function fetchItems() { /* ... */ }
</script>
Organized by Concern (Good):
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
// ============================================
// DATA FETCHING & STATE
// ============================================
const items = ref([])
const isLoading = ref(false)
const error = ref(null)
async function fetchItems() {
isLoading.value = true
try {
items.value = await api.getItems()
} catch (e) {
error.value = e
} finally {
isLoading.value = false
}
}
onMounted(() => fetchItems())
// ============================================
// SEARCH
// ============================================
const searchQuery = ref('')
const searchResults = computed(() =>
items.value.filter(i =>
i.name.toLowerCase().includes(searchQuery.value.toLowerCase())
)
)
watch(searchQuery, async (query) => {
if (query.length > 2) {
await fetchItems({ search: query })
}
})
// ============================================
// FILTERING & SORTING
// ============================================
const filterCategory = ref('all')
const sortOrder = ref('asc')
const filteredItems = computed(() =>
searchResults.value.filter(i =>
filterCategory.value === 'all' || i.category === filterCategory.value
)
)
const sortedItems = computed(() =>
[...filteredItems.value].sort((a, b) =>
sortOrder.value === 'asc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name)
)
)
// ============================================
// SELECTION & MODAL
// ============================================
const selectedItem = ref(null)
const isModalOpen = ref(false)
function selectItem(item) {
selectedItem.value = item
openModal()
}
function openModal() { isModalOpen.value = true }
function closeModal() {
isModalOpen.value = false
selectedItem.value = null
}
</script>
Best: Extract to Composables:
<script setup>
import { useItems } from '@/composables/useItems'
import { useSearch } from '@/composables/useSearch'
import { useModal } from '@/composables/useModal'
// Each composable encapsulates a logical concern
const { items, isLoading, error, fetchItems } = useItems()
const { searchQuery, searchResults } = useSearch(items)
const {
selectedItem,
isOpen: isModalOpen,
open: openModal,
close: closeModal
} = useModal()
function selectItem(item) {
selectedItem.value = item
openModal()
}
</script>
// composables/useItems.js
export function useItems() {
const items = ref([])
const isLoading = ref(false)
const error = ref(null)
async function fetchItems(params = {}) {
isLoading.value = true
try {
items.value = await api.getItems(params)
} catch (e) {
error.value = e
} finally {
isLoading.value = false
}
}
onMounted(() => fetchItems())
return { items, isLoading, error, fetchItems }
}
Signs Your Component Needs Refactoring
- Scrolling between related code - If you're jumping around to understand one feature
- 300+ lines in script setup - Consider extracting composables
- Multiple unrelated features - Each should be its own composable
- Similar patterns repeated - Extract to shared composable
When to Extract to Composables
// Extract when:
// - Logic is reused across components
// - A feature is self-contained (search, pagination, form handling)
// - Component is getting too large (>200 lines)
// - You want to test logic in isolation
// Keep inline when:
// - Logic is simple and component-specific
// - Extracting would add more complexity than it removes
// - The component is already small and focused