Astro Starter Kit
Words are nice... but code speaks louder. Dive into a fully commented project template, showcasing these techniques (and more) in action.
Rich text in DatoCMS is stored in Structured Text fields, which lets us use it in many different contexts, from HTML in the browser to speech fulfillments in voice interfaces, if that's what you want.
There's a lot to be said about Structured Text and the extensibility of it, but for now let's just say that it returns content in a particular JSON format called dast
which will resemble this example:
{"schema": "dast","document": {"type": "root","children": [{"type": "heading","level": 1,"children": [{"type": "span","marks": [],"value": "Hello world!"}]}]}}
To make it easy to convert this format in HTML inside your Astro projects, we released a package called @datocms/astro
that exposes a <StructuredText />
component that does all the tedious work for you.
To take advantage of it, install the @datocms/astro
package if you haven't already:
yarn add @datocms/astro
Now let's make a GraphQL query to fetch a Structured Text field and feed the result to the data
prop of a <StructuredText />
component:
---// src/pages/index.astroimport { StructuredText } from '@datocms/astro';const query = `query HomeQuery {blogPost {titlecontent {value}}}`;const data = await executeQuery(query);---<StructuredText data={data.blogPost.content} />
Other than "regular" formatting nodes (paragraphs, lists, etc.), Structured Text documents can contain three special types of node:
itemLink
nodes are just like regular HTML hyperlinks, but point to other records instead of URLs;
inlineItem
nodes lets you directly embed a reference to a record in-between regular text;
block
nodes lets you embed a DatoCMS block record in-between regular paragraphs;
If a Structured Text document contains one of these nodes, then we need to change the GraphQL query, so that we also fetch all the records and blocks it references. As an example, if the field can link to other Blog posts, and can embed blocks of type "Image block", then the query should change like this:
const query = `query HomeQuery {blogPostfirst {idtitlecontent {valueblocks {... on RecordInterface {id__typename}... on ImageBlockRecord {image { url alt }}}links {... on RecordInterface {id__typename}... on BlogPostRecord {slugtitle}}}}}`;
You also need to instruct <StructuredText />
on how to display these nodes. This can be done by using the blockComponents
, inlineRecordComponents
, and linkToRecordComponents
props to specify the Astro component to render the node.
---// src/pages/index.astroimport { StructuredText } from '@datocms/svelte';import ImageBlock from '~/components/ImageBlock/index.astro';import InlineBlogPost from '~/components/InlineBlogPost/index.astro';import LinkToBlogPost from '~/components/LinkToBlogPost/index.astro';---<StructuredTextdata={blogPost.content}blockComponents={{ImageBlockRecord: ImageBlock,}}inlineRecordComponents={{BlogPostRecord: InlineBlogPost,}}linkToRecordComponents={{BlogPostRecord: LinkToBlogPost,}}/>
The following rules will apply:
Astro components passed in blockComponents
will be used to render blocks and will receive a block
prop containing the actual block data.
Astro components passed in inlineRecordComponents
will be used to render inline records and will receive a record
prop containing the actual record.
Astro components passed in linkToRecordComponents
will be used to render links to records and will receive the following props: node
(the actual 'inlineItem'
node), record
(the record linked to the node), and attrs
(the custom attributes for the link specified by the node).