---
title: "How to Customize Document Previews in Sanity CMS Studio"
slug: "sanity-customize-document-previews"
published: "2025-09-22"
updated: "2025-09-17"
validated: "2025-10-20"
categories:
  - "Sanity"
tags:
  - "sanity"
  - "sanity studio"
  - "document preview"
  - "select"
  - "prepare"
  - "cms"
  - "content modeling"
  - "typescript"
  - "studio customization"
llm-intent: "reference"
audience-level: "intermediate"
framework-versions:
  - "sanity"
  - "typescript"
  - "next.js"
status: "stable"
llm-purpose: "Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references"
llm-prereqs:
  - "Access to Sanity"
  - "Access to TypeScript"
  - "Access to Next.js"
llm-outputs:
  - "Completed outcome: Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references"
---

**Summary Triples**
- (document schema, includes, preview configuration with select and prepare)
- (select, maps, document fields to preview keys (e.g., title, subtitle, media))
- (prepare, transforms, selected fields into the final preview object returned to Studio)
- (prepare, can compute, derived values such as status (draft/scheduled/published) and formatted dates)
- (select, supports, dotted paths for nested fields and reference dereferencing (use 'author->name' for references))
- (preview.media, can use, an image field or be set via prepare to provide fallbacks or custom React components)
- (defineType, declares, document type and its preview config in TypeScript schemas)
- (use-cases, include, showing publication dates, status indicators, reference fields, and computed summaries in lists)
- (date display, requires, selecting publishedAt and formatting it inside prepare)
- (debugging, requires, verifying field names in select, rebuilding Studio, and providing fallbacks in prepare)

### {GOAL}
Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references

### {PREREQS}
- Access to Sanity
- Access to TypeScript
- Access to Next.js

### {STEPS}
1. Understand the preview system
2. Add a basic preview
3. Select additional fields
4. Format and combine data
5. Add advanced patterns
6. Apply to other types
7. Compute complex summaries
8. Follow best practices

<!-- llm:goal="Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references" -->
<!-- llm:prereq="Access to Sanity" -->
<!-- llm:prereq="Access to TypeScript" -->
<!-- llm:prereq="Access to Next.js" -->
<!-- llm:output="Completed outcome: Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references" -->

# How to Customize Document Previews in Sanity CMS Studio
> Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references
Matija Žiberna · 2025-09-22

Last week, I was working on a client project where content creators needed to see publication dates and other key information directly in their Sanity Studio document lists. The default preview only shows title and maybe an image, but when you're managing scheduled content or complex document types, you need more context at a glance. After implementing custom previews across several document types, I'm sharing the complete process for tailoring how your documents appear in Sanity Studio lists.

## Understanding Sanity's Preview System

Sanity's preview system controls how documents appear in Studio lists, search results, and reference inputs. Every document type can have a custom preview configuration that determines which fields are displayed and how they're formatted. The preview system consists of two main parts: field selection and data preparation.

By default, Sanity shows just the document title and perhaps a main image. This works for simple content, but complex workflows require more information. The preview configuration lives in your document schema and gives you complete control over what content creators see when browsing documents.

## Basic Preview Configuration

Here's how a typical document preview is structured:

```typescript
// File: src/lib/sanity/schemaTypes/postType.ts
export const postType = defineType({
  name: 'post',
  title: 'Post',
  type: 'document',
  fields: [
    // ... your field definitions
  ],
  preview: {
    select: {
      title: 'title',
      subtitle: 'subtitle',
      media: 'mainImage',
    },
    prepare(selection) {
      return {
        title: selection.title,
        subtitle: selection.subtitle,
        media: selection.media,
      }
    },
  },
})
```

The `select` object defines which fields from your document to include in the preview. The `prepare` function receives those selected fields and returns the final preview object that Sanity displays. This two-step process gives you flexibility to transform and format data before it appears in the interface.

## Adding Custom Fields to Preview

Let's extend this basic setup to show publication dates and other relevant information. First, expand the field selection to include the data you need:

```typescript
// File: src/lib/sanity/schemaTypes/postType.ts
preview: {
  select: {
    title: 'title',
    subtitle: 'subtitle',
    author: 'author.name',
    media: 'mainImage',
    publishedAt: 'publishedAt',
    isHowTo: 'isHowTo',
    gallery: 'gallery',
  },
  prepare(selection) {
    const { author, subtitle, publishedAt, isHowTo, gallery } = selection
    
    // We'll customize this in the next step
    return {
      title: selection.title,
      subtitle: subtitle,
      media: selection.media,
    }
  },
}
```

Notice how you can select fields from referenced documents using dot notation (`author.name`) and access array fields like `gallery`. Sanity automatically resolves these relationships when building the preview.

## Formatting and Combining Data

The real power comes in the `prepare` function where you can format dates, combine multiple fields, and create conditional displays:

```typescript
// File: src/lib/sanity/schemaTypes/postType.ts
prepare(selection) {
  const { author, subtitle, publishedAt, isHowTo, gallery } = selection
  
  let subtitleText = ''
  
  // Format the published date
  const publishedDate = publishedAt ? new Date(publishedAt).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric'
  }) : ''
  
  if (publishedDate) {
    subtitleText = publishedDate
  }
  
  // Add conditional content type indicator
  if (isHowTo) {
    subtitleText = subtitleText ? `${subtitleText} • 📋 How-To Guide` : '📋 How-To Guide'
  } else if (subtitle) {
    subtitleText = subtitleText ? `${subtitleText} • ${subtitle}` : subtitle
  } else if (author) {
    const authorText = `by ${author}`
    subtitleText = subtitleText ? `${subtitleText} • ${authorText}` : authorText
  }
  
  // Add gallery count if images exist
  if (gallery && gallery.length > 0) {
    const galleryText = `${gallery.length} gallery image${gallery.length === 1 ? '' : 's'}`
    subtitleText = subtitleText ? `${subtitleText} • ${galleryText}` : galleryText
  }
  
  return {
    title: selection.title,
    subtitle: subtitleText,
    media: selection.media,
  }
},
```

This approach creates rich, informative previews. You might see something like "Jan 15, 2024 • 📋 How-To Guide • 3 gallery images" in your document list, giving content creators immediate context about each post.

## Advanced Preview Patterns

### Conditional Media Selection

Sometimes you want different images based on document content:

```typescript
prepare(selection) {
  const { title, mainImage, gallery, video } = selection
  
  // Use video thumbnail if available, otherwise main image, otherwise first gallery image
  let media = mainImage
  if (!media && video) {
    media = selection.videoThumbnail
  }
  if (!media && gallery && gallery.length > 0) {
    media = gallery[0]
  }
  
  return {
    title,
    media,
    subtitle: `${gallery?.length || 0} images • ${video ? 'Has video' : 'No video'}`
  }
}
```

### Status-Based Formatting

For documents with workflow states, you can indicate status visually:

```typescript
prepare(selection) {
  const { title, status, publishedAt } = selection
  
  let subtitle = ''
  let title_formatted = title
  
  if (status === 'draft') {
    title_formatted = `[DRAFT] ${title}`
    subtitle = 'Not published'
  } else if (status === 'scheduled') {
    subtitle = `Scheduled: ${new Date(publishedAt).toLocaleDateString()}`
  } else if (status === 'published') {
    subtitle = `Published: ${new Date(publishedAt).toLocaleDateString()}`
  }
  
  return {
    title: title_formatted,
    subtitle,
    media: selection.media,
  }
}
```

### Reference Field Details

When working with references, you can show related information:

```typescript
select: {
  title: 'title',
  categoryTitle: 'category.title',
  categoryColor: 'category.color',
  authorName: 'author.name',
  authorImage: 'author.image',
},
prepare(selection) {
  const { categoryTitle, authorName } = selection
  
  return {
    title: selection.title,
    subtitle: `${categoryTitle} • by ${authorName}`,
    media: selection.authorImage,
  }
}
```

## Applying to Different Document Types

This pattern works for any document type. Here's how you might customize a product preview:

```typescript
// File: src/lib/sanity/schemaTypes/productType.ts
preview: {
  select: {
    title: 'name',
    price: 'price',
    inventory: 'inventory',
    category: 'category.title',
    image: 'images.0', // First image from array
    onSale: 'onSale',
  },
  prepare(selection) {
    const { price, inventory, category, onSale } = selection
    
    const priceText = `$${price}`
    const stockText = inventory > 0 ? `${inventory} in stock` : 'Out of stock'
    const saleText = onSale ? 'ON SALE' : ''
    
    const subtitle = [saleText, priceText, stockText, category]
      .filter(Boolean)
      .join(' • ')
    
    return {
      title: selection.title,
      subtitle,
      media: selection.image,
    }
  },
}
```

This creates previews like "ON SALE • $29.99 • 15 in stock • Electronics" that give immediate business context.

## Complex Data Transformations

Sometimes you need to perform calculations or complex logic:

```typescript
prepare(selection) {
  const { title, tasks, totalEstimate } = selection
  
  const completedTasks = tasks?.filter(task => task.completed).length || 0
  const totalTasks = tasks?.length || 0
  const progressPercent = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0
  
  const estimateHours = Math.round(totalEstimate / 60) // Convert minutes to hours
  
  return {
    title,
    subtitle: `${progressPercent}% complete • ${completedTasks}/${totalTasks} tasks • ${estimateHours}h estimated`,
    media: selection.media,
  }
}
```

## Best Practices for Preview Customization

Keep preview subtitles concise but informative. Users scan these quickly, so prioritize the most important information first. Use consistent separators like bullets (•) to create visual structure, and consider using emoji sparingly for quick visual categorization.

Test your previews with real data to ensure they handle edge cases gracefully. Empty fields, missing references, and null values should all be handled elegantly in your prepare function.

Remember that previews are rebuilt whenever documents change, so avoid expensive operations in the prepare function. Simple data formatting and concatenation work well, but avoid API calls or complex calculations.

## Conclusion

Custom document previews transform the Sanity Studio experience from a basic list of titles into an information-rich interface that helps content creators work efficiently. By combining the `select` and `prepare` pattern, you can show dates, status indicators, related content, and calculated values directly in document lists.

The key insight is that the `select` object defines your data requirements, while the `prepare` function gives you complete control over formatting and presentation. This pattern works for any document type and scales from simple date formatting to complex business logic display.

Want to take your Sanity Studio customization further? Check out my guide on [adding custom sorting options to document lists](./sanity-custom-sorting-options.md) for complete control over how your content is organized.

Let me know in the comments if you have questions about customizing previews for your specific document types, and subscribe for more practical Sanity CMS guides.

Thanks, Matija

## LLM Response Snippet
```json
{
  "goal": "Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references",
  "responses": [
    {
      "question": "What does the article \"How to Customize Document Previews in Sanity CMS Studio\" cover?",
      "answer": "Guide to customizing Sanity CMS Studio document previews using select and prepare for richer lists: dates, status indicators, references"
    }
  ]
}
```