cosmic

Build applications with Cosmic headless CMS using the JavaScript SDK. Covers Objects, Media, AI generation (text, images, video), content modeling with Metafields, and queries. Use when working with Cosmic CMS, @cosmicjs/sdk, headless content, or building JAMstack applications.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "cosmic" with this command: npx skills add cosmicjs/skills/cosmicjs-skills-cosmic

Cosmic CMS

Build content-powered applications with the Cosmic headless CMS.

SDK-First Principle

Always use the @cosmicjs/sdk package. The SDK provides type-safe methods, better error handling, and cleaner syntax than raw REST calls.

bun add @cosmicjs/sdk
# or: npm install @cosmicjs/sdk

Setup

import { createBucketClient } from '@cosmicjs/sdk'

const cosmic = createBucketClient({
  bucketSlug: 'BUCKET_SLUG',
  readKey: 'BUCKET_READ_KEY',
  writeKey: 'BUCKET_WRITE_KEY' // Required for create/update/delete
})

Find keys in Cosmic Dashboard → Bucket → Settings → API Access.

Objects (Content)

Objects are the core content units. Each Object belongs to an Object type (like "posts", "products").

Read Objects

// Get multiple Objects
const posts = await cosmic.objects
  .find({ type: 'posts' })
  .props(['id', 'title', 'slug', 'metadata'])
  .limit(10)

// Get single Object by slug
const post = await cosmic.objects
  .findOne({ type: 'posts', slug: 'hello-world' })
  .props(['title', 'slug', 'metadata'])

// Get single Object by id
const obj = await cosmic.objects
  .findOne({ id: 'object-id' })
  .props(['title', 'metadata'])

Props Syntax

Use GraphQL-style syntax for nested properties:

const props = `{
  id
  slug
  title
  metadata {
    content
    author {
      title
      metadata {
        avatar { imgix_url }
      }
    }
  }
}`
await cosmic.objects.find({ type: 'posts' }).props(props)

Create Object

await cosmic.objects.insertOne({
  title: 'My Post',
  type: 'posts', // Object type SLUG, not title
  metadata: {
    content: 'Post content here...',
    author: 'author-object-id',        // Object relationship: use id
    featured_image: 'image-name.jpg'   // Media: use name property
  }
})

Update Object

await cosmic.objects.updateOne('object-id', {
  title: 'Updated Title',
  metadata: {
    featured: true,
    categories: ['cat1-id', 'cat2-id'] // Multiple objects: array of ids
  }
})

Delete Object

await cosmic.objects.deleteOne('object-id')

Object Types

Define content structure with Object types.

// List all Object types
const types = await cosmic.objectTypes.find()

// Get single Object type
const blogType = await cosmic.objectTypes.findOne('posts')

// Create Object type with Metafields
await cosmic.objectTypes.insertOne({
  title: 'Blog Posts',
  slug: 'posts',
  singular: 'Post',
  emoji: '📝',
  metafields: [
    { title: 'Content', key: 'content', type: 'markdown', required: true },
    { title: 'Image', key: 'image', type: 'file', media_validation_type: 'image' },
    { title: 'Author', key: 'author', type: 'object', object_type: 'authors' },
    { title: 'Tags', key: 'tags', type: 'objects', object_type: 'tags' }
  ]
})

Metafield Types

TypeDescriptionValue Format
textSingle line textstring
textareaMulti-line textstring
markdownMarkdown editorstring
html-textareaRich HTML editorstring
numberNumeric valuenumber
dateDate picker"YYYY-MM-DD"
switchBoolean toggletrue/false
select-dropdownDropdown selectionstring
radio-buttonsRadio selectionstring
check-boxesMultiple selectionstring[]
fileSingle mediaMedia name
filesMultiple mediaMedia name[]
objectSingle relationObject id
objectsMultiple relationsObject id[]
jsonJSON dataobject
colorColor picker"#hex"
repeaterRepeatable grouparray
parentNested groupobject

Queries

Filter content using MongoDB-style queries:

// Basic filter
await cosmic.objects.find({
  type: 'products',
  'metadata.category': 'electronics'
})

// Comparison operators
await cosmic.objects.find({
  type: 'products',
  'metadata.price': { $lt: 100 }    // Less than
  // $gt, $gte, $lte, $eq, $ne also available
})

// Array matching
await cosmic.objects.find({
  type: 'products',
  'metadata.tags': { $in: ['sale', 'featured'] }  // Any match
  // $all for all must match, $nin for none match
})

// Logical operators
await cosmic.objects.find({
  type: 'products',
  $and: [
    { 'metadata.price': { $lte: 50 } },
    { 'metadata.in_stock': true }
  ]
  // $or, $not, $nor also available
})

// Text search
await cosmic.objects.find({
  type: 'posts',
  title: { $regex: 'hello', $options: 'i' }  // Case insensitive
})

Query Options

await cosmic.objects.find({ type: 'posts' })
  .props(['title', 'slug', 'metadata'])
  .sort('-created_at')  // Descending by created date
  .limit(10)
  .skip(20)             // Pagination
  .depth(2)             // Resolve nested Object relationships
  .status('any')        // 'published' | 'draft' | 'any'

Media

// List media
const media = await cosmic.media
  .find({ folder: 'images' })
  .props(['url', 'imgix_url', 'alt_text'])
  .limit(20)

// Upload media
const uploaded = await cosmic.media.insertOne({
  media: { originalname: 'photo.jpg', buffer: fileBuffer },
  folder: 'uploads',
  alt_text: 'Description of image',
  metadata: { caption: 'Photo caption' }
})

// Update media
await cosmic.media.updateOne('media-id', {
  alt_text: 'Updated alt text',
  folder: 'new-folder'
})

// Delete media
await cosmic.media.deleteOne('media-id')

imgix Image Processing

All images have imgix_url for transformations:

const optimized = `${media.imgix_url}?w=800&auto=format,compress`
const thumbnail = `${media.imgix_url}?w=100&h=100&fit=crop`

AI Generation

Cosmic provides built-in AI capabilities for text, images, and video.

Generate Text

// Simple prompt
const text = await cosmic.ai.generateText({
  prompt: 'Write a product description for a coffee mug',
  model: 'claude-sonnet-4-5-20250929', // Optional
  max_tokens: 500
})
console.log(text.text)

// Chat messages
const chat = await cosmic.ai.generateText({
  messages: [
    { role: 'user', content: 'Tell me about coffee' },
    { role: 'assistant', content: 'Coffee is a beverage...' },
    { role: 'user', content: 'What about espresso?' }
  ]
})

// Analyze image or document
const analysis = await cosmic.ai.generateText({
  prompt: 'Describe this image',
  media_url: 'https://cdn.cosmicjs.com/image.jpg'
})

// Streaming
const stream = await cosmic.ai.stream({
  prompt: 'Write a blog post',
  max_tokens: 1000
})
for await (const chunk of stream) {
  process.stdout.write(chunk.text || '')
}

Generate Image

const image = await cosmic.ai.generateImage({
  prompt: 'Mountain landscape at sunset',
  model: 'gemini-3-pro-image-preview', // Default, supports up to 4K
  size: '1024x1024',
  folder: 'ai-generated',
  alt_text: 'AI mountain landscape'
})
console.log(image.media.url)

// With reference images (Gemini only)
const styled = await cosmic.ai.generateImage({
  prompt: 'Same style but with ocean',
  reference_images: ['https://cdn.cosmicjs.com/style-ref.jpg']
})

Generate Video

const video = await cosmic.ai.generateVideo({
  prompt: 'A kitten playing with yarn in sunlight',
  model: 'veo-3.1-fast-generate-preview', // Fast: 30-90s generation
  duration: 8,        // 4, 6, or 8 seconds
  resolution: '720p', // or '1080p'
  folder: 'videos'
})
console.log(video.media.url)

// With reference image as first frame
const productVideo = await cosmic.ai.generateVideo({
  prompt: 'Product rotates smoothly',
  reference_images: ['https://cdn.cosmicjs.com/product.jpg'],
  duration: 6
})

// Extend existing video
const extended = await cosmic.ai.extendVideo({
  media_id: video.media.id,
  prompt: 'The kitten walks away into the garden'
})

Available AI Models

Text: claude-sonnet-4-5-20250929 (recommended), claude-opus-4-5-20251101, gpt-5, gemini-3-pro-preview

Image: gemini-3-pro-image-preview (default, up to 4K), dall-e-3

Video: veo-3.1-fast-generate-preview (recommended), veo-3.1-generate-preview (premium)

Framework Patterns

Next.js App Router

// app/posts/page.tsx
import { createBucketClient } from '@cosmicjs/sdk'

const cosmic = createBucketClient({
  bucketSlug: process.env.COSMIC_BUCKET_SLUG!,
  readKey: process.env.COSMIC_READ_KEY!
})

export default async function Posts() {
  const { objects: posts } = await cosmic.objects
    .find({ type: 'posts' })
    .props(['title', 'slug', 'metadata.excerpt'])
    .limit(10)

  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

Server Actions

'use server'

export async function createPost(formData: FormData) {
  const cosmic = createBucketClient({
    bucketSlug: process.env.COSMIC_BUCKET_SLUG!,
    readKey: process.env.COSMIC_READ_KEY!,
    writeKey: process.env.COSMIC_WRITE_KEY!
  })

  await cosmic.objects.insertOne({
    title: formData.get('title') as string,
    type: 'posts',
    metadata: {
      content: formData.get('content')
    }
  })
}

Common Patterns

Pagination

const page = 1
const limit = 10

const { objects, total } = await cosmic.objects
  .find({ type: 'posts' })
  .skip((page - 1) * limit)
  .limit(limit)

const totalPages = Math.ceil(total / limit)

Draft Preview

const post = await cosmic.objects
  .findOne({ type: 'posts', slug })
  .status('any')  // Include drafts

Localized Content

const post = await cosmic.objects
  .findOne({ type: 'posts', slug, locale: 'es' })

Key Reminders

  1. Object type is the SLUG - Use type: 'blog-posts', not type: 'Blog Posts'
  2. Media uses name - Reference media by name property, not URL
  3. Relations use id - Reference related Objects by id, not slug
  4. Never expose writeKey - Keep it server-side only
  5. Use props() - Always specify needed properties for performance
  6. imgix for images - Use imgix_url with query params for optimizations

Resources

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

nano-banana-2

Nano Banana 2 - Gemini 3.1 Flash Image Preview

Repository Source
15339.7K
inferen-sh
General

p-video

Pruna P-Video Generation

Repository Source
15339.5K
inferen-sh
General

qwen-image-2

Qwen-Image - Alibaba Image Generation

Repository Source
15339.5K
inferen-sh