Article: Create and Publish Blog Posts with Rich Content and Images
Article URL:
https://dev.wix.com/docs/kb-only/MCP_REST_RECIPES_KB_ID/TRAIN_how-to-create-a-blog-post
This article demonstrates how to create and immediately publish blog posts using Wix Blog application, including handling external images, rich content formatting, and proper media management workflow.
IMPORTANT: Use the Wix SDK rather than direct API calls whenever possible
Identify external image URLs from user input for cover images and embedded content images.
Import each external image using Import File (SDK | REST). This converts external URLs to Wix Media IDs required for blog posts.
import { files } from '@wix/media';
const importResult = await files.importFile({
url: 'https://example.com/image.jpg',
mediaType: files.MediaType.IMAGE,
displayName: 'Cover Image.jpg'
});
const mediaId = importResult.file.id; // Use this ID in blog post
Store the returned file IDs for use in blog post creation. Images with operationStatus: "PENDING"
can be used immediately.
Create blog post using Create Draft Post (SDK | REST) for single posts, or Bulk Create Draft Posts (SDK | REST) for multiple posts.
import { draftPosts } from '@wix/blog';
const result = await draftPosts.createDraftPost({
draftPost: {
title: 'My Blog Post',
memberId: 'author-member-id',
richContent: ricosContent,
media: {
wixMedia: {
image: { id: mediaId }
},
displayed: true,
custom: true
}
},
publish: true
});
Structure rich content using Ricos JSON format. Reference Ricos documentation for complete node structure. Common node types:
PARAGRAPH
for text contentHEADING
for section headers IMAGE
for embedded images (requires Wix Media ID)ORDERED_LIST
and BULLETED_LIST
for listsBLOCKQUOTE
for quoted textLIST_ITEM
for individual list itemsCRITICAL: All TEXT nodes MUST be wrapped in PARAGRAPH nodes within their parent containers.
const ricosContent = {
nodes: [
{
type: 'PARAGRAPH',
nodes: [{
type: 'TEXT',
textData: {
text: 'This is a paragraph with some content.',
decorations: []
}
}],
paragraphData: {}
}
]
};
Correct BLOCKQUOTE structure:
{
type: 'BLOCKQUOTE',
nodes: [
{
type: 'PARAGRAPH', // TEXT nodes must be in PARAGRAPH
nodes: [
{
type: 'TEXT',
textData: { text: 'Quote text here', decorations: [] }
}
],
paragraphData: {}
}
],
blockquoteData: { indentation: 1 }
}
Correct LIST_ITEM structure:
{
type: 'LIST_ITEM',
nodes: [
{
type: 'PARAGRAPH', // TEXT nodes must be in PARAGRAPH
nodes: [
{
type: 'TEXT',
textData: { text: 'List item text', decorations: [] }
}
],
paragraphData: {}
}
]
}
For embedded images in rich content, use IMAGE nodes with Wix Media IDs:
const imageNode = {
type: 'IMAGE',
nodes: [],
imageData: {
containerData: {
width: { size: 'CONTENT' },
alignment: 'CENTER'
},
image: {
src: { id: mediaId }, // Use imported media ID
width: 900,
height: 600
},
altText: 'Descriptive alt text'
}
};
Set publish: true
to immediately publish the post rather than saving as draft.
Resolve category IDs using List Categories (SDK | REST) if user provides category names.
Resolve tag IDs using Query Tags (SDK | REST) if user provides tag labels.
Include resolved IDs in categoryIds
and tagIds
arrays in the draft post object.
@wix/blog
and @wix/media
packages are in project dependencies@wix/blog
and @wix/media
packagesmemberId
is mandatory - use List Members API if needed to get member IDwix:image://v1/
prefix) for both cover images and embedded imageswidth
and height
properties in the image
object"operationStatus": "PENDING"
from import can be used immediately in blog postspublish: true
in the request to publish immediately rather than save as draftdraftPosts
arrayfieldsets: ['URL']
to get post URLs in the responsedisplayName
values during image import for better organization