Types & Configuration
Nuxt Crouton provides comprehensive TypeScript types for type-safe collection management, UI configuration, and data operations. This reference documents all core types, interfaces, and configuration patterns.
Core Configuration Types
CollectionConfig
The master configuration interface for registering collections in app.config.ts.
interface CollectionConfig {
// Basic Collection Info
name?: string
layer?: string
componentName?: string
apiPath?: string
// Pagination Settings
defaultPagination?: {
currentPage: number
pageSize: number
sortBy: string
sortDirection: 'asc' | 'desc'
}
// Relationship Declarations
references?: Record<string, string>
// Custom Component Mapping
dependentFieldComponents?: Record<string, string>
// Extensible for custom properties
[key: string]: any
}
Property Details
| Property | Type | Description |
|---|---|---|
name | string | Collection name (usually auto-set by generator) |
layer | string | Nuxt layer this collection belongs to |
componentName | string | Name of the form component (e.g., 'ShopProductsForm') |
apiPath | string | API endpoint path (defaults to collection name) |
defaultPagination | object | Default pagination settings for this collection |
references | Record<string, string> | Field-to-collection mappings for automatic cache refresh |
dependentFieldComponents | Record<string, string> | Custom component mappings for dependent fields |
Basic Usage
// app.config.ts
export default defineAppConfig({
croutonCollections: {
shopProducts: {
name: 'shopProducts',
layer: 'shop',
componentName: 'ShopProductsForm',
apiPath: 'products',
defaultPagination: {
currentPage: 1,
pageSize: 25,
sortBy: 'name',
sortDirection: 'asc'
}
}
}
})
With References (Cache Invalidation)
When a collection has fields that reference other collections, declare them using references. This enables automatic cache refresh when related items are updated.
// app.config.ts
export default defineAppConfig({
croutonCollections: {
bookingsEvents: {
name: 'bookingsEvents',
layer: 'bookings',
componentName: 'BookingsEventsForm',
references: {
location: 'bookingsLocations', // 'location' field references 'bookingsLocations'
host: 'users', // 'host' field references 'users'
category: 'bookingsCategories' // 'category' field references 'bookingsCategories'
}
}
}
})
How references work:
- When you update an event with
{ location: 'location-123' } - Crouton invalidates cache for both:
collection:bookingsEvents:*(the event collection)collection:bookingsLocations:*(the referenced location collection)
- Any UI displaying locations automatically refreshes to show updated data
- This keeps CardMini displays in sync across the application
With Custom Dependent Fields
For complex field relationships, map field names to custom components:
// app.config.ts
export default defineAppConfig({
croutonCollections: {
bookingsEvents: {
name: 'bookingsEvents',
layer: 'bookings',
componentName: 'BookingsEventsForm',
dependentFieldComponents: {
slots: 'SlotSelect', // Use SlotSelect component for 'slots' field
recurringPattern: 'RecurringPatternEditor' // Custom editor for recurring events
}
}
}
})
The FormDependentFieldLoader component uses this mapping to dynamically load the correct component for each field.
Custom Properties
You can extend CollectionConfig with any custom properties your application needs:
export default defineAppConfig({
croutonCollections: {
shopProducts: {
name: 'shopProducts',
layer: 'shop',
componentName: 'ShopProductsForm',
// Custom properties
features: {
enableInventoryTracking: true,
enableVariants: true
},
permissions: {
create: 'product:create',
update: 'product:update',
delete: 'product:delete'
},
metadata: {
icon: 'i-lucide-package',
displayName: 'Products',
singularName: 'Product'
}
}
}
})
Access custom properties via useCollections():
const collections = useCollections()
const config = collections.getConfig('shopProducts')
if (config?.features?.enableInventoryTracking) {
// Show inventory fields
}
ExternalCollectionConfig
Configuration for external collections (e.g., users from auth system, third-party APIs).
interface ExternalCollectionConfig {
name: string
schema: z.ZodSchema
apiPath?: string
fetchStrategy?: 'query' | 'restful'
readonly?: boolean
meta?: {
label?: string
description?: string
}
proxy?: {
enabled: boolean
sourceEndpoint: string
transform: (item: any) => { id: string; title: string; [key: string]: any }
}
}
Property Details
| Property | Type | Default | Description |
|---|---|---|---|
name | string | required | Collection name (must match app.config.ts key) |
schema | z.ZodSchema | required | Zod schema for validation and types |
apiPath | string | name | API endpoint path |
fetchStrategy | 'query' | 'restful' | 'query' | Fetch method: ?ids= vs /{id} |
readonly | boolean | true | Hide edit/delete buttons in CardMini |
meta | object | {} | Display metadata |
proxy | object | undefined | Proxy configuration for external endpoints |
Basic External Collection
// composables/useExternalCollections.ts
import { defineExternalCollection } from '@friendlyinternet/nuxt-crouton'
import { z } from 'zod'
const userSchema = z.object({
id: z.string(),
title: z.string(), // Required for CroutonReferenceSelect display
email: z.string().optional(),
avatarUrl: z.string().optional()
})
export const usersConfig = defineExternalCollection({
name: 'users',
schema: userSchema,
apiPath: 'users',
readonly: true, // Users managed by auth system
meta: {
label: 'Team Members',
description: 'Users from the authentication system'
}
})
// app.config.ts
import { usersConfig } from '~/composables/useExternalCollections'
export default defineAppConfig({
croutonCollections: {
users: usersConfig,
// ... other collections
}
})
With Proxy Transform
Proxy external endpoints and transform data to Crouton format:
import { defineExternalCollection } from '@friendlyinternet/nuxt-crouton'
import { z } from 'zod'
const memberSchema = z.object({
id: z.string(),
title: z.string(),
role: z.string(),
joinedAt: z.string()
})
export const membersConfig = defineExternalCollection({
name: 'members',
schema: memberSchema,
proxy: {
enabled: true,
sourceEndpoint: 'members', // → /api/teams/[id]/members
transform: (item) => ({
id: item.userId,
title: `${item.firstName} ${item.lastName}`, // Transform to required 'title' field
role: item.memberRole,
joinedAt: item.createdAt
})
}
})
How proxy works:
- CroutonReferenceSelect fetches from
/api/teams/[teamId]/members - Raw data from external system is transformed using the
transformfunction - Transformed data has
idandtitlefields (required by Crouton) - Data displays correctly in CroutonItemCardMini and CroutonReferenceSelect
RESTful Fetch Strategy
For APIs using /resource/{id} pattern instead of /resource?ids=:
export const customersConfig = defineExternalCollection({
name: 'customers',
schema: customerSchema,
fetchStrategy: 'restful', // Use /{id} instead of ?ids=
apiPath: 'customers'
})
This changes how single items are fetched:
'query'(default):GET /api/teams/[id]/customers?ids=customer-123'restful':GET /api/teams/[id]/customers/customer-123
Layout System Types
LayoutType
Basic layout modes for displaying collections.
type LayoutType = 'table' | 'list' | 'grid' | 'cards' | 'tree'
| Layout | Description | Use Case |
|---|---|---|
table | Traditional data table | Desktop, detailed data with many columns |
list | Compact list view | Mobile, simple data, quick scanning |
grid | Grid of cards (2-3 columns) | Mobile/tablet, visual content |
cards | Large card tiles (1-2 columns) | Desktop, rich content with images |
tree | Hierarchical tree view | Parent-child relationships, nested data |
ResponsiveLayout
Responsive layout configuration with breakpoint support.
interface ResponsiveLayout {
base: LayoutType
sm?: LayoutType // 640px+
md?: LayoutType // 768px+
lg?: LayoutType // 1024px+
xl?: LayoutType // 1280px+
'2xl'?: LayoutType // 1536px+
}
Basic Responsive Layout
<script setup lang="ts">
const layout = {
base: 'list', // Mobile: list
md: 'grid', // Tablet: grid
lg: 'table' // Desktop: table
}
</script>
<template>
<CroutonCollection
:layout="layout"
:rows="products"
:columns="columns"
collection="shopProducts"
/>
</template>
Using Layout Presets
// Built-in presets
const layoutPresets = {
'responsive': { base: 'list', md: 'grid', lg: 'table' },
'mobile-friendly': { base: 'list', lg: 'table' },
'compact': { base: 'list', xl: 'table' }
}
<template>
<!-- Use preset by name -->
<CroutonCollection
layout="responsive"
:rows="products"
:columns="columns"
collection="shopProducts"
/>
</template>
Complex Responsive Example
<script setup lang="ts">
import type { ResponsiveLayout } from '@friendlyinternet/nuxt-crouton'
// Fine-tuned for different screen sizes
const layout: ResponsiveLayout = {
base: 'list', // Phone (< 640px)
sm: 'list', // Large phone (640px+)
md: 'grid', // Tablet (768px+)
lg: 'grid', // Small laptop (1024px+)
xl: 'table', // Desktop (1280px+)
'2xl': 'table' // Large desktop (1536px+)
}
</script>
<template>
<CroutonCollection
:layout="layout"
:rows="products"
:columns="columns"
collection="shopProducts"
/>
</template>
Table and Column Types
TableColumn
Column definition for table layouts.
interface TableColumn {
id?: string
accessorKey?: string
header: string | ((props: any) => any)
cell?: (props: any) => any
sortable?: boolean
enableSorting?: boolean
enableHiding?: boolean
}
Property Details
| Property | Type | Default | Description |
|---|---|---|---|
id | string | accessorKey | Unique column identifier |
accessorKey | string | - | Object property to access (dot notation supported) |
header | string | function | required | Column header text or render function |
cell | function | - | Custom cell renderer (receives { row, value }) |
sortable | boolean | false | Enable sorting for this column |
enableSorting | boolean | sortable | TanStack Table sorting flag |
enableHiding | boolean | true | Allow hiding this column |
Basic Columns
const columns: TableColumn[] = [
{
accessorKey: 'name',
header: 'Product Name',
sortable: true
},
{
accessorKey: 'price',
header: 'Price',
sortable: true
},
{
accessorKey: 'inStock',
header: 'In Stock'
}
]
Custom Cell Renderers
import type { TableColumn } from '@friendlyinternet/nuxt-crouton'
const columns: TableColumn[] = [
{
accessorKey: 'price',
header: 'Price',
cell: ({ value }) => `$${value.toFixed(2)}`
},
{
accessorKey: 'status',
header: 'Status',
cell: ({ row }) => {
const status = row.original.status
const color = status === 'active' ? 'green' : 'gray'
return h('span', { class: `text-${color}-600` }, status)
}
}
]
Nested Data Access
const columns: TableColumn[] = [
{
accessorKey: 'user.name', // Dot notation for nested properties
header: 'User Name'
},
{
accessorKey: 'location.city',
header: 'City'
}
]
Custom Header Renderers
const columns: TableColumn[] = [
{
accessorKey: 'price',
header: () => h('div', [
h('span', 'Price '),
h('span', { class: 'text-xs text-gray-500' }, '(USD)')
])
}
]
CollectionProps
Props interface for CroutonCollection component.
interface CollectionProps {
// Layout Configuration
layout?: LayoutType | ResponsiveLayout | keyof typeof layoutPresets
card?: 'Card' | 'CardMini' | 'CardSmall' | 'CardTree' | string // Card variant
// Data (Required)
rows: any[]
columns: TableColumn[]
collection: string
// Pagination
serverPagination?: boolean
paginationData?: PaginationData | null
refreshFn?: () => Promise<void> | null
// UI Options
create?: boolean
hideDefaultColumns?: {
createdAt?: boolean
updatedAt?: boolean
createdBy?: boolean
updatedBy?: boolean
actions?: boolean
}
}
The card prop allows specifying which card variant to use:
card="CardSmall"resolves to{Collection}CardSmall(e.g.,BookingsCardSmall)card="CardTree"resolves to{Collection}CardTree- No
cardprop uses{Collection}Cardwith thelayoutprop passed to it
Complete Example
useCollectionQuery patterns, see Querying Data.<script setup lang="ts">
import type { CollectionProps, TableColumn } from '@friendlyinternet/nuxt-crouton'
// See /fundamentals/querying for query patterns
const { items, pending, refresh } = await useCollectionQuery('shopProducts')
const columns: TableColumn[] = [
{ accessorKey: 'name', header: 'Name', sortable: true },
{ accessorKey: 'price', header: 'Price', sortable: true }
]
const paginationData = computed(() => ({
currentPage: page.value,
pageSize: 25,
totalItems: totalItems.value
}))
</script>
<template>
<CroutonCollection
layout="responsive"
:rows="items"
:columns="columns"
collection="shopProducts"
:server-pagination="true"
:pagination-data="paginationData"
:refresh-fn="refresh"
create
:hide-default-columns="{
createdBy: true,
updatedBy: true
}"
/>
</template>
Pagination Types
PaginationData
Pagination metadata for server-side pagination.
interface PaginationData {
currentPage: number
pageSize: number
totalItems: number
totalPages?: number
sortBy?: string
sortDirection?: 'asc' | 'desc'
}
Property Details
| Property | Type | Required | Description |
|---|---|---|---|
currentPage | number | Yes | Current page number (1-indexed) |
pageSize | number | Yes | Items per page |
totalItems | number | Yes | Total number of items across all pages |
totalPages | number | No | Total pages (auto-calculated if omitted) |
sortBy | string | No | Current sort column |
sortDirection | 'asc' | 'desc' | No | Current sort direction |
Pagination Usage
useCollectionQuery, see Querying Data.<script setup lang="ts">
// See /fundamentals/querying for query patterns
const { items, data } = await useCollectionQuery('shopProducts')
const paginationData = computed(() => ({
currentPage: page.value,
pageSize: 25,
totalItems: data.value?.pagination?.totalItems || 0
}))
</script>
<template>
<CroutonCollection
:rows="items"
:columns="columns"
collection="shopProducts"
:server-pagination="true"
:pagination-data="paginationData"
/>
</template>
Server Response Format
Your API should return data in this format:
// GET /api/teams/[id]/products?page=1&pageSize=25
{
items: [
{ id: '1', name: 'Product 1', price: 29.99 },
// ... more items
],
pagination: {
currentPage: 1,
pageSize: 25,
totalItems: 156,
totalPages: 7,
sortBy: 'name',
sortDirection: 'asc'
}
}
PaginationState (Internal)
Internal pagination state (used within composables).
interface PaginationState {
currentPage: number
pageSize: number
sortBy: string
sortDirection: 'asc' | 'desc'
totalItems?: number
totalPages?: number
}
Used internally by useCrouton() to manage pagination across multiple collections.
Composable Return Types
CollectionQueryReturn
Return type of useCollectionQuery().
interface CollectionQueryReturn<T = any> {
items: ComputedRef<T[]>
data: Ref<any>
refresh: () => Promise<void>
pending: Ref<boolean>
error: Ref<any>
}
Usage with Types
import type { ShopProduct } from '~/layers/shop/types/products'
const {
items, // ComputedRef<ShopProduct[]>
pending, // Ref<boolean>
error, // Ref<any>
refresh // () => Promise<void>
} = await useCollectionQuery<ShopProduct>('shopProducts')
CollectionQueryOptions
Options for useCollectionQuery().
interface CollectionQueryOptions {
query?: ComputedRef<Record<string, any>> | Ref<Record<string, any>>
watch?: boolean
}
Property Details
| Property | Type | Default | Description |
|---|---|---|---|
query | ComputedRef | Ref | {} | Reactive query parameters |
watch | boolean | true | Auto-refetch when query changes |
Basic Query Options
const page = ref(1)
const search = ref('')
const { items } = await useCollectionQuery('shopProducts', {
query: computed(() => ({
page: page.value,
search: search.value
})),
watch: true // Auto-refetch when page or search changes
})
CollectionMutation
Return type of useCollectionMutation().
interface CollectionMutation {
create: (data: any) => Promise<any>
update: (id: string, data: any) => Promise<any>
deleteItems: (ids: string[]) => Promise<void>
}
Usage
See Mutation Composables API for usage examples.
Component Prop Types
CardProps
Props for custom card components.
interface CardProps {
item: any
layout: 'list' | 'grid' | 'cards' | 'tree'
collection: string
pending?: boolean
error?: any
}
Custom Card Component
<script setup lang="ts">
import type { CardProps } from '@friendlyinternet/nuxt-crouton'
const props = defineProps<CardProps>()
</script>
<template>
<div :class="layout === 'list' ? 'py-2' : 'p-4 border rounded'">
<h3>{{ item.name }}</h3>
<p v-if="layout !== 'list'">{{ item.description }}</p>
</div>
</template>
TableSearchProps
Props for CroutonTableSearch component.
interface TableSearchProps {
modelValue: string
placeholder?: string
debounceMs?: number
}
TablePaginationProps
Props for CroutonTablePagination component.
interface TablePaginationProps {
page: number
pageCount: number
totalItems: number
loading?: boolean
pageSizes?: number[]
}
TableActionsProps
Props for CroutonTableActions component.
interface TableActionsProps {
selectedRows: any[]
collection: string
table?: any
onDelete?: (ids: string[]) => void
onColumnVisibilityChange?: (column: string, visible: boolean) => void
}
Hook System Types
crouton:mutation Hook
Nuxt hook emitted after successful mutations. Use for event tracking, analytics, or custom cache invalidation.
// Hook payload type
interface CroutonMutationPayload {
operation: 'create' | 'update' | 'delete'
collection: string
itemId?: string
data?: any
result?: any
}
Registering Hook Listeners
// plugins/crouton-events.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hooks.hook('crouton:mutation', async (payload) => {
const { operation, collection, itemId, data, result } = payload
// Track analytics
if (operation === 'create') {
console.log(`Created ${collection} item:`, itemId)
await $fetch('/api/analytics/track', {
method: 'POST',
body: {
event: `${collection}_created`,
properties: { itemId }
}
})
}
// Custom cache invalidation
if (collection === 'shopProducts' && operation === 'update') {
// Invalidate related caches
await clearNuxtData('product-analytics')
await clearNuxtData('trending-products')
}
})
})
Hook Payload Examples
Create operation:
{
operation: 'create',
collection: 'shopProducts',
itemId: 'product-123',
data: {
name: 'New Product',
price: 49.99
},
result: {
id: 'product-123',
name: 'New Product',
price: 49.99,
createdAt: '2025-01-15T10:30:00Z'
}
}
Update operation:
{
operation: 'update',
collection: 'shopProducts',
itemId: 'product-123',
data: {
price: 39.99
},
result: {
id: 'product-123',
name: 'New Product',
price: 39.99,
updatedAt: '2025-01-15T11:00:00Z'
}
}
Delete operation:
{
operation: 'delete',
collection: 'shopProducts',
itemId: undefined, // Not available for bulk delete
data: {
ids: ['product-123', 'product-456']
},
result: undefined
}
Use Cases for Hooks
1. Event Tracking / Analytics
nuxtApp.hooks.hook('crouton:mutation', async ({ operation, collection, itemId }) => {
await $fetch('/api/analytics/events', {
method: 'POST',
body: {
event: `${collection}.${operation}`,
userId: user.value?.id,
timestamp: new Date().toISOString(),
metadata: { itemId }
}
})
})
2. Audit Logging
nuxtApp.hooks.hook('crouton:mutation', async (payload) => {
await $fetch('/api/audit-log', {
method: 'POST',
body: {
action: payload.operation,
resource: payload.collection,
resourceId: payload.itemId,
changes: payload.data,
performedBy: user.value?.id,
timestamp: new Date()
}
})
})
3. Custom Cache Invalidation
nuxtApp.hooks.hook('crouton:mutation', async ({ collection, operation }) => {
// When products change, refresh dashboard stats
if (collection === 'shopProducts') {
await clearNuxtData('dashboard-stats')
await clearNuxtData('inventory-summary')
}
// When orders change, refresh customer data
if (collection === 'shopOrders') {
await clearNuxtData('customer-orders')
await clearNuxtData('revenue-stats')
}
})
4. Webhook Notifications
nuxtApp.hooks.hook('crouton:mutation', async (payload) => {
// Notify external systems of changes
if (payload.operation === 'create' && payload.collection === 'shopOrders') {
await $fetch('/api/webhooks/order-created', {
method: 'POST',
body: {
orderId: payload.itemId,
order: payload.result
}
})
}
})
5. Real-time Updates (WebSocket)
nuxtApp.hooks.hook('crouton:mutation', async (payload) => {
// Broadcast changes to connected clients
websocket.broadcast({
type: 'collection:mutation',
collection: payload.collection,
operation: payload.operation,
itemId: payload.itemId
})
})
State Management Types
CroutonState (Internal)
Internal state for modal/form management (used by useCrouton()).
interface CroutonState {
id: string
action: CroutonAction
collection: string | null
activeItem: any
items: any[]
loading: LoadingState
isOpen: boolean
containerType: 'slideover' | 'modal' | 'dialog'
}
type CroutonAction = 'create' | 'update' | 'delete' | 'view' | null
type LoadingState =
| 'notLoading'
| 'create_send' | 'update_send' | 'delete_send' | 'view_send'
| 'create_open' | 'update_open' | 'delete_open' | 'view_open'
Utility Types
ProxyConfig (Internal)
Configuration for proxying external collections.
interface ProxyConfig {
enabled: boolean
sourceEndpoint: string
transform: (item: any) => { id: string; title: string; [key: string]: any }
}
ConfigsMap (Internal)
Type for collection configuration registry.
type ConfigsMap = {
[K in CollectionName]?: CollectionConfig
}
Type Guards and Helpers
Checking Collection Config
const collections = useCollections()
const config = collections.getConfig('shopProducts')
if (!config) {
throw new Error('Collection not found')
}
// Access config properties
const apiPath = config.apiPath || 'products'
const references = config.references || {}
Type-Safe Query Building
import type { PaginationData } from '@friendlyinternet/nuxt-crouton'
function buildPaginationData(
page: number,
pageSize: number,
total: number
): PaginationData {
return {
currentPage: page,
pageSize,
totalItems: total,
totalPages: Math.ceil(total / pageSize)
}
}
Type-Safe Column Definitions
import type { TableColumn } from '@friendlyinternet/nuxt-crouton'
import type { ShopProduct } from '~/layers/shop/types/products'
function defineProductColumns(): TableColumn[] {
return [
{
accessorKey: 'name',
header: 'Product Name',
sortable: true
},
{
accessorKey: 'price',
header: 'Price',
cell: ({ row }: { row: { original: ShopProduct } }) =>
`$${row.original.price.toFixed(2)}`
}
]
}
Common Patterns
Pattern 1: Type-Safe Collection Setup
// 1. Define your data type
import type { ShopProduct } from '~/layers/shop/types/products'
// 2. Register collection config
// app.config.ts
export default defineAppConfig({
croutonCollections: {
shopProducts: {
name: 'shopProducts',
layer: 'shop',
componentName: 'ShopProductsForm'
}
}
})
// 3. Use with type parameter
const { items, pending } = await useCollectionQuery<ShopProduct>('shopProducts')
// items is ComputedRef<ShopProduct[]>
Pattern 2: External Collection with Transform
// 1. Define external collection
import { defineExternalCollection } from '@friendlyinternet/nuxt-crouton'
export const membersConfig = defineExternalCollection({
name: 'members',
schema: z.object({
id: z.string(),
title: z.string()
}),
proxy: {
enabled: true,
sourceEndpoint: 'members',
transform: (item) => ({
id: item.userId,
title: `${item.firstName} ${item.lastName}`
})
}
})
// 2. Register in app.config.ts
export default defineAppConfig({
croutonCollections: {
members: membersConfig
}
})
// 3. Use in components
const { items } = await useCollectionQuery('members')
Pattern 3: Responsive Layout with Type Safety
import type { ResponsiveLayout, TableColumn } from '@friendlyinternet/nuxt-crouton'
const layout: ResponsiveLayout = {
base: 'list',
md: 'grid',
lg: 'table'
}
const columns: TableColumn[] = [
{ accessorKey: 'name', header: 'Name' }
]
Pattern 4: Server Pagination with Types
import type { PaginationData } from '@friendlyinternet/nuxt-crouton'
const page = ref(1)
const { items, data } = await useCollectionQuery('shopProducts', {
query: computed(() => ({ page: page.value }))
})
const paginationData = computed<PaginationData>(() => ({
currentPage: page.value,
pageSize: 25,
totalItems: data.value?.pagination?.totalItems || 0
}))
Pattern 5: Hook Integration
// Plugin for mutation tracking
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hooks.hook('crouton:mutation', async (payload) => {
// Type-safe payload access
const { operation, collection, itemId, data, result } = payload
console.log(`[${operation}] ${collection}:`, itemId)
})
})
TypeScript Configuration
Recommended tsconfig.json
{
"extends": "./.nuxt/tsconfig.json",
"compilerOptions": {
"strict": true,
"types": ["@nuxt/types", "@friendlyinternet/nuxt-crouton"]
}
}
Module Augmentation
Extend Crouton types for your app:
// types/crouton.d.ts
declare module '@friendlyinternet/nuxt-crouton' {
interface CollectionConfig {
// Add custom properties
permissions?: {
create?: string
update?: string
delete?: string
}
metadata?: {
icon?: string
displayName?: string
}
}
}
Type Checking
Always run type checking after making changes:
# Type check your application
npx nuxt typecheck
# Watch mode for development
npx nuxt typecheck --watch
Related Resources
- Components Reference - Component prop types
- Composables Reference - Composable return types
- Collection Generator - Generated types from schemas
- TypeScript in Nuxt - Official Nuxt TypeScript guide