Guides

Migration Guide

Guide for migrating from older versions of Nuxt Crouton

This guide helps you migrate your Nuxt Crouton projects from older versions to the latest release.

v1.x → v2.0

Version 2.0 introduced significant changes to improve performance and developer experience.

Breaking Changes Overview

  1. send() method removed
  2. ✅ Global state management removed
  3. ✅ Button component API updated
  4. ✅ Cache invalidation improved

Breaking Change 1: send() Removed

What Changed

The send() method from useCrouton() has been removed and replaced with two new approaches:

  • useCroutonMutate() - For quick, one-off mutations
  • useCollectionMutation() - For optimized mutations in forms

Before (v1.x)

<script setup lang="ts">
const { send } = useCrouton()

const handleCreate = async () => {
  await send('create', 'shopProducts', {
    name: 'New Product',
    price: 29.99
  })
}

const handleUpdate = async (id: string) => {
  await send('update', 'shopProducts', {
    id,
    name: 'Updated Name'
  })
}

const handleDelete = async (ids: string[]) => {
  await send('delete', 'shopProducts', ids)
}
</script>

After v2.0 - Option 1: useCroutonMutate (Quick)

For quick actions, toggle buttons, and utility functions:

<script setup lang="ts">
const { mutate } = useCroutonMutate()

const handleCreate = async () => {
  await mutate('create', 'shopProducts', {
    name: 'New Product',
    price: 29.99
  })
}

const handleUpdate = async (id: string) => {
  await mutate('update', 'shopProducts', {
    id,
    name: 'Updated Name'
  })
}

const handleDelete = async (ids: string[]) => {
  await mutate('delete', 'shopProducts', ids)
}
</script>

After v2.0 - Option 2: useCollectionMutation (Optimized)

For forms and repeated operations on the same collection:

<script setup lang="ts">
const { create, update, deleteItems } = useCollectionMutation('shopProducts')

const handleCreate = async () => {
  await create({
    name: 'New Product',
    price: 29.99
  })
}

const handleUpdate = async (id: string, data: any) => {
  await update(id, data)
}

const handleDelete = async (ids: string[]) => {
  await deleteItems(ids)
}
</script>

When to Use Which?

Use CaseUse This
Toggle buttonuseCroutonMutate()
Quick add/removeuseCroutonMutate()
Utility functionuseCroutonMutate()
Generated formsuseCollectionMutation()
Multi-step wizarduseCollectionMutation()
Bulk operationsuseCollectionMutation()

Breaking Change 2: Global State Removed

What Changed

The global reactive collections state (useCollections()) has been removed in favor of useCollectionQuery() with proper caching.

Before (v1.x)

<script setup lang="ts">
const { shopProducts } = useCollections()

// Manual fetch
const { data } = await useFetch('/api/products')
shopProducts.value = data.value

// Manual updates
watch(shopProducts, () => {
  // React to changes
})
</script>

<template>
  <div v-for="product in shopProducts" :key="product.id">
    {{ product.name }}
  </div>
</template>

After v2.0

Query Examples: For complete useCollectionQuery patterns including filters, pagination, and sorting, see Querying Data.
<script setup lang="ts">
// Automatic fetching and caching
const { items, pending, refresh } = await useCollectionQuery('shopProducts')

// Automatic refetch after mutations
const { create } = useCollectionMutation('shopProducts')
await create({ name: 'New Product' })
// → items automatically updates
</script>

<template>
  <div v-if="pending">Loading...</div>
  <div v-else>
    <div v-for="product in items" :key="product.id">
      {{ product.name }}
    </div>
  </div>
</template>

Benefits

  • ✅ Automatic cache management
  • ✅ Automatic refetching after mutations
  • ✅ Loading and error states built-in
  • ✅ No manual state synchronization

Breaking Change 3: Button Component Updated

What Changed

CroutonButton no longer accepts a @submit handler. Form submission is now handled by the UForm component.

Before (v1.x)

<template>
  <UForm :state="state" :schema="schema">
    <UFormField label="Name" name="name">
      <UInput v-model="state.name" />
    </UFormField>

    <CroutonButton
      :action="action"
      :collection="collection"
      @submit="send(action, collection, state)"
    />
  </UForm>
</template>

<script setup lang="ts">
const { send } = useCrouton()
const state = ref({ name: '' })
</script>

After v2.0

<template>
  <UForm
    :state="state"
    :schema="schema"
    @submit="handleSubmit"
  >
    <UFormField label="Name" name="name">
      <UInput v-model="state.name" />
    </UFormField>

    <CroutonButton
      :action="action"
      :collection="collection"
      :loading="loading"
      type="submit"
    />
  </UForm>
</template>

<script setup lang="ts">
const props = defineProps<{
  action: 'create' | 'update' | 'delete'
  collection: string
}>()

const { create, update, deleteItems } = useCollectionMutation(props.collection)
const state = ref({ name: '' })

const handleSubmit = async () => {
  if (props.action === 'create') {
    await create(state.value)
  } else if (props.action === 'update') {
    await update(state.value.id, state.value)
  } else if (props.action === 'delete') {
    await deleteItems(props.items)
  }
  close()
}
</script>

Migration Steps

Step 1: Update Dependencies

# Update to latest version
pnpm update @friendlyinternet/nuxt-crouton
pnpm update @friendlyinternet/nuxt-crouton-collection-generator
pnpm update @friendlyinternet/nuxt-crouton-i18n  # If using i18n

Step 2: Backup Generated Code

# Create backup of your customizations
cp -r layers layers.backup

Step 3: Update Generated Forms

Option A: Regenerate (Recommended for standard forms)

# Regenerate all collections
npx crouton-generate config ./crouton.config.js --force

Then restore any customizations from layers.backup/.

Option B: Manual Update (If heavily customized)

Update each Form.vue manually:

  1. Replace useCrouton().send() with useCollectionMutation()
  2. Add handleSubmit function
  3. Update CroutonButton props

See Breaking Change 1 and Breaking Change 3 for examples.

Step 4: Update Custom Code

Find and replace all instances of send():

# Find all usages
grep -r "const.*send.*=.*useCrouton" layers/

# Replace with useCroutonMutate or useCollectionMutation

Quick actions:

// Before
const { send } = useCrouton()
await send('update', 'products', data)

// After
const { mutate } = useCroutonMutate()
await mutate('update', 'products', data)

Forms:

// Before
const { send } = useCrouton()
await send('create', 'products', data)

// After
const { create } = useCollectionMutation('products')
await create(data)

Step 5: Update Global State Usage

Replace useCollections() with useCollectionQuery():

<!-- Before -->
<script setup>
const { shopProducts } = useCollections()
</script>

<!-- After -->
<script setup>
const { items: shopProducts } = await useCollectionQuery('shopProducts')
</script>

See Querying Data for advanced query patterns.

Step 6: Test Thoroughly

  1. Test CRUD operations:
    • Create new items
    • Update existing items
    • Delete items
    • Verify data refreshes automatically
  2. Test forms:
    • Open create form
    • Open edit form
    • Submit forms
    • Check validation
  3. Test caching:
    • Verify data loads from cache
    • Verify cache invalidates after mutations
    • Check multiple views update together

Step 7: Clean Up

# Remove backup if everything works
rm -rf layers.backup

# Clear caches
rm -rf .nuxt node_modules/.cache

# Restart dev server
pnpm dev

Common Migration Issues

Issue: "send is not a function"

Cause: Using old form with new core library

Fix: Regenerate form or manually update (see Step 3)

Issue: Data not refreshing

Cause: Old cache invalidation logic

Fix: Ensure using useCollectionMutation() which handles invalidation automatically

Issue: Type errors

Cause: Type definitions changed

Fix:

rm -rf .nuxt
npx nuxt prepare
# Restart TS server in VS Code

Issue: Forms not submitting

Cause: Missing @submit handler on UForm

Fix: Add @submit="handleSubmit" to UForm component


Need Help?

If you encounter issues during migration:

  1. Check GitHub Issues: github.com/pmcp/nuxt-crouton/issues
  2. Search Discussions: github.com/pmcp/nuxt-crouton/discussions
  3. Create an Issue: Include:
    • Version you're migrating from
    • Version you're migrating to
    • Error messages
    • Code samples