Skip to content

Instantly share code, notes, and snippets.

@tomsseisums
Last active September 14, 2018 13:12
Show Gist options
  • Select an option

  • Save tomsseisums/659f720c3264cce20f7678b227946a61 to your computer and use it in GitHub Desktop.

Select an option

Save tomsseisums/659f720c3264cce20f7678b227946a61 to your computer and use it in GitHub Desktop.
Nethart GraphQL structure

What we are building here, is a simple homepage composed of pages of blocks.

Not a rich app, really "homepage" that may have various landing pages, has some navigation and bla bla, so... it's built around concept of "Pages", which in our case are defined by "Main" (section:main) section type.

It is somewhat against the Don't model your content for display ideology of Sanity, but in this case it makes sense. We hold data in various documents where they make sense as documents and otherwise structure our pages with "blocks".

In Craft we used the Matrix field type to make the Blocks.
Sanity is much more looser in that sense, we would simply have an array of all the "block" object types.

We'll probably go ham with custom preview components later on. :D
Also conditional widgets will come in handy!

The fragments define the "ribs" of our content - just DRYness/organizational thing.

There may be some naming inconsistencies, because our Junior is setting up the CMS (the beauty of headless CMS'es) and we haven't got to the normalization phase yet, still prototyping.

#
# A limited version of "Main" type.
#
fragment Nethart_CasesPageContentBlockFragment on Nethart_PageUnion {
...Nethart_PageHeroContentBlockFragment
...Nethart_PageEmployeesContentBlockFragment
...Nethart_PageQuotesContentBlockFragment
...Nethart_PageProcessContentBlockFragment
...Nethart_PageOurValuesContentBlockFragment
...Nethart_PageMultiColumnBlockContentBlockFragment
...Nethart_PageStatementsBlockFragment
...Nethart_PageGalleryBlockFragment
}
#
# Case block implementation.
#
fragment Nethart_CustomerBodyFragment on Nethart_EntryInterface {
... on Nethart_Customers {
slug
customerName
caseTitle
mainPicture {
url
width
height
}
mainDescription
contactUsText
contactUsLink {
entry {
uri
slug
__typename
}
target
url
type
customText
defaultText
}
page {
...Nethart_CasesPageContentBlockFragment
}
}
}
#
# For use when generating "Cases" pages.
#
fragment Nethart_PageCasesContentBlockFragment on Nethart_PageUnion {
... on Nethart_PageCases {
customer {
__typename
...Nethart_CustomerBodyFragment
}
}
}
#
# For use when generating "Main" pages.
#
fragment Nethart_FullPageContentBlockFragment on Nethart_PageUnion {
__typename
...Nethart_CasesPageContentBlockFragment
...Nethart_PageCasesContentBlockFragment
}
#
# In Sanity terms, this would simply be the Structured Text Block, I wanted to present such functionality
# to our content editors through CraftCMS.
# That's how much I love Sanity's approach, as you know it already!
#
fragment Nethart_PageHeroContentBlockFragment on Nethart_PageUnion {
... on Nethart_PageRichHero {
heroTitle
richDescription: description {
blocks {
__typename
... on Nethart_BlocksParagraph {
paragraph {
content
}
}
... on Nethart_BlocksLinkLine {
linkLine {
entry {
uri
slug
__typename
}
target
url
type
customText
defaultText
}
}
... on Nethart_BlocksPicture {
picture {
url
width
height
}
}
}
}
picture {
url
width
height
}
heroType
buttonLink {
entry {
uri
slug
__typename
}
target
url
type
customText
defaultText
}
}
}
#
# A wrapper block around "Employee" entry (document) type.
#
fragment Nethart_PageEmployeesContentBlockFragment on Nethart_PageUnion {
... on Nethart_PageEmployees {
employee {
... on Nethart_Employees {
subjectName
profilePicture {
url
width
height
}
subjectRole
phoneNumber {
url
}
eMail
}
}
}
}
#
# A wrapper block around "Quote" entry (document) type.
#
fragment Nethart_PageQuotesContentBlockFragment on Nethart_PageUnion {
... on Nethart_PageQuotes {
quotes: quote {
... on Nethart_Quotes {
authorName
picture {
url
width
height
}
mainQuote
subQuote
quoteType
}
}
}
}
#
# A block for the "Process Graphic" type.
#
fragment Nethart_PageProcessContentBlockFragment on Nethart_PageUnion {
... on Nethart_PageProcess {
process {
__typename
slug
...Nethart_ProcessSummaryGraphicFragment
...Nethart_ProcessDescriptiveGraphicFragment
}
}
}
#
# In Sanity, this would be an object block with array field of "Value Entry" object type.
#
fragment Nethart_PageOurValuesContentBlockFragment on Nethart_PageUnion {
... on Nethart_PageOurValues {
ourValue {
name: valueName
title: valueTitle
description: valueDescription {
content
}
pictures: valuePicture {
url
width
height
}
}
}
}
#
# Have yet to really think this through how this would get implemented in Sanity, but my idea
# is that we would have this as a wrapper around our main "Content" block. Array of "Content" blocks, so to speak.
#
fragment Nethart_PageMultiColumnBlockContentBlockFragment on Nethart_PageUnion {
... on Nethart_PageMultiColumnBlock {
title: blockTitle
columns: column {
title: columnTitle
text: columnText {
content
}
}
}
}
#
# In Sanity, object with array of "Statement" object type.
#
fragment Nethart_PageStatementsBlockFragment on Nethart_PageUnion {
... on Nethart_PageStatements {
statement {
title: statementTitle
message: statementDescription {
content
}
backgroundColor
}
}
}
#
# Have yet to think this through.
#
fragment Nethart_PageGalleryBlockFragment on Nethart_PageUnion {
... on Nethart_PageGallery {
galleryLine {
leftPicture {
url
}
rightPicture {
url
}
widthDistribution
}
}
}
#
# Process graphic is a crazy roundabout in Craft, we also used an "extra" plugin to limit reference selection.
# In Sanity we would have a different approach, maybe utilizing custom input components, have yet to lay it out.
# But Sanity gives loads of ways how to go about it and we will explore the most ... sane one.
#
fragment Nethart_ProcessSummaryGraphicFragment on Nethart_ProcessSummaryGraphicOnlyProcessSummary {
processStepGraphic {
... on Nethart_ProcessStepGraphicSuperTableBlockType {
name: processName
color
tasks {
... on Nethart_TasksTask {
title: taskTitle
}
}
fade
id
}
}
}
fragment Nethart_ProcessDescriptiveGraphicFragment on Nethart_ProcessSummaryMinimalGraphicWithDescriptionProcessSummary {
processSummary {
graphic {
__typename
slug
...Nethart_ProcessSummaryGraphicFragment
}
title: processTitle
description: processDescription {
content
}
callToAction {
entry {
__typename
uri
slug
... on Nethart_MainPage {
parent {
slug
}
}
}
target
url
type
customText
defaultText
}
}
}
#
# The query we use in Gatsby, to build our "pages".
# We ask for such minimum data, as this is just being used to set up the meta data, as upon creation
# of actual pages, the data is then sourced by the following query - PageContentQuery.
#
query PageCreationDataQuery {
nethart {
pages: entries(section: main, level: 1) {
slug
title
subpages: children {
slug
title
}
}
cases: entries(section: customers) {
slug
}
}
}
#
# This is where all the magic happens, all the blocks are being loaded here. This is the "Main" page.
# The catch here is that not always each of the page will have all of the block types assigned.
# That's the sole reason why [gatsby-source-sanity] wouldn't fit us, because it would generate
# schema only from the visible data, which beats the purpose..
#
query PageContentQuery ($slug: String) {
nethart {
page: entry(section:main, slug:$slug) {
id
pageTitle: title
slug
... on Nethart_MainPage {
lightNavigation
blocks {
...Nethart_FullPageContentBlockFragment
}
}
}
}
}
#
# As I said, limited version of "Main" page.
#
query CaseContentQuery ($slug: String) {
nethart {
case: entry(section:customers, slug:$slug) {
id
slug
...Nethart_CustomerBodyFragment
}
}
}
#
# We handle Homepage separately, because we treat it as "always there" kind of type.
# "Main" pages may not be defined, but Homepage should always be there. Yup, Singletons, I'm looking at you.
# (I said 10 days, we would hack around this for now.)
#
query HomepageContentQuery {
nethart {
page: entry (section:home) {
... on Nethart_Home {
lightNavigation
blocks {
...Nethart_FullPageContentBlockFragment
}
}
}
}
}
#
# Footer block is self-sufficient, that it queries it's own data from CraftCMS's Globals. Singletons would come
# in handy here, but we'll manage for now. :D
#
query FooterBlockContentQuery {
nethart {
globals {
footer {
followTitle: socialMediaCta
social: socialMediaLinks {
name: socialMediaName
url: socialMediaLink
}
slogan: companyName
copyrightDate
addressEntries: contactInfo {
text: contactText
type: contactTextType
}
}
}
}
}
#
# Same with Footer, Navigation queries it's own data and renders accordingly.
#
query NavigationMenuDataQuery {
nethart {
pages: entries(section: main, level: 1) {
pageType: __typename
slug
title
... on Nethart_MainPage {
hiddenFromMenu
}
... on Nethart_MainContainerPage {
subpages: children {
pageType: __typename
slug
title
... on Nethart_MainPage {
hiddenFromMenu
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment