mdxui

Auto-Wiring

Automatic Payload CMS collection mapping for Site and App components

Auto-Wiring

Auto-wiring is mdxui's automatic mapping between components and Payload CMS collections. Components marked with @autowire comments query their data automatically without manual setup.

How It Works

When you use components like Blog, APIKeys, or Webhooks, mdxui automatically:

  1. Identifies the corresponding Payload collection
  2. Configures default query parameters (sorting, limits)
  3. Passes data to the component as props
  4. Handles loading states and errors

This eliminates boilerplate data fetching code and ensures consistent patterns across your application.

Site Auto-Wiring

The siteAutoWiring object maps Site components to their Payload collections.

import { siteAutoWiring } from 'mdxui'

console.log(siteAutoWiring)
// {
//   Blog: {
//     collection: 'posts',
//     defaultQuery: {
//       limit: 10,
//       sort: '-publishedAt'
//     }
//   },
//   BlogPost: {
//     collection: 'posts'
//   },
//   Docs: {
//     collection: 'docs',
//     defaultQuery: {
//       sort: 'order'
//     }
//   },
//   DocsPage: {
//     collection: 'docs'
//   }
// }

Site Components with Auto-Wiring

Blog

Auto-wires to the posts collection.

// Component definition
interface BlogProps {
  posts?: Post[]
  // ... other props
}

// Auto-wire configuration
{
  collection: 'posts',
  defaultQuery: {
    limit: 10,
    sort: '-publishedAt'  // Newest first
  }
}

Usage:

// mdxui automatically fetches posts
<Blog />

// Or provide custom data
<Blog posts={customPosts} />

BlogPost

Auto-wires to the posts collection (single post).

interface BlogPostProps {
  post?: Post
  slug?: string
  // ... other props
}

// Auto-wire configuration
{
  collection: 'posts'
}

Usage:

// Fetch by slug from URL
<BlogPost slug={params.slug} />

// Or provide post data
<BlogPost post={post} />

Docs

Auto-wires to the docs collection.

interface DocsProps {
  docs?: Doc[]
  // ... other props
}

// Auto-wire configuration
{
  collection: 'docs',
  defaultQuery: {
    sort: 'order'  // Ordered by manual sort field
  }
}

Usage:

<Docs />

DocsPage

Auto-wires to the docs collection (single doc page).

interface DocsPageProps {
  doc?: Doc
  slug?: string
  // ... other props
}

// Auto-wire configuration
{
  collection: 'docs'
}

Usage:

<DocsPage slug={params.slug} />

App Auto-Wiring

The appAutoWiring object maps App components to their Payload collections.

import { appAutoWiring } from 'mdxui'

console.log(appAutoWiring)
// {
//   APIKeys: {
//     collection: 'apiKeys',
//     defaultQuery: {
//       sort: '-createdAt'
//     }
//   },
//   Webhooks: {
//     collection: 'webhooks',
//     defaultQuery: {
//       sort: '-createdAt'
//     }
//   },
//   Usage: {
//     collection: 'usageRecords',
//     defaultQuery: {
//       sort: '-timestamp'
//     }
//   },
//   Team: {
//     collection: 'members',
//     defaultQuery: {
//       sort: 'name'
//     }
//   },
//   Billing: {
//     collection: 'subscriptions'
//   }
// }

App Components with Auto-Wiring

APIKeys

Auto-wires to the apiKeys collection.

interface APIKeysProps {
  apiKeys?: APIKey[]
  // ... other props
}

// Auto-wire configuration
{
  collection: 'apiKeys',
  defaultQuery: {
    sort: '-createdAt'  // Newest first
  }
}

Usage:

<APIKeys />

The component automatically:

  • Fetches API keys for the current user
  • Provides create/revoke actions
  • Shows key metadata (created date, last used, etc.)

Webhooks

Auto-wires to the webhooks collection.

interface WebhooksProps {
  webhooks?: Webhook[]
  // ... other props
}

// Auto-wire configuration
{
  collection: 'webhooks',
  defaultQuery: {
    sort: '-createdAt'
  }
}

Usage:

<Webhooks />

Features:

  • Create/edit/delete webhooks
  • Test webhook endpoints
  • View delivery history
  • Retry failed deliveries

Usage

Auto-wires to the usageRecords collection.

interface UsageProps {
  usageRecords?: UsageRecord[]
  // ... other props
}

// Auto-wire configuration
{
  collection: 'usageRecords',
  defaultQuery: {
    sort: '-timestamp'  // Most recent first
  }
}

Usage:

<Usage />

Shows:

  • API call volume over time
  • Resource consumption metrics
  • Cost estimates
  • Usage limits and quotas

Team

Auto-wires to the members collection.

interface TeamProps {
  members?: Member[]
  // ... other props
}

// Auto-wire configuration
{
  collection: 'members',
  defaultQuery: {
    sort: 'name'  // Alphabetical
  }
}

Usage:

<Team />

Provides:

  • Invite team members
  • Manage roles and permissions
  • Remove team members
  • View member activity

Billing

Auto-wires to the subscriptions collection.

interface BillingProps {
  subscription?: Subscription
  // ... other props
}

// Auto-wire configuration
{
  collection: 'subscriptions'
}

Usage:

<Billing />

Features:

  • View current plan
  • Upgrade/downgrade plans
  • Manage payment methods
  • View billing history
  • Download invoices

AutoWire Type

The AutoWire interface defines the auto-wiring configuration:

interface AutoWire {
  /** The Payload collection to query */
  collection: string

  /** Default query parameters */
  defaultQuery?: {
    /** Filter conditions */
    where?: Record<string, unknown>
    /** Maximum records to fetch */
    limit?: number
    /** Sort order (use '-' prefix for descending) */
    sort?: string
  }
}

Custom Auto-Wiring

You can extend auto-wiring for custom components:

import type { AutoWire } from 'mdxui'

const customAutoWiring: Record<string, AutoWire> = {
  Products: {
    collection: 'products',
    defaultQuery: {
      limit: 20,
      sort: '-featured',
      where: {
        status: 'published'
      }
    }
  },
  Testimonials: {
    collection: 'testimonials',
    defaultQuery: {
      limit: 6,
      sort: 'order',
      where: {
        approved: true
      }
    }
  }
}

Using Auto-Wiring in Your Runtime

If you're building a custom mdxui runtime, use the auto-wiring configs to fetch data:

import { siteAutoWiring, appAutoWiring } from 'mdxui'
import { payload } from './payload'

async function fetchComponentData(componentName: string, props: any) {
  // Check if component has auto-wiring
  const autoWire = siteAutoWiring[componentName] || appAutoWiring[componentName]

  if (!autoWire) {
    return null  // No auto-wiring
  }

  // If data already provided in props, use it
  const dataKey = componentName.toLowerCase()
  if (props[dataKey]) {
    return props
  }

  // Fetch from Payload
  const { collection, defaultQuery } = autoWire

  const result = await payload.find({
    collection,
    limit: defaultQuery?.limit,
    sort: defaultQuery?.sort,
    where: defaultQuery?.where
  })

  // Return props with auto-wired data
  return {
    ...props,
    [dataKey]: result.docs
  }
}

Collection Schema

All auto-wired collections should follow consistent schemas:

Posts Collection

{
  slug: 'posts',
  fields: [
    { name: 'title', type: 'text', required: true },
    { name: 'slug', type: 'text', required: true, unique: true },
    { name: 'content', type: 'richText', required: true },
    { name: 'excerpt', type: 'textarea' },
    { name: 'author', type: 'relationship', relationTo: 'users' },
    { name: 'publishedAt', type: 'date' },
    { name: 'status', type: 'select', options: ['draft', 'published'] },
    { name: 'featured', type: 'checkbox' },
    { name: 'tags', type: 'array', fields: [{ name: 'tag', type: 'text' }] }
  ]
}

API Keys Collection

{
  slug: 'apiKeys',
  fields: [
    { name: 'name', type: 'text', required: true },
    { name: 'key', type: 'text', required: true, unique: true },
    { name: 'prefix', type: 'text' },
    { name: 'lastUsed', type: 'date' },
    { name: 'expiresAt', type: 'date' },
    { name: 'scopes', type: 'array', fields: [{ name: 'scope', type: 'text' }] },
    { name: 'user', type: 'relationship', relationTo: 'users', required: true },
    { name: 'active', type: 'checkbox', defaultValue: true }
  ]
}

Webhooks Collection

{
  slug: 'webhooks',
  fields: [
    { name: 'name', type: 'text', required: true },
    { name: 'url', type: 'text', required: true },
    { name: 'events', type: 'array', fields: [{ name: 'event', type: 'text' }] },
    { name: 'secret', type: 'text' },
    { name: 'active', type: 'checkbox', defaultValue: true },
    { name: 'user', type: 'relationship', relationTo: 'users', required: true },
    { name: 'lastDelivery', type: 'date' },
    { name: 'failureCount', type: 'number', defaultValue: 0 }
  ]
}

Benefits

Auto-wiring provides several advantages:

  1. Less Boilerplate: No manual data fetching code
  2. Consistency: Same patterns across all components
  3. Type Safety: TypeScript knows the expected data shape
  4. Defaults: Sensible defaults for sorting and limits
  5. Flexibility: Can override with custom data
  6. Documentation: Self-documenting data requirements

Next Steps

On this page