Thinkmill / Thinkmill/keystatic
Trying to preview a componentBlock image in the editor
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 2.4k
- Forks
- 159
- Avg merge
- 21h 41m
- Merged PRs (30d)
- 2
Description
Hey, Im having a hard time figuring this one out!
I'm using Astro. I've created two component blocks that I want to use in blog posts: Youtube Videos, and images. I've been able to preview the youtube videos in my editor without issue, with the help of this video.
But for the life of me, I don't know how to render a preview of the image as well. I've changed my config file from TS to TSX, imported React, etc... and I just can't get a dang image to preview.
Digging through the KeyStatic Docs, I think this organization principle might be relevant...
Regardless of where the posts entries are created, the coverImage image will be generated in public/images/posts/{post-slug}.
My best guess is that, since images must be generated within the same folder as a post (I hope I'm wrong here -- am i?), then there's no way to preview the images since there's no way to dynamically generate the path to the image.
Please tell me I'm wrong. There simply must be a way to preview images within the document editor!
Here's the relevant code (keystatic.config.tsx)
// keystatic.config.tsx
import { config, fields, collection, component } from '@keystatic/core'
import React from 'react'
export default config({
storage: {
kind: 'local',
},
collections: {
posts: collection({
label: 'Posts',
slugField: 'title',
path: 'src/content/posts/*/',
format: { contentField: 'content' },
schema: {
title: fields.slug({ name: { label: 'Title' } }),
content: fields.document({
label: 'Content',
formatting: true,
links: true,
componentBlocks: {
youtubeVideo: component({
label: 'YouTube Video',
preview: ({ fields }) => (
<div style={{ padding: '1rem', backgroundColor: '#f9f9f9' }}>
{fields.youtubeVideoId.value ? (
<iframe
width='100%'
height='315'
src={`https://www.youtube.com/embed/${fields.youtubeVideoId.value}`}
frameBorder='0'
allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'
allowFullScreen
></iframe>
) : (
<p>Please enter a YouTube video ID</p>
)}
<h3>{fields.videoTitle.value}</h3>
<p>{fields.videoDescription.value}</p>
</div>
),
schema: {
youtubeVideoId: fields.text({ label: 'YouTube Video ID' }),
videoTitle: fields.text({ label: 'Video Title' }),
videoDescription: fields.text({ label: 'Video Description' }),
},
}),
astroImage: component({
label: 'Astro Image',
preview: ({ fields }) => {
const image = fields.imageSrc.value
const imageUrl = image
? `content/posts/{post.name}/content/${image.filename}`
: ''
return imageUrl ? (
<img
src={imageUrl}
alt={fields.imageAlt.value || 'Astro Image'}
title={fields.imageTitle.value}
style={{ maxWidth: '100%', height: 'auto' }}
/>
) : (
<p>Please select an image</p>
)
},
schema: {
imageSrc: fields.image({
label: 'Image Source',
directory: 'src/content/posts/*/content',
}),
imageTitle: fields.text({ label: 'Image Title' }),
imageAlt: fields.text({ label: 'Alt Text' }),
},
}),
},
}),
},
}),
},
})
I would appreciate any help very much, I simply must be wrong that this is not possible!
Thank you very much.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in keystatic.config.tsx at the astroImage component preview and its fields.imageSrc configuration. Trace how the selected image value and its filename are exposed to the preview, then verify the generated path against the collection path. Done means a selected image renders in the document editor preview, with the empty-state message still appearing when no image is selected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- content, frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100