JS Client Response don't have Image URL and how to display images in Remix (edited title)

Hello,

I am Newbie & exploring the Dato CMS how to use and what it offers and how it can fulfill my use-cases, and I am using REST API Client to get the list of Records available under my Project.

I’ve below Schema Model for my Project:

  • SEO and Social
  • Single-line String
  • Structured Text
  • Single Asset
  • Single-line String
  • Single-line String
  • Slug
  • Date
  • Single Link (References)

when I am using the above-shared JavaScript CMA Client, I am getting below response:

"project_display_image": {
   "alt": "dv-social-share",
   "title": "dv-social-share",
   "custom_data": {},
   "focal_point": null,
   "upload_id": "Rt7tzv0JRsOE-5LqfpPlyA"
},

where I am getting the ID of the Uploaded Image for this Single Asset and I am getting similar for SEO Meta which is as below:

"seo_details": {
   "image": "Rt7tzv0JRsOE-5LqfpPlyA",
   "title": "NPM dv-social-share",
   "no_index": false,
   "description": "dv-social-share is a powerful npm package for seamless social media sharing integration in Reactjs & Nextjs web app. Simplify sharing with ease!",
   "twitter_card": "summary_large_image"
},

here I am getting ID only, and I am thinking to use react-datocms, can anyone help me or guide me how to display this Image in my Remix Project?

hi @dhavalveera,

Welcome to DatoCMS!

Generally, for fetching content and images for your frontend, we recommend using our GraphQL Content Delivery API instead: Overview— Content Delivery API — DatoCMS

The GraphQL API seamlessly handles relationships between item types for you (such as records and images) and lets you fetch exactly the data you need in a single call. For example, to fetch an image alongside other record data: Images and videos— Content Delivery API — DatoCMS

If you’ve never used GraphQL before, we’d encourage you to check it out. There is a very slight learning curve (just an hour or two, I think?) but it’s very helpful for this use case of getting data from a CMS into your frontend.


While it’s possible to do something similar with the REST API as well, it would require several independent calls (such as listing records and then separately fetching their uploads) and then joining all of that back together clientside (typically by ID).


Does that help?

Hello @roger ,

Thanks for your quick help. I’ll look into GraphQL how to use it, and save my time with all this.

I want to ask is like after fetching the Data, how can I show that it to client? I mean in my Remix App, how do I display the content? for that I need to use react-datocms?

Well, that’s really up to you :slight_smile: That’s what makes this a “headless” system: it’s entirely up to you how the frontend displays this content. You can render it to raw HTML, or compose complex and beautiful JSX components, or use a UI toolkit like MUI or Chakra.

For a starting place, I suggest taking a look at our Remix Blog example: Remix example - Get started with Remix and DatoCMS — DatoCMS

And its source code here: GitHub - datocms/remix-example

But in general, it depends on your field type. For example, given a sample post model type, this is how it’s fetched and displayed on a page in our Remix example: remix-example/app/routes/posts/$slug.jsx at main · datocms/remix-example · GitHub

A single-line text field field type would return a simple string, which you could then render with something like:

        <h1 className="title">{post.title}</h1>

react-datocms is optional but helpful for rendering certain field types like Structured Text, images, and videos in a “best practices” kind of way. We recommend using it, but it’s really just a set of open-source React components that you can look at (GitHub - datocms/react-datocms: A set of components and utilities to work faster with DatoCMS in React environments) and fork/modify as necessary if it doesn’t meet your needs out of the box.

Some of our bigger customers also choose to implement their own components instead using ours, which is totally fine too if they need more control. But ours should get you a “good enough” implementation for most use cases.

Hello,

Thank you for quick reply,

I want to understand one thing, if I am using GraphQL to retrieve the Article, which will retrieve Article + Image associated with it, so it’ll be counted as only 1 Request or 2?

like in REST API, it’ll be multiple API Calls which will be more than 1 Request…

because 100k API calls each month are available under the Free Plan, so how it’ll be counted for both REST API & GraphQL?

Each network request you send to the CDA or CMA is one call. That’s one of the benefits of the GraphQL system: We handle the relationships on our side and you just get the data you need back, in one call. The CMA’s intended purpose is for record updates (it supports writes) and exports. For your frontend, the GraphQL is more suitable (it only supports reads, not mutations, but it will handle the relationships and embedded links and such better).

If you’re trying to stay under the free plan limits for a production site, it would be best to not call the API directly from user browsers (clientside), but to do some sort of server-side fetching & building into static pages. That way you’d only have to make API calls when something actually changes, not on every page load. Frameworks like Next should make that easy. At the very least, you can also do server-side rendering with caching (on a CDN) to at least limit the amount of requests that make it through to our API.

Hello @roger ,

I want to know one more thing that inside of Structured Text how can I add Images? like mostly one after another? because in grid it won’t be possible…

so is that possible to add multiple Images inside of Structured Text?

like if I tell more clearly so what I want is like, I want to show/display some text, like some heading, some p tags and some bullet points, then show the images (maybe 2 or 3 or maybe 4) and then again show the some texts again.

I want to achieve this, can you please guide or help me how can I do this with Dato CMS?

Hey @dhavalveera,

I’d probably use Blocks for this. A Block is a DatoCMS term for a repeatable set of fields that you can embed into Structured Text (and modular content fields. That way, you can make a Block with a single-asset (or gallery field), add additional layout information there if needed (as hints for your frontend, e.g. to tell it you want the images “side by side” or in a “mosaic” or “thumbnail gallery” or whatever).

That way, you’d get a JSON of those images along with your Structured Text, and then after that it’s up to your frontend how to display them.

Does that help? Please me know if you need a fuller example.

1 Like

Hello @roger ,

this give me little sense for my problem.

@roger Sorry to bother but can you please help me with fuller example? as am quite new to Dato CMS and still learning and exploring the potential of it… And Yes, I started a little and Yes it seems quite good.

Also, how can I render this Blocks into my FrontEnd with the use of react-datocms?

@dhavalveera, have you already seen the Remix example I provided above? Remix example - Get started with Remix and DatoCMS — DatoCMS

I also invited you to a sample project (please check your email) using that example.

Given a record like this:
https://forum-5121-remix-blog.admin.datocms.com/editor/item_types/538956/items/19072917 (you’ll have to accept the invitation to see it)

That gets rendered in Remix and react-datocms like this:

And the rendered output:

Basically, it breaks to something like this:

  • You build the schema in DatoCMS, making a block that contains an image
  • You edit the record’s structured text field, adding the image block and specifying the image within it
  • You fetch that record’s fields and blocks using our GraphQL Content Delivery API
  • You write Remix code, together with react-datocms’s component and a custom block renderer to deal with the image block

Please see that example repo for a more complete example.

We also have some intro videos that might help, like Intro to Blocks and Let’s Build Blocks. There’s more videos and written documentation on the docs page for them: Blocks — Content modelling — DatoCMS

For fetching structured text from GraphQL, here’s the docs page: Structured text fields — Content Delivery API — DatoCMS

Then from that point on, it’s up to your frontend (Remix and the example repo).


Can I ask if this is the kind of setup you were looking for? I’m just trying to make sure you’re not looking for something more WYSIWYG/no-code/low-code? DatoCMS is a “headless” CMS, so really, the primary thing we provide you is a JSON of your content. How you render that on the frontend is really up to you. Although we do provide JS helper libs for things like Structured Text, that’s just to assist in parsing them. Rendering the blocks in a particular way is still up to you and your frontend. The Remix example has a very basic example, but if you need more complex layouts than that, you’d either have to use a UI kit (like I mentioned earlier) or write your own CSS to lay them out a certain way.

At that point it’s not really about the CMS at all, but just your frontend (like how you’d display any image, whether from Dato or a local file). Does that make sense?

Thank You @roger for the example.

Yes, I do have checked the Remix Example (GitHub) you’ve shared, and based on that only I’m able to give it a shoot and started with it and created Records and populated over there… I just made a little change is that I’ve used fetch() here to get the Records from Dato CMS.

Furthermore, I just accepted the invitation to the sample project you’ve shared to me, and in that I just tried to play with the GraphQL Query for Blocks, but in that I am not getting record.__typename: "ImageBlockRecord, or it’ll be taken care by react-datocms’s StructuredText ?

Furthermore, suppose in 1st Image Block I’ve 3-4 Images, how can I identify that it’s a Single Image or Multiple Image together?

Furthermore, I just accepted the invitation to the sample project you’ve shared to me, and in that I just tried to play with the GraphQL Query for Blocks, but in that I am not getting record.__typename: "ImageBlockRecord , or it’ll be taken care by react-datocms ’s StructuredText ?

I’m not totally sure I understand the question, sorry? In GraphQL, you can either query for the __typename or the modelApiKey (different representations of the same thing):

Then from there you have to tell the frontend how to render it using the custom block renderer.

Furthermore, suppose in 1st Image Block I’ve 3-4 Images, how can I identify that it’s a Single Image or Multiple Image together?

That depends on your schema. If your block only accepts a single image, it will be just that image. You can have multiple blocks one after another, each for one image.

If your block contains a gallery field (for multiple assets) then they’ll be an array.

In either case, you’ll have to adjust the frontend to accommodate that.

Hello @roger ,

Thanks for your response, and Sorry for late reply.

I am stuck into something, so didn’t able to check the solution you’ve shared with me… I’ll check it ASAP.

I’ve one more question which is, in Dato CMS with GraphQL is there any way I can get Previous & Next Article/Record?

Yes, but depending on your use case, it might be better (for the user) to do this clientside.

To do it at the API level, please see Pagination: Pagination — Content Delivery API — DatoCMS

Basically, to fetch record #1, you’d say first: 1, skip: 0, to fetch the 2nd record it’d be first: 1, skip 1, etc. You just keep track of which record you’re currently on and then skip however many you want.

But in many cases (like going prev/next between blog posts) it may be better to let your frontend router handle that instead, fetching all possible article IDs ahead of time and then passing them to a router so the next/prev links can be hardcoded. That way your users can just directly navigate to the next article instead of waiting for you to do an API lookup.

Hello @roger ,

Sorry for being ghosted in between, I need your one more help on this.

I am using fetch() to get the Project Data using GraphQL Query, and below is my method to achieve it:

const graphQLFetchHeaders = {
  "Content-Type": "application/json",
  Accept: "application/json",
  Authorization: `Bearer ${token}`,
};

const resp = await fetch("https://graphql.datocms.com/", {
      method: "POST",
      headers: graphQLFetchHeaders,
      body: JSON.stringify({ query: getAllDatoCMSProjectsGraphQLQuery }),
    });

    const data = await resp.json();

    return { datoCMSProject: data.data.allProjects };

in the above fetch() body — getAllDatoCMSProjectsGraphQLQuery this is the GraphQL Query I am generating from the DatoCMS CDA Playground.

Now I need help with getting the type/interface for the Response I am getting.

Furthermore, content in react-datocms’s StructuredText → data have defined below type/interface:

(property) data: Document | Node | StructuredText<Record, Record> | null | undefined
The actual field value you get from DatoCMS *

how can I get all the correct type/interface for the Response I am getting using fetch(), can you please help & guide me through??

Hey @dhavalveera,

You can generally get your own project’s GraphQL types using our generators: How To Generate TypeScript Types From GraphQL — DatoCMS

For Structured Text in particular, though, we don’t recommend that you manually parse it. Instead, we offer the helper lib that can handle the parsing and rendering for you: react-datocms/docs/structured-text.md at master · datocms/react-datocms · GitHub

Does that help at all?

Hey @roger ,

Unfortunately the Link you shared for generating the TypeScript Types from GraphQL, doesn’t seems to work as expected and the way I am looking…

more specifically I am getting types error when I am running the loop on the Array, and that time either I need to define any or the proper types for it… For other fields like title, date, slug I can define the type as string correctly, but when it comes for the StructuredText data, block, I am getting the error for type/interface.

@dhavalveera,

Sorry, it is difficult to replicate & debug this from these code snippets. Might it be possible for you to share your repo with us (r.tuan@datocms.com on Github) or make a separate minimal example for us?

Otherwise, you might be able to import the StructuredText types directly from our libs (possibly one of these react-datocms/src/StructuredText/index.tsx at master · datocms/react-datocms · GitHub). But unless you are doing some parsing on your own, I don’t know that it would get you anything over just marking them as any and using our lib to render them into HTML directly. (i.e. if you are trying to validate our response shape, you are redoing work that our internal libs should already be doing).

The TypeScirpt won’t get you runtime/fetch time response type validation anyway… so if I’m understanding your use case here, maybe what you need instead is a simple try/catch block that makes sure the GraphQL response was successful, and that the resulting data block is valid and not empty? It’s just a sanity check, not a full type check, but it should be fine?

What I’m saying is that it’s OK to just treat our structured text as a generic blob you don’t have to worry about typing individually, and you can use our renderer to override specific node rendering if you need to.

Does that help at all? Otherwise, can you please share a repo with us so we can take a deeper look at your specific use case?

Hey @roger ,

that GitHub Link you shared regarding the type/interface that worked for me.

Actually I use the fetch() to get to Query the GraphQL, and when I am passing the response like data.datoCMSProject.value to Structured Text it was throwing error for any or unknown something and to resolve it I was needed the correct type for it to resolve it, TypesafeStructuredTextGraphQlResponse this resolved my problem.

Thanks

1 Like